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: 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>
This commit is contained in:
Martin Wilck 2023-06-14 12:36:13 +02:00 committed by Martin K. Petersen
parent c5e46f7ad4
commit d7035b73a7

View 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);