Avoid that kmemleak reports the following memory leak if a
SCSI LLD calls scsi_host_alloc() and scsi_host_put() but neither
scsi_host_add() nor scsi_host_remove(). The following shell
command triggers that scenario:
for ((i=0; i<2; i++)); do
srp_daemon -oac |
while read line; do
echo $line >/sys/class/infiniband_srp/srp-mlx4_0-1/add_target
done
done
unreferenced object 0xffff88021b24a220 (size 8):
comm "srp_daemon", pid 56421, jiffies
4295006762 (age 4240.750s)
hex dump (first 8 bytes):
68 6f 73 74 35 38 00 a5 host58..
backtrace:
[<
ffffffff8151014a>] kmemleak_alloc+0x7a/0xc0
[<
ffffffff81165c1e>] __kmalloc_track_caller+0xfe/0x160
[<
ffffffff81260d2b>] kvasprintf+0x5b/0x90
[<
ffffffff81260e2d>] kvasprintf_const+0x8d/0xb0
[<
ffffffff81254b0c>] kobject_set_name_vargs+0x3c/0xa0
[<
ffffffff81337e3c>] dev_set_name+0x3c/0x40
[<
ffffffff81355757>] scsi_host_alloc+0x327/0x4b0
[<
ffffffffa03edc8e>] srp_create_target+0x4e/0x8a0 [ib_srp]
[<
ffffffff8133778b>] dev_attr_store+0x1b/0x20
[<
ffffffff811f27fa>] sysfs_kf_write+0x4a/0x60
[<
ffffffff811f1e8e>] kernfs_fop_write+0x14e/0x180
[<
ffffffff81176eef>] __vfs_write+0x2f/0xf0
[<
ffffffff811771e4>] vfs_write+0xa4/0x100
[<
ffffffff81177c64>] SyS_write+0x54/0xc0
[<
ffffffff8151b257>] entry_SYSCALL_64_fastpath+0x12/0x6f
Signed-off-by: Bart Van Assche <bart.vanassche@sandisk.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Johannes Thumshirn <jthumshirn@suse.de>
Reviewed-by: Sagi Grimberg <sagig@mellanox.com>
Reviewed-by: Lee Duncan <lduncan@suse.com>
Cc: Christoph Hellwig <hch@lst.de>
Cc: Hannes Reinecke <hare@suse.de>
Cc: stable <stable@vger.kernel.org>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
kfree(queuedata);
}
+ if (shost->shost_state == SHOST_CREATED) {
+ /*
+ * Free the shost_dev device name here if scsi_host_alloc()
+ * and scsi_host_put() have been called but neither
+ * scsi_host_add() nor scsi_host_remove() has been called.
+ * This avoids that the memory allocated for the shost_dev
+ * name is leaked.
+ */
+ kfree(dev_name(&shost->shost_dev));
+ }
+
scsi_destroy_command_freelist(shost);
if (shost_use_blk_mq(shost)) {
if (shost->tag_set.tags)