Skip to content

Commit e8cfe8f

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: "Seven fixes, all in drivers (qla2xxx, mkt3sas, qedi, target, ibmvscsi). The most serious are the target pscsi oom and the qla2xxx revert which can otherwise cause a use after free" * tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: scsi: target: pscsi: Clean up after failure in pscsi_map_sg() scsi: target: pscsi: Avoid OOM in pscsi_map_sg() scsi: mpt3sas: Fix error return code of mpt3sas_base_attach() scsi: qedi: Fix error return code of qedi_alloc_global_queues() scsi: Revert "qla2xxx: Make sure that aborted commands are freed" scsi: ibmvfc: Make ibmvfc_wait_for_ops() MQ aware scsi: ibmvfc: Fix potential race in ibmvfc_wait_for_ops()
2 parents 0f4498c + 36fa766 commit e8cfe8f

File tree

6 files changed

+74
-28
lines changed

6 files changed

+74
-28
lines changed

drivers/scsi/ibmvscsi/ibmvfc.c

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2371,6 +2371,24 @@ static int ibmvfc_match_lun(struct ibmvfc_event *evt, void *device)
23712371
return 0;
23722372
}
23732373

2374+
/**
2375+
* ibmvfc_event_is_free - Check if event is free or not
2376+
* @evt: ibmvfc event struct
2377+
*
2378+
* Returns:
2379+
* true / false
2380+
**/
2381+
static bool ibmvfc_event_is_free(struct ibmvfc_event *evt)
2382+
{
2383+
struct ibmvfc_event *loop_evt;
2384+
2385+
list_for_each_entry(loop_evt, &evt->queue->free, queue_list)
2386+
if (loop_evt == evt)
2387+
return true;
2388+
2389+
return false;
2390+
}
2391+
23742392
/**
23752393
* ibmvfc_wait_for_ops - Wait for ops to complete
23762394
* @vhost: ibmvfc host struct
@@ -2385,35 +2403,58 @@ static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device,
23852403
{
23862404
struct ibmvfc_event *evt;
23872405
DECLARE_COMPLETION_ONSTACK(comp);
2388-
int wait;
2406+
int wait, i, q_index, q_size;
23892407
unsigned long flags;
23902408
signed long timeout = IBMVFC_ABORT_WAIT_TIMEOUT * HZ;
2409+
struct ibmvfc_queue *queues;
23912410

23922411
ENTER;
2412+
if (vhost->mq_enabled && vhost->using_channels) {
2413+
queues = vhost->scsi_scrqs.scrqs;
2414+
q_size = vhost->scsi_scrqs.active_queues;
2415+
} else {
2416+
queues = &vhost->crq;
2417+
q_size = 1;
2418+
}
2419+
23932420
do {
23942421
wait = 0;
2395-
spin_lock_irqsave(&vhost->crq.l_lock, flags);
2396-
list_for_each_entry(evt, &vhost->crq.sent, queue_list) {
2397-
if (match(evt, device)) {
2398-
evt->eh_comp = ∁
2399-
wait++;
2422+
spin_lock_irqsave(vhost->host->host_lock, flags);
2423+
for (q_index = 0; q_index < q_size; q_index++) {
2424+
spin_lock(&queues[q_index].l_lock);
2425+
for (i = 0; i < queues[q_index].evt_pool.size; i++) {
2426+
evt = &queues[q_index].evt_pool.events[i];
2427+
if (!ibmvfc_event_is_free(evt)) {
2428+
if (match(evt, device)) {
2429+
evt->eh_comp = &comp;
2430+
wait++;
2431+
}
2432+
}
24002433
}
2434+
spin_unlock(&queues[q_index].l_lock);
24012435
}
2402-
spin_unlock_irqrestore(&vhost->crq.l_lock, flags);
2436+
spin_unlock_irqrestore(vhost->host->host_lock, flags);
24032437

24042438
if (wait) {
24052439
timeout = wait_for_completion_timeout(&comp, timeout);
24062440

24072441
if (!timeout) {
24082442
wait = 0;
2409-
spin_lock_irqsave(&vhost->crq.l_lock, flags);
2410-
list_for_each_entry(evt, &vhost->crq.sent, queue_list) {
2411-
if (match(evt, device)) {
2412-
evt->eh_comp = NULL;
2413-
wait++;
2443+
spin_lock_irqsave(vhost->host->host_lock, flags);
2444+
for (q_index = 0; q_index < q_size; q_index++) {
2445+
spin_lock(&queues[q_index].l_lock);
2446+
for (i = 0; i < queues[q_index].evt_pool.size; i++) {
2447+
evt = &queues[q_index].evt_pool.events[i];
2448+
if (!ibmvfc_event_is_free(evt)) {
2449+
if (match(evt, device)) {
2450+
evt->eh_comp = NULL;
2451+
wait++;
2452+
}
2453+
}
24142454
}
2455+
spin_unlock(&queues[q_index].l_lock);
24152456
}
2416-
spin_unlock_irqrestore(&vhost->crq.l_lock, flags);
2457+
spin_unlock_irqrestore(vhost->host->host_lock, flags);
24172458
if (wait)
24182459
dev_err(vhost->dev, "Timed out waiting for aborted commands\n");
24192460
LEAVE;

drivers/scsi/mpt3sas/mpt3sas_base.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7806,14 +7806,18 @@ mpt3sas_base_attach(struct MPT3SAS_ADAPTER *ioc)
78067806
ioc->pend_os_device_add_sz++;
78077807
ioc->pend_os_device_add = kzalloc(ioc->pend_os_device_add_sz,
78087808
GFP_KERNEL);
7809-
if (!ioc->pend_os_device_add)
7809+
if (!ioc->pend_os_device_add) {
7810+
r = -ENOMEM;
78107811
goto out_free_resources;
7812+
}
78117813

78127814
ioc->device_remove_in_progress_sz = ioc->pend_os_device_add_sz;
78137815
ioc->device_remove_in_progress =
78147816
kzalloc(ioc->device_remove_in_progress_sz, GFP_KERNEL);
7815-
if (!ioc->device_remove_in_progress)
7817+
if (!ioc->device_remove_in_progress) {
7818+
r = -ENOMEM;
78167819
goto out_free_resources;
7820+
}
78177821

78187822
ioc->fwfault_debug = mpt3sas_fwfault_debug;
78197823

drivers/scsi/qedi/qedi_main.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1675,6 +1675,7 @@ static int qedi_alloc_global_queues(struct qedi_ctx *qedi)
16751675
if (!qedi->global_queues[i]) {
16761676
QEDI_ERR(&qedi->dbg_ctx,
16771677
"Unable to allocation global queue %d.\n", i);
1678+
status = -ENOMEM;
16781679
goto mem_alloc_failure;
16791680
}
16801681

drivers/scsi/qla2xxx/qla_target.c

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3222,8 +3222,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
32223222
if (!qpair->fw_started || (cmd->reset_count != qpair->chip_reset) ||
32233223
(cmd->sess && cmd->sess->deleted)) {
32243224
cmd->state = QLA_TGT_STATE_PROCESSED;
3225-
res = 0;
3226-
goto free;
3225+
return 0;
32273226
}
32283227

32293228
ql_dbg_qp(ql_dbg_tgt, qpair, 0xe018,
@@ -3234,8 +3233,9 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
32343233

32353234
res = qlt_pre_xmit_response(cmd, &prm, xmit_type, scsi_status,
32363235
&full_req_cnt);
3237-
if (unlikely(res != 0))
3238-
goto free;
3236+
if (unlikely(res != 0)) {
3237+
return res;
3238+
}
32393239

32403240
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
32413241

@@ -3255,8 +3255,7 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
32553255
vha->flags.online, qla2x00_reset_active(vha),
32563256
cmd->reset_count, qpair->chip_reset);
32573257
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
3258-
res = 0;
3259-
goto free;
3258+
return 0;
32603259
}
32613260

32623261
/* Does F/W have an IOCBs for this request */
@@ -3359,8 +3358,6 @@ int qlt_xmit_response(struct qla_tgt_cmd *cmd, int xmit_type,
33593358
qlt_unmap_sg(vha, cmd);
33603359
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
33613360

3362-
free:
3363-
vha->hw->tgt.tgt_ops->free_cmd(cmd);
33643361
return res;
33653362
}
33663363
EXPORT_SYMBOL(qlt_xmit_response);

drivers/scsi/qla2xxx/tcm_qla2xxx.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -644,7 +644,6 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
644644
{
645645
struct qla_tgt_cmd *cmd = container_of(se_cmd,
646646
struct qla_tgt_cmd, se_cmd);
647-
struct scsi_qla_host *vha = cmd->vha;
648647

649648
if (cmd->aborted) {
650649
/* Cmd can loop during Q-full. tcm_qla2xxx_aborted_task
@@ -657,7 +656,6 @@ static int tcm_qla2xxx_queue_data_in(struct se_cmd *se_cmd)
657656
cmd->se_cmd.transport_state,
658657
cmd->se_cmd.t_state,
659658
cmd->se_cmd.se_cmd_flags);
660-
vha->hw->tgt.tgt_ops->free_cmd(cmd);
661659
return 0;
662660
}
663661

@@ -685,7 +683,6 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
685683
{
686684
struct qla_tgt_cmd *cmd = container_of(se_cmd,
687685
struct qla_tgt_cmd, se_cmd);
688-
struct scsi_qla_host *vha = cmd->vha;
689686
int xmit_type = QLA_TGT_XMIT_STATUS;
690687

691688
if (cmd->aborted) {
@@ -699,7 +696,6 @@ static int tcm_qla2xxx_queue_status(struct se_cmd *se_cmd)
699696
cmd, kref_read(&cmd->se_cmd.cmd_kref),
700697
cmd->se_cmd.transport_state, cmd->se_cmd.t_state,
701698
cmd->se_cmd.se_cmd_flags);
702-
vha->hw->tgt.tgt_ops->free_cmd(cmd);
703699
return 0;
704700
}
705701
cmd->bufflen = se_cmd->data_length;

drivers/target/target_core_pscsi.c

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,6 @@ pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
882882
if (!bio) {
883883
new_bio:
884884
nr_vecs = bio_max_segs(nr_pages);
885-
nr_pages -= nr_vecs;
886885
/*
887886
* Calls bio_kmalloc() and sets bio->bi_end_io()
888887
*/
@@ -939,6 +938,14 @@ pscsi_map_sg(struct se_cmd *cmd, struct scatterlist *sgl, u32 sgl_nents,
939938

940939
return 0;
941940
fail:
941+
if (bio)
942+
bio_put(bio);
943+
while (req->bio) {
944+
bio = req->bio;
945+
req->bio = bio->bi_next;
946+
bio_put(bio);
947+
}
948+
req->biotail = NULL;
942949
return TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
943950
}
944951

0 commit comments

Comments
 (0)