scsi: core: Revert "Make sure that hosts outlive targets"
authorBart Van Assche <bvanassche@acm.org>
Sun, 21 Aug 2022 22:05:01 +0000 (15:05 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Thu, 1 Sep 2022 05:02:10 +0000 (01:02 -0400)
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: 16728aaba62e ("scsi: core: Make sure that hosts outlive targets")
Reported-by: syzbot+bafeb834708b1bb750bc@syzkaller.appspotmail.com
Tested-by: Kenneth R. Crudup <kenny@panix.com>
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/hosts.c
drivers/scsi/scsi_scan.c
include/scsi/scsi_host.h

index 20c1f5420ba6ebb516ba19b393da56ceb5f7cb46..26bf3b1535959f177075961601a36f77191b61a1 100644 (file)
@@ -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) {
index ac6059702d13514d8bb9ed704e644b62117109fb..4c1efd6a3b0ca9d4f5abe56cdae4d5a97e20250b 100644 (file)
@@ -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);
 
index aa7b7496c93aa16a6c1487425ec1de6dc862923b..b6e41ee3d566ecd29b9f0295eb85efaaafb0cc8e 100644 (file)
@@ -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