From: Gleb C. <lna...@ya...> - 2024-01-12 07:50:46
|
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); |