Commit: df039cb
GitHub URL: https://github.com/SCST-project/scst/commit/df039cb3e9f549fde3079849f19e5b34186de701
Author: Brian Meagher
Date: 2024-01-12T10:50:15+03:00
Log Message:
-----------
scst.h, scst, device handlers: Fix scst_replace_port_info
scst_pass_through_cmd_done can run in interrupt context, and call
scst_replace_port_info, which in turn was calling scst_lookup_tg_id.
Since scst_lookup_tg_id does a mutex_lock, we should not call it from
interrupt context.
Add scst_cmd_inquired_dev_ident and use in various locations.
Modified Paths:
--------------
scst/include/scst.h | 9 +++++++++
scst/src/dev_handlers/scst_disk.c | 9 +++++++++
scst/src/scst_targ.c | 11 +++++------
3 files changed, 23 insertions(+), 6 deletions(-)
===================================================================
diff --git a/scst/include/scst.h b/scst/include/scst.h
index 781aabb..2e5aa57 100644
--- a/scst/include/scst.h
+++ b/scst/include/scst.h
@@ -2318,6 +2318,8 @@ struct scst_cmd {
uint32_t tgt_sn; /* SN set by target driver (for TM purposes) */
+ uint16_t tg_id; /* Only used during TYPE_DISK INQUIRY EVPD=0x83 */
+
uint8_t *cdb; /* Pointer on CDB. Points on cdb_buf for small CDBs. */
unsigned short cdb_len;
uint8_t cdb_buf[SCST_MAX_CDB_SIZE];
@@ -4524,6 +4526,13 @@ static inline bool scst_get_cmd_dev_d_sense(struct scst_cmd *cmd)
return (cmd->dev != NULL) ? cmd->dev->d_sense : 0;
}
+/* Returns if command is INQUIRY EVPD=0x83 (device identification) */
+static inline bool scst_cmd_inquired_dev_ident(struct scst_cmd *cmd)
+{
+ return (cmd->cdb[0] == INQUIRY) && ((cmd->cdb[1] & 0x01/*EVPD*/) == 0x01) &&
+ (cmd->cdb[2] == 0x83/*device identification*/);
+}
+
/*
* Get/Set functions for expected data direction, transfer length
* and its validity flag
diff --git a/scst/src/dev_handlers/scst_disk.c b/scst/src/dev_handlers/scst_disk.c
index 341a05a..df2f436 100644
--- a/scst/src/dev_handlers/scst_disk.c
+++ b/scst/src/dev_handlers/scst_disk.c
@@ -374,6 +374,15 @@ static enum scst_exec_res disk_exec(struct scst_cmd *cmd)
}
}
+ /*
+ * If we are passing thru a INQUIRY VPD=0x83 (device identification) then
+ * we will call scst_replace_port_info on success in scst_pass_through_cmd_done.
+ * This will run in interrupt context, so we should not perform operations that
+ * involve mutexes. Call scst_lookup_tg_id here intead and save the output.
+ */
+ if (unlikely(scst_cmd_inquired_dev_ident(cmd)))
+ cmd->tg_id = scst_lookup_tg_id(dev, tgt);
+
/*
* For PC requests we are going to submit max_hw_sectors used instead
* of max_sectors.
diff --git a/scst/src/scst_targ.c b/scst/src/scst_targ.c
index a325e7b..fa4afb2 100644
--- a/scst/src/scst_targ.c
+++ b/scst/src/scst_targ.c
@@ -2227,8 +2227,7 @@ static void scst_replace_port_info(struct scst_cmd *cmd)
uint8_t *buf, *end, *p, designator_length;
int32_t length, page_length;
- if (cmd->cdb[0] != INQUIRY || (cmd->cdb[1] & 0x01/*EVPD*/) == 0 ||
- cmd->cdb[2] != 0x83/*device identification*/)
+ if (!scst_cmd_inquired_dev_ident(cmd))
return;
length = scst_get_buf_full_sense(cmd, &buf);
@@ -2242,7 +2241,6 @@ static void scst_replace_port_info(struct scst_cmd *cmd)
const uint8_t code_set = p[0] & 0xf;
const uint8_t association = (p[1] & 0x30) >> 4;
const uint8_t designator_type = p[1] & 0xf;
- uint16_t tg_id;
designator_length = p[3];
@@ -2259,9 +2257,7 @@ static void scst_replace_port_info(struct scst_cmd *cmd)
break;
case 5:
/* target port group */
- tg_id = scst_lookup_tg_id(cmd->dev, cmd->tgt);
- if (tg_id)
- put_unaligned_be16(tg_id, p + 6);
+ put_unaligned_be16(cmd->tg_id, p + 6);
break;
}
}
@@ -2622,6 +2618,9 @@ static enum scst_exec_res scst_do_real_exec(struct scst_cmd *cmd)
scsi_dev->host->host_no, scsi_dev->channel, scsi_dev->id,
(u64)scsi_dev->lun);
+ if (unlikely(scst_cmd_inquired_dev_ident(cmd)))
+ cmd->tg_id = scst_lookup_tg_id(dev, cmd->tgt);
+
rc = scst_scsi_exec_async(cmd, cmd, scst_pass_through_cmd_done);
if (unlikely(rc != 0)) {
PRINT_ERROR("scst pass-through exec failed: %d", rc);
|