Commit d7035b73 authored by Martin Wilck's avatar Martin Wilck Committed by Martin K. Petersen

scsi: core: Don't wait for quiesce in scsi_stop_queue()

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: default avatarMartin Wilck <mwilck@suse.com>
Link: https://lore.kernel.org/r/20230614103616.31857-5-mwilck@suse.comReviewed-by: default avatarHannes Reinecke <hare@suse.de>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent c5e46f7a
...@@ -2725,24 +2725,16 @@ void scsi_start_queue(struct scsi_device *sdev) ...@@ -2725,24 +2725,16 @@ void scsi_start_queue(struct scsi_device *sdev)
blk_mq_unquiesce_queue(sdev->request_queue); 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 * The atomic variable of ->queue_stopped covers that
* blk_mq_quiesce_queue* is balanced with blk_mq_unquiesce_queue. * blk_mq_quiesce_queue* is balanced with blk_mq_unquiesce_queue.
* *
* However, we still need to wait until quiesce is done * The caller needs to wait until quiesce is done.
* in case that queue has been stopped.
*/ */
if (!cmpxchg(&sdev->queue_stopped, 0, 1)) { if (!cmpxchg(&sdev->queue_stopped, 0, 1))
if (nowait) blk_mq_quiesce_queue_nowait(sdev->request_queue);
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);
}
} }
/** /**
...@@ -2769,7 +2761,7 @@ int scsi_internal_device_block_nowait(struct scsi_device *sdev) ...@@ -2769,7 +2761,7 @@ int scsi_internal_device_block_nowait(struct scsi_device *sdev)
* request queue. * request queue.
*/ */
if (!ret) if (!ret)
scsi_stop_queue(sdev, true); scsi_stop_queue(sdev);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(scsi_internal_device_block_nowait); EXPORT_SYMBOL_GPL(scsi_internal_device_block_nowait);
...@@ -2794,9 +2786,17 @@ static void scsi_device_block(struct scsi_device *sdev, void *data) ...@@ -2794,9 +2786,17 @@ static void scsi_device_block(struct scsi_device *sdev, void *data)
mutex_lock(&sdev->state_mutex); mutex_lock(&sdev->state_mutex);
err = __scsi_internal_device_block_nowait(sdev); err = __scsi_internal_device_block_nowait(sdev);
if (err == 0) if (err == 0) {
scsi_stop_queue(sdev, false); /*
mutex_unlock(&sdev->state_mutex); * 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", WARN_ONCE(err, "__scsi_internal_device_block_nowait(%s) failed: err = %d\n",
dev_name(&sdev->sdev_gendev), err); dev_name(&sdev->sdev_gendev), err);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment