Skip to content

Commit 67ff377

Browse files
committed
Merge tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull SCSI fixes from James Bottomley: "Four driver fixes and one core fix. The core fix closes a race window where we could kick off a second asynchronous scan because the test and set of the variable preventing it isn't atomic" * tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: scsi: hisi_sas: Stop using queue #0 always for v2 hw scsi: ibmvscsi: Fix potential race after loss of transport scsi: mptfusion: Fix null pointer dereferences in mptscsih_remove() scsi: qla2xxx: Return EBUSY on fcport deletion scsi: core: Don't start concurrent async scan on same host
2 parents 5fc6b07 + fab09aa commit 67ff377

5 files changed

Lines changed: 43 additions & 21 deletions

File tree

drivers/message/fusion/mptscsih.c

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,8 +1176,10 @@ mptscsih_remove(struct pci_dev *pdev)
11761176
MPT_SCSI_HOST *hd;
11771177
int sz1;
11781178

1179-
if((hd = shost_priv(host)) == NULL)
1180-
return;
1179+
if (host == NULL)
1180+
hd = NULL;
1181+
else
1182+
hd = shost_priv(host);
11811183

11821184
mptscsih_shutdown(pdev);
11831185

@@ -1193,14 +1195,15 @@ mptscsih_remove(struct pci_dev *pdev)
11931195
"Free'd ScsiLookup (%d) memory\n",
11941196
ioc->name, sz1));
11951197

1196-
kfree(hd->info_kbuf);
1198+
if (hd)
1199+
kfree(hd->info_kbuf);
11971200

11981201
/* NULL the Scsi_Host pointer
11991202
*/
12001203
ioc->sh = NULL;
12011204

1202-
scsi_host_put(host);
1203-
1205+
if (host)
1206+
scsi_host_put(host);
12041207
mpt_detach(pdev);
12051208

12061209
}

drivers/scsi/hisi_sas/hisi_sas_main.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@ static int hisi_sas_task_prep(struct sas_task *task,
445445
}
446446
}
447447

448-
if (scmd) {
448+
if (scmd && hisi_hba->shost->nr_hw_queues) {
449449
unsigned int dq_index;
450450
u32 blk_tag;
451451

drivers/scsi/ibmvscsi/ibmvscsi.c

Lines changed: 26 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -806,14 +806,30 @@ static void purge_requests(struct ibmvscsi_host_data *hostdata, int error_code)
806806
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
807807
}
808808

809+
/**
810+
* ibmvscsi_set_request_limit - Set the adapter request_limit in response to
811+
* an adapter failure, reset, or SRP Login. Done under host lock to prevent
812+
* race with SCSI command submission.
813+
* @hostdata: adapter to adjust
814+
* @limit: new request limit
815+
*/
816+
static void ibmvscsi_set_request_limit(struct ibmvscsi_host_data *hostdata, int limit)
817+
{
818+
unsigned long flags;
819+
820+
spin_lock_irqsave(hostdata->host->host_lock, flags);
821+
atomic_set(&hostdata->request_limit, limit);
822+
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
823+
}
824+
809825
/**
810826
* ibmvscsi_reset_host - Reset the connection to the server
811827
* @hostdata: struct ibmvscsi_host_data to reset
812828
*/
813829
static void ibmvscsi_reset_host(struct ibmvscsi_host_data *hostdata)
814830
{
815831
scsi_block_requests(hostdata->host);
816-
atomic_set(&hostdata->request_limit, 0);
832+
ibmvscsi_set_request_limit(hostdata, 0);
817833

818834
purge_requests(hostdata, DID_ERROR);
819835
hostdata->action = IBMVSCSI_HOST_ACTION_RESET;
@@ -1146,13 +1162,13 @@ static void login_rsp(struct srp_event_struct *evt_struct)
11461162
dev_info(hostdata->dev, "SRP_LOGIN_REJ reason %u\n",
11471163
evt_struct->xfer_iu->srp.login_rej.reason);
11481164
/* Login failed. */
1149-
atomic_set(&hostdata->request_limit, -1);
1165+
ibmvscsi_set_request_limit(hostdata, -1);
11501166
return;
11511167
default:
11521168
dev_err(hostdata->dev, "Invalid login response typecode 0x%02x!\n",
11531169
evt_struct->xfer_iu->srp.login_rsp.opcode);
11541170
/* Login failed. */
1155-
atomic_set(&hostdata->request_limit, -1);
1171+
ibmvscsi_set_request_limit(hostdata, -1);
11561172
return;
11571173
}
11581174

@@ -1163,7 +1179,7 @@ static void login_rsp(struct srp_event_struct *evt_struct)
11631179
* This value is set rather than added to request_limit because
11641180
* request_limit could have been set to -1 by this client.
11651181
*/
1166-
atomic_set(&hostdata->request_limit,
1182+
ibmvscsi_set_request_limit(hostdata,
11671183
be32_to_cpu(evt_struct->xfer_iu->srp.login_rsp.req_lim_delta));
11681184

11691185
/* If we had any pending I/Os, kick them */
@@ -1195,13 +1211,13 @@ static int send_srp_login(struct ibmvscsi_host_data *hostdata)
11951211
login->req_buf_fmt = cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
11961212
SRP_BUF_FORMAT_INDIRECT);
11971213

1198-
spin_lock_irqsave(hostdata->host->host_lock, flags);
11991214
/* Start out with a request limit of 0, since this is negotiated in
12001215
* the login request we are just sending and login requests always
12011216
* get sent by the driver regardless of request_limit.
12021217
*/
1203-
atomic_set(&hostdata->request_limit, 0);
1218+
ibmvscsi_set_request_limit(hostdata, 0);
12041219

1220+
spin_lock_irqsave(hostdata->host->host_lock, flags);
12051221
rc = ibmvscsi_send_srp_event(evt_struct, hostdata, login_timeout * 2);
12061222
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
12071223
dev_info(hostdata->dev, "sent SRP login\n");
@@ -1781,7 +1797,7 @@ static void ibmvscsi_handle_crq(struct viosrp_crq *crq,
17811797
return;
17821798
case VIOSRP_CRQ_XPORT_EVENT: /* Hypervisor telling us the connection is closed */
17831799
scsi_block_requests(hostdata->host);
1784-
atomic_set(&hostdata->request_limit, 0);
1800+
ibmvscsi_set_request_limit(hostdata, 0);
17851801
if (crq->format == 0x06) {
17861802
/* We need to re-setup the interpartition connection */
17871803
dev_info(hostdata->dev, "Re-enabling adapter!\n");
@@ -2137,12 +2153,12 @@ static void ibmvscsi_do_work(struct ibmvscsi_host_data *hostdata)
21372153
}
21382154

21392155
hostdata->action = IBMVSCSI_HOST_ACTION_NONE;
2156+
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
21402157

21412158
if (rc) {
2142-
atomic_set(&hostdata->request_limit, -1);
2159+
ibmvscsi_set_request_limit(hostdata, -1);
21432160
dev_err(hostdata->dev, "error after %s\n", action);
21442161
}
2145-
spin_unlock_irqrestore(hostdata->host->host_lock, flags);
21462162

21472163
scsi_unblock_requests(hostdata->host);
21482164
}
@@ -2226,7 +2242,7 @@ static int ibmvscsi_probe(struct vio_dev *vdev, const struct vio_device_id *id)
22262242
init_waitqueue_head(&hostdata->work_wait_q);
22272243
hostdata->host = host;
22282244
hostdata->dev = dev;
2229-
atomic_set(&hostdata->request_limit, -1);
2245+
ibmvscsi_set_request_limit(hostdata, -1);
22302246
hostdata->host->max_sectors = IBMVSCSI_MAX_SECTORS_DEFAULT;
22312247

22322248
if (map_persist_bufs(hostdata)) {

drivers/scsi/qla2xxx/qla_nvme.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -554,10 +554,12 @@ static int qla_nvme_post_cmd(struct nvme_fc_local_port *lport,
554554

555555
fcport = qla_rport->fcport;
556556

557-
if (!qpair || !fcport || (qpair && !qpair->fw_started) ||
558-
(fcport && fcport->deleted))
557+
if (!qpair || !fcport)
559558
return -ENODEV;
560559

560+
if (!qpair->fw_started || fcport->deleted)
561+
return -EBUSY;
562+
561563
vha = fcport->vha;
562564

563565
if (!(fcport->nvme_flag & NVME_FLAG_REGISTERED))

drivers/scsi/scsi_scan.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1714,15 +1714,16 @@ static void scsi_sysfs_add_devices(struct Scsi_Host *shost)
17141714
*/
17151715
static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
17161716
{
1717-
struct async_scan_data *data;
1717+
struct async_scan_data *data = NULL;
17181718
unsigned long flags;
17191719

17201720
if (strncmp(scsi_scan_type, "sync", 4) == 0)
17211721
return NULL;
17221722

1723+
mutex_lock(&shost->scan_mutex);
17231724
if (shost->async_scan) {
17241725
shost_printk(KERN_DEBUG, shost, "%s called twice\n", __func__);
1725-
return NULL;
1726+
goto err;
17261727
}
17271728

17281729
data = kmalloc(sizeof(*data), GFP_KERNEL);
@@ -1733,7 +1734,6 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
17331734
goto err;
17341735
init_completion(&data->prev_finished);
17351736

1736-
mutex_lock(&shost->scan_mutex);
17371737
spin_lock_irqsave(shost->host_lock, flags);
17381738
shost->async_scan = 1;
17391739
spin_unlock_irqrestore(shost->host_lock, flags);
@@ -1748,6 +1748,7 @@ static struct async_scan_data *scsi_prep_async_scan(struct Scsi_Host *shost)
17481748
return data;
17491749

17501750
err:
1751+
mutex_unlock(&shost->scan_mutex);
17511752
kfree(data);
17521753
return NULL;
17531754
}

0 commit comments

Comments
 (0)