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

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.com


Reviewed-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
Loading
Loading
Loading
Loading
+16 −16
Original line number Diff line number Diff line
@@ -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)
	if (!cmpxchg(&sdev->queue_stopped, 0, 1))
		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)
	 * request queue.
	 */
	if (!ret)
		scsi_stop_queue(sdev, true);
		scsi_stop_queue(sdev);
	return ret;
}
EXPORT_SYMBOL_GPL(scsi_internal_device_block_nowait);
@@ -2794,8 +2786,16 @@ 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);
	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",