Skip to content

Commit f2ec631

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: "The biggest core change is the reliable wake fix for scsi_schedule_eh which is used by both libata and libsas which could otherwise cause error handler hangs due to rare races. All other fixes are in drivers (well except the export symbol removal) the next biggest being the target PR-OUT transportid parsing fix" * tag 'scsi-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: scsi: hpsa: Fix DMA mapping leak on IOACCEL2 reset path scsi: elx: efct: Fix refcount leak in efct_hw_io_abort() scsi: elx: efct: Fix I/O leak on unsupported additional CDB scsi: core: wake eh reliably when using scsi_schedule_eh scsi: target: core: Fix iSCSI ISID use-after-free in REGISTER AND MOVE scsi: target: Bound PR-OUT TransportID parsing to the received buffer scsi: lpfc: Fix memory leak in lpfc_sli4_driver_resource_setup() scsi: sg: Report request-table problems when any status is set scsi: ufs: core: tracing: Do not dereference pointers in TP_printk() scsi: bfa: Reduce kernel stack usage in bfa_fcs_lport_fdmi_build_portattr_block() scsi: xen: scsiback: Free the command tag on the TMR submit-failure path scsi: xen: scsiback: Free unsubmitted command instead of double-putting it scsi: core: Remove export for scsi_device_from_queue()
2 parents ba6bd0d + e166baf commit f2ec631

16 files changed

Lines changed: 141 additions & 50 deletions

drivers/scsi/bfa/bfa_fcs_lport.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2627,7 +2627,7 @@ bfa_fcs_fdmi_get_hbaattr(struct bfa_fcs_lport_fdmi_s *fdmi,
26272627

26282628
}
26292629

2630-
static void
2630+
static noinline_for_stack void
26312631
bfa_fcs_fdmi_get_portattr(struct bfa_fcs_lport_fdmi_s *fdmi,
26322632
struct bfa_fcs_fdmi_port_attr_s *port_attr)
26332633
{

drivers/scsi/elx/efct/efct_hw.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1997,6 +1997,8 @@ efct_hw_io_abort(struct efct_hw *hw, struct efct_hw_io *io_to_abort,
19971997
wqcb = efct_hw_reqtag_alloc(hw, efct_hw_wq_process_abort, io_to_abort);
19981998
if (!wqcb) {
19991999
efc_log_err(hw->os, "can't allocate request tag\n");
2000+
io_to_abort->abort_in_progress = false;
2001+
kref_put(&io_to_abort->ref, io_to_abort->release);
20002002
return -ENOSPC;
20012003
}
20022004

drivers/scsi/elx/efct/efct_unsol.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,7 @@ efct_dispatch_fcp_cmd(struct efct_node *node, struct efc_hw_sequence *seq)
385385

386386
if (cmnd->fc_flags & FCP_CFL_LEN_MASK) {
387387
efc_log_err(efct, "Additional CDB not supported\n");
388+
efct_scsi_io_free(io);
388389
return -EIO;
389390
}
390391
/*

drivers/scsi/hosts.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ static void scsi_host_dev_release(struct device *dev)
357357
/* Wait for functions invoked through call_rcu(&scmd->rcu, ...) */
358358
rcu_barrier();
359359

360+
cancel_work_sync(&shost->eh_work);
360361
if (shost->tmf_work_q)
361362
destroy_workqueue(shost->tmf_work_q);
362363
if (shost->ehandler)
@@ -422,6 +423,7 @@ struct Scsi_Host *scsi_host_alloc(const struct scsi_host_template *sht, int priv
422423
INIT_LIST_HEAD(&shost->starved_list);
423424
init_waitqueue_head(&shost->host_wait);
424425
mutex_init(&shost->scan_mutex);
426+
INIT_WORK(&shost->eh_work, scsi_rcu_eh_wakeup);
425427

426428
index = ida_alloc(&host_index_ida, GFP_KERNEL);
427429
if (index < 0) {

drivers/scsi/hpsa.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5017,6 +5017,10 @@ static int hpsa_scsi_ioaccel2_queue_command(struct ctlr_info *h,
50175017

50185018
if (phys_disk->in_reset) {
50195019
cmd->result = DID_RESET << 16;
5020+
atomic_dec(&phys_disk->ioaccel_cmds_out);
5021+
scsi_dma_unmap(cmd);
5022+
if (use_sg > h->ioaccel_maxsg)
5023+
hpsa_unmap_ioaccel2_sg_chain_block(h, cp);
50205024
return -1;
50215025
}
50225026

drivers/scsi/lpfc/lpfc_init.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8189,6 +8189,7 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
81898189
mempool_free(mboxq, phba->mbox_mem_pool);
81908190
goto out_free_bsmbx;
81918191
}
8192+
mempool_free(mboxq, phba->mbox_mem_pool);
81928193

81938194
/*
81948195
* 1 for cmd, 1 for rsp, NVME adds an extra one
@@ -8311,8 +8312,6 @@ lpfc_sli4_driver_resource_setup(struct lpfc_hba *phba)
83118312
goto out_free_sg_dma_buf;
83128313
}
83138314

8314-
mempool_free(mboxq, phba->mbox_mem_pool);
8315-
83168315
/* Verify OAS is supported */
83178316
lpfc_sli4_oas_verify(phba);
83188317

drivers/scsi/scsi_error.c

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,26 @@ void scsi_eh_wakeup(struct Scsi_Host *shost, unsigned int busy)
7373
}
7474
}
7575

76+
void scsi_rcu_eh_wakeup(struct work_struct *work)
77+
{
78+
struct Scsi_Host *shost = container_of(work, struct Scsi_Host, eh_work);
79+
unsigned long flags;
80+
unsigned int busy;
81+
82+
/*
83+
* Ensure any running scsi_dec_host_busy has completed its rcu section
84+
* so changes to host state and host_eh_scheduled are visible to all
85+
* future calls of scsi_dec_host_busy
86+
*/
87+
synchronize_rcu();
88+
89+
busy = scsi_host_busy(shost);
90+
91+
spin_lock_irqsave(shost->host_lock, flags);
92+
scsi_eh_wakeup(shost, busy);
93+
spin_unlock_irqrestore(shost->host_lock, flags);
94+
}
95+
7696
/**
7797
* scsi_schedule_eh - schedule EH for SCSI host
7898
* @shost: SCSI host to invoke error handling on.
@@ -88,7 +108,7 @@ void scsi_schedule_eh(struct Scsi_Host *shost)
88108
if (scsi_host_set_state(shost, SHOST_RECOVERY) == 0 ||
89109
scsi_host_set_state(shost, SHOST_CANCEL_RECOVERY) == 0) {
90110
shost->host_eh_scheduled++;
91-
scsi_eh_wakeup(shost, scsi_host_busy(shost));
111+
queue_work(shost->tmf_work_q, &shost->eh_work);
92112
}
93113

94114
spin_unlock_irqrestore(shost->host_lock, flags);

drivers/scsi/scsi_lib.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2224,14 +2224,6 @@ struct scsi_device *scsi_device_from_queue(struct request_queue *q)
22242224

22252225
return sdev;
22262226
}
2227-
/*
2228-
* pktcdvd should have been integrated into the SCSI layers, but for historical
2229-
* reasons like the old IDE driver it isn't. This export allows it to safely
2230-
* probe if a given device is a SCSI one and only attach to that.
2231-
*/
2232-
#ifdef CONFIG_CDROM_PKTCDVD_MODULE
2233-
EXPORT_SYMBOL_GPL(scsi_device_from_queue);
2234-
#endif
22352227

22362228
/**
22372229
* scsi_block_requests - Utility function used by low-level drivers to prevent

drivers/scsi/scsi_priv.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ extern enum blk_eh_timer_return scsi_timeout(struct request *req);
9191
extern int scsi_error_handler(void *host);
9292
extern enum scsi_disposition scsi_decide_disposition(struct scsi_cmnd *cmd);
9393
extern void scsi_eh_wakeup(struct Scsi_Host *shost, unsigned int busy);
94+
extern void scsi_rcu_eh_wakeup(struct work_struct *work);
9495
extern void scsi_eh_scmd_add(struct scsi_cmnd *);
9596
void scsi_eh_ready_devs(struct Scsi_Host *shost,
9697
struct list_head *work_q,
@@ -102,6 +103,7 @@ void scsi_eh_done(struct scsi_cmnd *scmd);
102103

103104
/* scsi_lib.c */
104105
extern void scsi_device_unbusy(struct scsi_device *sdev, struct scsi_cmnd *cmd);
106+
extern struct scsi_device *scsi_device_from_queue(struct request_queue *q);
105107
extern void scsi_queue_insert(struct scsi_cmnd *cmd,
106108
enum scsi_qc_status reason);
107109
extern void scsi_io_completion(struct scsi_cmnd *, unsigned int);

drivers/scsi/sg.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -863,10 +863,9 @@ sg_fill_request_table(Sg_fd *sfp, sg_req_info_t *rinfo)
863863
if (val >= SG_MAX_QUEUE)
864864
break;
865865
rinfo[val].req_state = srp->done + 1;
866-
rinfo[val].problem =
867-
srp->header.masked_status &
868-
srp->header.host_status &
869-
srp->header.driver_status;
866+
rinfo[val].problem = srp->header.masked_status ||
867+
srp->header.host_status ||
868+
srp->header.driver_status;
870869
if (srp->done)
871870
rinfo[val].duration =
872871
srp->header.duration;

0 commit comments

Comments
 (0)