summaryrefslogtreecommitdiff
path: root/drivers/scsi/scsi_lib.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-13 17:41:21 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-13 17:41:21 -0700
commit03ce3ca4b02bfc1e6567a7851ae231ad3cc9418e (patch)
treebf953469c6cac6b0a5b7d3671a27473eace144e3 /drivers/scsi/scsi_lib.c
parentf8acc450e10dbe7996220bac5459ee9c14a82a6a (diff)
parent622f9a8e7b8043a5ea2c7d047d65ecad01fe0f97 (diff)
Merge tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi
Pull final round of SCSI updates from James Bottomley: "This is the remaining set of SCSI patches for the merge window. It's mostly driver updates (scsi_debug, qla2xxx, storvsc, mp3sas). There are also several bug fixes in fcoe, libfc, and megaraid_sas. We also have a couple of core changes to try to make device destruction more deterministic" * tag 'scsi-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi: (46 commits) [SCSI] scsi constants: command, sense key + additional sense strings fcoe: Reduce number of sparse warnings fcoe: Stop fc_rport_priv structure leak libfcoe: Fix meaningless log statement libfc: Differentiate echange timer cancellation debug statements libfc: Remove extra space in fc_exch_timer_cancel definition fcoe: fix the link error status block sparse warnings fcoe: Fix smatch warning in fcoe_fdmi_info function libfc: Reject PLOGI from nodes with incompatible role [SCSI] enable destruction of blocked devices which fail LUN scanning [SCSI] Fix race between starved list and device removal [SCSI] megaraid_sas: fix a bug for 64 bit arches [SCSI] scsi_debug: reduce duplication between prot_verify_read and prot_verify_write [SCSI] scsi_debug: simplify offset calculation for dif_storep [SCSI] scsi_debug: invalidate protection info for unmapped region [SCSI] scsi_debug: fix NULL pointer dereference with parameters dif=0 dix=1 [SCSI] scsi_debug: fix incorrectly nested kmap_atomic() [SCSI] scsi_debug: fix invalid address passed to kunmap_atomic() [SCSI] mpt3sas: Bump driver version to v02.100.00.00 [SCSI] mpt3sas: when async scanning is enabled then while scanning, devices are removed but their transport layer entries are not removed ...
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r--drivers/scsi/scsi_lib.c27
1 files changed, 22 insertions, 5 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 86d522004a20..124392f3091e 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -434,6 +434,8 @@ static void scsi_run_queue(struct request_queue *q)
list_splice_init(&shost->starved_list, &starved_list);
while (!list_empty(&starved_list)) {
+ struct request_queue *slq;
+
/*
* As long as shost is accepting commands and we have
* starved queues, call blk_run_queue. scsi_request_fn
@@ -456,11 +458,25 @@ static void scsi_run_queue(struct request_queue *q)
continue;
}
- spin_unlock(shost->host_lock);
- spin_lock(sdev->request_queue->queue_lock);
- __blk_run_queue(sdev->request_queue);
- spin_unlock(sdev->request_queue->queue_lock);
- spin_lock(shost->host_lock);
+ /*
+ * Once we drop the host lock, a racing scsi_remove_device()
+ * call may remove the sdev from the starved list and destroy
+ * it and the queue. Mitigate by taking a reference to the
+ * queue and never touching the sdev again after we drop the
+ * host lock. Note: if __scsi_remove_device() invokes
+ * blk_cleanup_queue() before the queue is run from this
+ * function then blk_run_queue() will return immediately since
+ * blk_cleanup_queue() marks the queue with QUEUE_FLAG_DYING.
+ */
+ slq = sdev->request_queue;
+ if (!blk_get_queue(slq))
+ continue;
+ spin_unlock_irqrestore(shost->host_lock, flags);
+
+ blk_run_queue(slq);
+ blk_put_queue(slq);
+
+ spin_lock_irqsave(shost->host_lock, flags);
}
/* put any unprocessed entries back */
list_splice(&starved_list, &shost->starved_list);
@@ -2177,6 +2193,7 @@ scsi_device_set_state(struct scsi_device *sdev, enum scsi_device_state state)
case SDEV_OFFLINE:
case SDEV_TRANSPORT_OFFLINE:
case SDEV_CANCEL:
+ case SDEV_CREATED_BLOCK:
break;
default:
goto illegal;