Commit d460f624 authored by Bart Van Assche's avatar Bart Van Assche Committed by Martin K. Petersen
Browse files

scsi: core: Rework scsi_single_lun_run()



Use __starget_for_each_device() instead of open-coding
starget_for_each_device(). Run the queues asynchronously instead of
synchronously.

This commit removes code that calls scsi_device_put() from atomic context.

Cc: Christoph Hellwig <hch@lst.de>
Cc: Ming Lei <ming.lei@redhat.com>
Cc: Hannes Reinecke <hare@suse.de>
Cc: John Garry <john.garry@huawei.com>
Cc: Mike Christie <michael.christie@oracle.com>
Cc: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
Signed-off-by: default avatarBart Van Assche <bvanassche@acm.org>
Link: https://lore.kernel.org/r/20221015002418.30955-6-bvanassche@acm.org


Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 036abd61
Loading
Loading
Loading
Loading
+15 −17
Original line number Diff line number Diff line
@@ -307,6 +307,18 @@ static void scsi_kick_queue(struct request_queue *q)
	blk_mq_run_hw_queues(q, false);
}

/*
 * Kick the queue of SCSI device @sdev if @sdev != current_sdev. Called with
 * interrupts disabled.
 */
static void scsi_kick_sdev_queue(struct scsi_device *sdev, void *data)
{
	struct scsi_device *current_sdev = data;

	if (sdev != current_sdev)
		blk_mq_run_hw_queues(sdev->request_queue, true);
}

/*
 * Called for single_lun devices on IO completion. Clear starget_sdev_user,
 * and call blk_run_queue for all the scsi_devices on the target -
@@ -317,7 +329,6 @@ static void scsi_kick_queue(struct request_queue *q)
static void scsi_single_lun_run(struct scsi_device *current_sdev)
{
	struct Scsi_Host *shost = current_sdev->host;
	struct scsi_device *sdev, *tmp;
	struct scsi_target *starget = scsi_target(current_sdev);
	unsigned long flags;

@@ -334,22 +345,9 @@ static void scsi_single_lun_run(struct scsi_device *current_sdev)
	scsi_kick_queue(current_sdev->request_queue);

	spin_lock_irqsave(shost->host_lock, flags);
	if (starget->starget_sdev_user)
		goto out;
	list_for_each_entry_safe(sdev, tmp, &starget->devices,
			same_target_siblings) {
		if (sdev == current_sdev)
			continue;
		if (scsi_device_get(sdev))
			continue;

		spin_unlock_irqrestore(shost->host_lock, flags);
		scsi_kick_queue(sdev->request_queue);
		spin_lock_irqsave(shost->host_lock, flags);

		scsi_device_put(sdev);
	}
 out:
	if (!starget->starget_sdev_user)
		__starget_for_each_device(starget, current_sdev,
					  scsi_kick_sdev_queue);
	spin_unlock_irqrestore(shost->host_lock, flags);
}