scsi: Avoid that toggling use_blk_mq triggers a memory leak
authorBart Van Assche <bart.vanassche@sandisk.com>
Thu, 22 Sep 2016 21:20:54 +0000 (14:20 -0700)
committerMartin K. Petersen <martin.petersen@oracle.com>
Tue, 27 Sep 2016 00:58:42 +0000 (20:58 -0400)
This patch avoids that the following memory leak is triggered if
use_blk_mq is disabled after a SCSI host has been allocated by the
ib_srp driver and before the same SCSI host is freed:

unreferenced object 0xffff8803a168c568 (size 256):
  backtrace:
    [<ffffffff81620c95>] kmemleak_alloc+0x45/0xa0
    [<ffffffff811bb104>] __kmalloc_node+0x1e4/0x400
    [<ffffffff81309fe4>] blk_mq_alloc_tag_set+0xb4/0x230
    [<ffffffff814731b7>] scsi_mq_setup_tags+0xc7/0xd0
    [<ffffffff81469c26>] scsi_add_host_with_dma+0x216/0x2d0
    [<ffffffffa064bef5>] srp_create_target+0xe55/0x13d0 [ib_srp]
    [<ffffffff8143ce23>] dev_attr_store+0x13/0x20
    [<ffffffff8125f030>] sysfs_kf_write+0x40/0x50
    [<ffffffff8125e397>] kernfs_fop_write+0x137/0x1c0
    [<ffffffff811d8c13>] __vfs_write+0x23/0x140
    [<ffffffff811d92e0>] vfs_write+0xb0/0x190
    [<ffffffff811da5b4>] SyS_write+0x44/0xa0
    [<ffffffff8162c8a5>] entry_SYSCALL_64_fastpath+0x18/0xa8

Fixes: 9aa9cc4221f5 ("scsi: remove the disable_blk_mq host flag")
Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Martin K. Petersen <martin.petersen@oracle.com>
Cc: <stable@vger.kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
drivers/scsi/hosts.c
drivers/scsi/scsi.c
drivers/scsi/scsi_priv.h
include/scsi/scsi_host.h

index ba9af4a2bd2ab3159ed415b5acc73328925aa3c3..ec6381e57eb737cebbae0689595979ac6ee9628b 100644 (file)
@@ -486,6 +486,8 @@ struct Scsi_Host *scsi_host_alloc(struct scsi_host_template *sht, int privsize)
        else
                shost->dma_boundary = 0xffffffff;
 
+       shost->use_blk_mq = scsi_use_blk_mq;
+
        device_initialize(&shost->shost_gendev);
        dev_set_name(&shost->shost_gendev, "host%d", shost->host_no);
        shost->shost_gendev.bus = &scsi_bus_type;
index 1f36aca44394eaf49a8edc0ce78d6db371288cc8..1deb6adc411f795833a444a84b1e80e9f9629c4d 100644 (file)
@@ -1160,7 +1160,6 @@ bool scsi_use_blk_mq = true;
 bool scsi_use_blk_mq = false;
 #endif
 module_param_named(use_blk_mq, scsi_use_blk_mq, bool, S_IWUSR | S_IRUGO);
-EXPORT_SYMBOL_GPL(scsi_use_blk_mq);
 
 static int __init init_scsi(void)
 {
index 57a4b9973320f159d13730214f3e1f7c6d7b24eb..85c8a51bc5637701cc2b2d79f1b678064cb628ca 100644 (file)
@@ -29,6 +29,7 @@ extern int scsi_init_hosts(void);
 extern void scsi_exit_hosts(void);
 
 /* scsi.c */
+extern bool scsi_use_blk_mq;
 extern int scsi_setup_command_freelist(struct Scsi_Host *shost);
 extern void scsi_destroy_command_freelist(struct Scsi_Host *shost);
 #ifdef CONFIG_SCSI_LOGGING
index 0dee7afa93d6621881b2f6a4afb6828a4b5f8d63..7e4cd53139ed518a89795ea360bf30cce0ce1377 100644 (file)
@@ -771,12 +771,9 @@ static inline int scsi_host_in_recovery(struct Scsi_Host *shost)
                shost->tmf_in_progress;
 }
 
-extern bool scsi_use_blk_mq;
-
 static inline bool shost_use_blk_mq(struct Scsi_Host *shost)
 {
-       return scsi_use_blk_mq;
-
+       return shost->use_blk_mq;
 }
 
 extern int scsi_queue_work(struct Scsi_Host *, struct work_struct *);