]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
scsi: core: Don't wait for quiesce in scsi_stop_queue()
authorMartin Wilck <mwilck@suse.com>
Wed, 14 Jun 2023 10:36:13 +0000 (12:36 +0200)
committerMartin K. Petersen <martin.petersen@oracle.com>
Fri, 16 Jun 2023 16:19:59 +0000 (12:19 -0400)
scsi_stop_queue() has just two callers, one with and one without
"nowait". As blk_mq_quiesce_queue() comes down to
blk_mq_quiesce_queue_nowait() followed by blk_mq_wait_quiesce_done(), we
might as well open-code this in scsi_device_block().

Also, add a comment explaining why blk_mq_quiesce_queue_nowait() must be
called with the state_mutex held, see
https://lore.kernel.org/linux-scsi/3b8b13bf-a458-827a-b916-07d7eee8ae00@acm.org/.

Signed-off-by: Martin Wilck <mwilck@suse.com>
Link: https://lore.kernel.org/r/20230614103616.31857-5-mwilck@suse.com
Reviewed-by: Hannes Reinecke <hare@suse.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/scsi_lib.c

index 357eb0ab6f217975389de31a1bdb944f4d97bdd0..4b46dcba764932ee4b3ae82b918dc70671f1ef0b 100644 (file)
@@ -2725,24 +2725,16 @@ void scsi_start_queue(struct scsi_device *sdev)
                blk_mq_unquiesce_queue(sdev->request_queue);
 }
 
-static void scsi_stop_queue(struct scsi_device *sdev, bool nowait)
+static void scsi_stop_queue(struct scsi_device *sdev)
 {
        /*
         * The atomic variable of ->queue_stopped covers that
         * blk_mq_quiesce_queue* is balanced with blk_mq_unquiesce_queue.
         *
-        * However, we still need to wait until quiesce is done
-        * in case that queue has been stopped.
+        * The caller needs to wait until quiesce is done.
         */
-       if (!cmpxchg(&sdev->queue_stopped, 0, 1)) {
-               if (nowait)
-                       blk_mq_quiesce_queue_nowait(sdev->request_queue);
-               else
-                       blk_mq_quiesce_queue(sdev->request_queue);
-       } else {
-               if (!nowait)
-                       blk_mq_wait_quiesce_done(sdev->request_queue->tag_set);
-       }
+       if (!cmpxchg(&sdev->queue_stopped, 0, 1))
+               blk_mq_quiesce_queue_nowait(sdev->request_queue);
 }
 
 /**
@@ -2769,7 +2761,7 @@ int scsi_internal_device_block_nowait(struct scsi_device *sdev)
         * request queue.
         */
        if (!ret)
-               scsi_stop_queue(sdev, true);
+               scsi_stop_queue(sdev);
        return ret;
 }
 EXPORT_SYMBOL_GPL(scsi_internal_device_block_nowait);
@@ -2794,9 +2786,17 @@ static void scsi_device_block(struct scsi_device *sdev, void *data)
 
        mutex_lock(&sdev->state_mutex);
        err = __scsi_internal_device_block_nowait(sdev);
-       if (err == 0)
-               scsi_stop_queue(sdev, false);
-       mutex_unlock(&sdev->state_mutex);
+       if (err == 0) {
+               /*
+                * scsi_stop_queue() must be called with the state_mutex
+                * held. Otherwise a simultaneous scsi_start_queue() call
+                * might unquiesce the queue before we quiesce it.
+                */
+               scsi_stop_queue(sdev);
+               mutex_unlock(&sdev->state_mutex);
+               blk_mq_wait_quiesce_done(sdev->request_queue->tag_set);
+       } else
+               mutex_unlock(&sdev->state_mutex);
 
        WARN_ONCE(err, "__scsi_internal_device_block_nowait(%s) failed: err = %d\n",
                  dev_name(&sdev->sdev_gendev), err);