Skip to content

Commit 2b5bebc

Browse files
Joe LawrenceJames Bottomley
authored andcommitted
[SCSI] st: Take additional queue ref in st_probe
This patch fixes a reference count bug in the SCSI tape driver which can be reproduced with the following: * Boot with slub_debug=FZPU, tape drive attached * echo 1 > /sys/devices/... tape device pci path .../remove * Wait for device removal * echo 1 > /sys/kernel/slab/blkdev_queue/validate * Slub debug complains about corrupted poison pattern In commit 523e1d3 (block: make gendisk hold a reference to its queue) add_disk() and disk_release() were modified to get/put an additional reference on a disk queue to fix a reference counting discrepency between bdev release and SCSI device removal. The ST driver never calls add_disk(), so this commit introduced an extra kref put when the ST driver frees its struct gendisk. Attempts were made to fix this bug at the block level [1] but later abandoned due to floppy driver issues [2]. [1] https://lkml.org/lkml/2012/8/27/354 [2] https://lkml.org/lkml/2012/9/22/113 Signed-off-by: Joe Lawrence <joe.lawrence@stratus.com> Tested-by: Ewan D. Milne <emilne@redhat.com> Acked-by: Kai Mäkisara <Kai.Makisara@kolumbus.fi> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
1 parent 95c9f4d commit 2b5bebc

File tree

1 file changed

+7
-1
lines changed

1 file changed

+7
-1
lines changed

drivers/scsi/st.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4112,6 +4112,10 @@ static int st_probe(struct device *dev)
41124112
tpnt->disk = disk;
41134113
disk->private_data = &tpnt->driver;
41144114
disk->queue = SDp->request_queue;
4115+
/* SCSI tape doesn't register this gendisk via add_disk(). Manually
4116+
* take queue reference that release_disk() expects. */
4117+
if (!blk_get_queue(disk->queue))
4118+
goto out_put_disk;
41154119
tpnt->driver = &st_template;
41164120

41174121
tpnt->device = SDp;
@@ -4185,7 +4189,7 @@ static int st_probe(struct device *dev)
41854189
idr_preload_end();
41864190
if (error < 0) {
41874191
pr_warn("st: idr allocation failed: %d\n", error);
4188-
goto out_put_disk;
4192+
goto out_put_queue;
41894193
}
41904194
tpnt->index = error;
41914195
sprintf(disk->disk_name, "st%d", tpnt->index);
@@ -4211,6 +4215,8 @@ static int st_probe(struct device *dev)
42114215
spin_lock(&st_index_lock);
42124216
idr_remove(&st_index_idr, tpnt->index);
42134217
spin_unlock(&st_index_lock);
4218+
out_put_queue:
4219+
blk_put_queue(disk->queue);
42144220
out_put_disk:
42154221
put_disk(disk);
42164222
kfree(tpnt);

0 commit comments

Comments
 (0)