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

scsi: core: Revert "Make sure that hosts outlive targets"

Revert the patch series "Call blk_mq_free_tag_set() earlier" because it
introduces a deadlock if the scsi_remove_host() caller holds a reference on
a device, target or host.

Link: https://lore.kernel.org/r/20220821220502.13685-4-bvanassche@acm.org


Fixes: 16728aab ("scsi: core: Make sure that hosts outlive targets")
Reported-by: default avatar <syzbot+bafeb834708b1bb750bc@syzkaller.appspotmail.com>
Tested-by: default avatarKenneth R. Crudup <kenny@panix.com>
Signed-off-by: default avatarBart Van Assche <bvanassche@acm.org>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 70e8d057
Loading
Loading
Loading
Loading
+0 −8
Original line number Diff line number Diff line
@@ -190,13 +190,6 @@ void scsi_remove_host(struct Scsi_Host *shost)
	transport_unregister_device(&shost->shost_gendev);
	device_unregister(&shost->shost_dev);
	device_del(&shost->shost_gendev);

	/*
	 * After scsi_remove_host() has returned the scsi LLD module can be
	 * unloaded and/or the host resources can be released. Hence wait until
	 * the dependent SCSI targets and devices are gone before returning.
	 */
	wait_event(shost->targets_wq, atomic_read(&shost->target_count) == 0);
}
EXPORT_SYMBOL(scsi_remove_host);

@@ -406,7 +399,6 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
	INIT_LIST_HEAD(&shost->starved_list);
	init_waitqueue_head(&shost->host_wait);
	mutex_init(&shost->scan_mutex);
	init_waitqueue_head(&shost->targets_wq);

	index = ida_alloc(&host_index_ida, GFP_KERNEL);
	if (index < 0) {
+0 −7
Original line number Diff line number Diff line
@@ -406,14 +406,9 @@ static void scsi_target_destroy(struct scsi_target *starget)
static void scsi_target_dev_release(struct device *dev)
{
	struct device *parent = dev->parent;
	struct Scsi_Host *shost = dev_to_shost(parent);
	struct scsi_target *starget = to_scsi_target(dev);

	kfree(starget);

	if (atomic_dec_return(&shost->target_count) == 0)
		wake_up(&shost->targets_wq);

	put_device(parent);
}

@@ -528,8 +523,6 @@ static struct scsi_target *scsi_alloc_target(struct device *parent,
	starget->max_target_blocked = SCSI_DEFAULT_TARGET_BLOCKED;
	init_waitqueue_head(&starget->sdev_wq);

	atomic_inc(&shost->target_count);

 retry:
	spin_lock_irqsave(shost->host_lock, flags);

+0 −3
Original line number Diff line number Diff line
@@ -690,9 +690,6 @@ struct Scsi_Host {
	/* ldm bits */
	struct device		shost_gendev, shost_dev;

	atomic_t		target_count;
	wait_queue_head_t	targets_wq;

	/*
	 * Points to the transport data (if any) which is allocated
	 * separately