summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/scsi_lib.c
diff options
context:
space:
mode:
authorJianchao Wang <jianchao.w.wang@oracle.com>2018-03-03 09:54:09 +0800
committerMartin K. Petersen <martin.petersen@oracle.com>2018-03-06 21:16:33 -0500
commit2f793a27d58f0fb302f8e162b46fe4b366bbdedd (patch)
tree04cef37a0265f155ab760e6606a19df9e36bdcd8 /drivers/scsi/scsi_lib.c
parent61b142afb2e28d4f06e158399409d181ad91949c (diff)
downloadlinux-2f793a27d58f0fb302f8e162b46fe4b366bbdedd.tar.gz
linux-2f793a27d58f0fb302f8e162b46fe4b366bbdedd.tar.bz2
linux-2f793a27d58f0fb302f8e162b46fe4b366bbdedd.zip
scsi: core: use blk_mq_requeue_request in __scsi_queue_insert
In scsi core, __scsi_queue_insert should just put request back on the queue and retry using the same command as before. However, for blk-mq, scsi_mq_requeue_cmd is employed here which will unprepare the request. To align with the semantics of __scsi_queue_insert, use blk_mq_requeue_request with kick_requeue_list == true and put the reference of scsi_device. Cc: Christoph Hellwig <hch@lst.de> Signed-off-by: Jianchao Wang <jianchao.w.wang@oracle.com> Reviewed-by: Bart Van Assche <bart.vanassche@wdc.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/scsi_lib.c')
-rw-r--r--drivers/scsi/scsi_lib.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index aea5a1ae318b..10430d500792 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -191,7 +191,19 @@ static void __scsi_queue_insert(struct scsi_cmnd *cmd, int reason, bool unbusy)
*/
cmd->result = 0;
if (q->mq_ops) {
- scsi_mq_requeue_cmd(cmd);
+ /*
+ * Before a SCSI command is dispatched,
+ * get_device(&sdev->sdev_gendev) is called and the host,
+ * target and device busy counters are increased. Since
+ * requeuing a request causes these actions to be repeated and
+ * since scsi_device_unbusy() has already been called,
+ * put_device(&device->sdev_gendev) must still be called. Call
+ * put_device() after blk_mq_requeue_request() to avoid that
+ * removal of the SCSI device can start before requeueing has
+ * happened.
+ */
+ blk_mq_requeue_request(cmd->request, true);
+ put_device(&device->sdev_gendev);
return;
}
spin_lock_irqsave(q->queue_lock, flags);