Commit db59133e authored by Yu Kuai's avatar Yu Kuai Committed by Jens Axboe

scsi: sg: fix blktrace debugfs entries leakage

sg_ioctl() support to enable blktrace, which will create debugfs entries
"/sys/kernel/debug/block/sgx/", however, there is no guarantee that user
will remove these entries through ioctl, and deleting sg device doesn't
cleanup these blktrace entries.

This problem can be fixed by cleanup blktrace while releasing
request_queue, however, it's not a good idea to do this special handling
in common layer just for sg device.

Fix this problem by shutdown bltkrace in sg_device_destroy(), where the
device is deleted and all the users close the device, also grab a
scsi_device reference from sg_add_device() to prevent scsi_device to be
freed before sg_device_destroy();
Signed-off-by: default avatarYu Kuai <yukuai3@huawei.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Reviewed-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
Link: https://lore.kernel.org/r/20230610022003.2557284-3-yukuai1@huaweicloud.comSigned-off-by: default avatarJens Axboe <axboe@kernel.dk>
parent cbe7cff4
...@@ -1497,6 +1497,10 @@ sg_add_device(struct device *cl_dev) ...@@ -1497,6 +1497,10 @@ sg_add_device(struct device *cl_dev)
int error; int error;
unsigned long iflags; unsigned long iflags;
error = scsi_device_get(scsidp);
if (error)
return error;
error = -ENOMEM; error = -ENOMEM;
cdev = cdev_alloc(); cdev = cdev_alloc();
if (!cdev) { if (!cdev) {
...@@ -1554,6 +1558,7 @@ sg_add_device(struct device *cl_dev) ...@@ -1554,6 +1558,7 @@ sg_add_device(struct device *cl_dev)
out: out:
if (cdev) if (cdev)
cdev_del(cdev); cdev_del(cdev);
scsi_device_put(scsidp);
return error; return error;
} }
...@@ -1561,6 +1566,7 @@ static void ...@@ -1561,6 +1566,7 @@ static void
sg_device_destroy(struct kref *kref) sg_device_destroy(struct kref *kref)
{ {
struct sg_device *sdp = container_of(kref, struct sg_device, d_ref); struct sg_device *sdp = container_of(kref, struct sg_device, d_ref);
struct request_queue *q = sdp->device->request_queue;
unsigned long flags; unsigned long flags;
/* CAUTION! Note that the device can still be found via idr_find() /* CAUTION! Note that the device can still be found via idr_find()
...@@ -1568,6 +1574,9 @@ sg_device_destroy(struct kref *kref) ...@@ -1568,6 +1574,9 @@ sg_device_destroy(struct kref *kref)
* any other cleanup. * any other cleanup.
*/ */
blk_trace_remove(q);
scsi_device_put(sdp->device);
write_lock_irqsave(&sg_index_lock, flags); write_lock_irqsave(&sg_index_lock, flags);
idr_remove(&sg_index_idr, sdp->index); idr_remove(&sg_index_idr, sdp->index);
write_unlock_irqrestore(&sg_index_lock, flags); write_unlock_irqrestore(&sg_index_lock, flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment