mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-14 09:11:27 +00:00
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.
This commit is contained in:
committed by
Gleb Chesnokov
parent
7baf286609
commit
df039cb3e9
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user