Skip to content

Commit

Permalink
scst.h, scst, device handlers: Fix scst_replace_port_info
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
bmeagherix committed Jan 20, 2024
1 parent 34a44cd commit 31b7728
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 6 deletions.
9 changes: 9 additions & 0 deletions scst/include/scst.h
Original file line number Diff line number Diff line change
Expand Up @@ -2315,6 +2315,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];
Expand Down Expand Up @@ -4520,6 +4522,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
Expand Down
9 changes: 9 additions & 0 deletions scst/src/dev_handlers/scst_disk.c
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
11 changes: 5 additions & 6 deletions scst/src/scst_targ.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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];

Expand All @@ -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;
}
}
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 31b7728

Please sign in to comment.