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:
parent
c5e46f7ad4
commit
d7035b73a7
@ -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);
|
||||
|
Loading…
x
Reference in New Issue
Block a user