summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYu Kuai <yukuai3@huawei.com>2023-06-10 05:20:02 +0300
committerJens Axboe <axboe@kernel.dk>2023-06-15 05:24:03 +0300
commitdb59133e927916d8a25ee1fd8264f2808040909d (patch)
treee7867d42daaafe5d4f41c14caa8bcdff11654882
parentcbe7cff4a76bc749dd70264ca5cf924e2adf9296 (diff)
downloadlinux-db59133e927916d8a25ee1fd8264f2808040909d.tar.xz
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: Yu Kuai <yukuai3@huawei.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Martin K. Petersen <martin.petersen@oracle.com> Link: https://lore.kernel.org/r/20230610022003.2557284-3-yukuai1@huaweicloud.com Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--drivers/scsi/sg.c9
1 files changed, 9 insertions, 0 deletions
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 138e28bb76b7..2433eeef042a 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -1497,6 +1497,10 @@ sg_add_device(struct device *cl_dev)
int error;
unsigned long iflags;
+ error = scsi_device_get(scsidp);
+ if (error)
+ return error;
+
error = -ENOMEM;
cdev = cdev_alloc();
if (!cdev) {
@@ -1554,6 +1558,7 @@ cdev_add_err:
out:
if (cdev)
cdev_del(cdev);
+ scsi_device_put(scsidp);
return error;
}
@@ -1561,6 +1566,7 @@ static void
sg_device_destroy(struct kref *kref)
{
struct sg_device *sdp = container_of(kref, struct sg_device, d_ref);
+ struct request_queue *q = sdp->device->request_queue;
unsigned long flags;
/* CAUTION! Note that the device can still be found via idr_find()
@@ -1568,6 +1574,9 @@ sg_device_destroy(struct kref *kref)
* any other cleanup.
*/
+ blk_trace_remove(q);
+ scsi_device_put(sdp->device);
+
write_lock_irqsave(&sg_index_lock, flags);
idr_remove(&sg_index_idr, sdp->index);
write_unlock_irqrestore(&sg_index_lock, flags);