summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJosef Bacik <josef@toxicpanda.com>2026-10-28 10:41:19 -0600
committerJens Axboe <axboe@kernel.dk>2026-10-29 07:23:19 -0600
commitd9667ade40f986c565769a900ced6ee95edd33c6 (patch)
tree1369e72009e20f55b0cbb89553810f5fba4557f2
parentbf7fff620c890a7ee0b444f1c7e9f0d1263a30ac (diff)
downloadlinux-d9667ade40f986c565769a900ced6ee95edd33c6.tar.gz
linux-d9667ade40f986c565769a900ced6ee95edd33c6.zip
block/rnbd-srv: don't free the device on a sysfs error
rnbd_srv_create_dev_sysfs() drops the only kobject reference on its error paths, and the release function frees the rnbd_srv_dev. process_msg_open() keeps using it and ends in destroy_device() with a list_del() and a second kfree(). This doesn't need memory pressure: a client opening a device while its last mapping goes away gets -EEXIST from kobject_add() against the old directory. Only undo kobject_add() on failure and leave the reference to destroy_device(). Initialise the kobject once, the next open retries. Fixes: 8cee532f469b ("block/rnbd: server: sysfs interface functions") Fixes: d3a95ccaaf4d ("block/rnbd: call kobject_put in the failure path") Cc: "Md. Haris Iqbal" <haris.iqbal@ionos.com> Cc: Jack Wang <jinpu.wang@ionos.com> Signed-off-by: Josef Bacik <josef@toxicpanda.com> Link: https://patch.msgid.link/20261028164415.1262013-17-axboe@kernel.dk Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--drivers/block/rnbd/rnbd-srv-sysfs.c16
-rw-r--r--drivers/block/rnbd/rnbd-srv.c3
2 files changed, 13 insertions, 6 deletions
diff --git a/drivers/block/rnbd/rnbd-srv-sysfs.c b/drivers/block/rnbd/rnbd-srv-sysfs.c
index 64780094442c..33d5d1738be5 100644
--- a/drivers/block/rnbd/rnbd-srv-sysfs.c
+++ b/drivers/block/rnbd/rnbd-srv-sysfs.c
@@ -44,12 +44,17 @@ int rnbd_srv_create_dev_sysfs(struct rnbd_srv_dev *dev,
struct kobject *bdev_kobj;
int ret;
- ret = kobject_init_and_add(&dev->dev_kobj, &dev_ktype,
- rnbd_devs_kobj, "%pg", bdev);
- if (ret) {
- kobject_put(&dev->dev_kobj);
+ /*
+ * The release function frees the device, which the caller goes on
+ * using and which others may share: never drop the reference of the
+ * kobject here. That is for destroy_device().
+ */
+ if (!dev->dev_kobj.state_initialized)
+ kobject_init(&dev->dev_kobj, &dev_ktype);
+
+ ret = kobject_add(&dev->dev_kobj, rnbd_devs_kobj, "%pg", bdev);
+ if (ret)
return ret;
- }
dev->dev_sessions_kobj = kobject_create_and_add("sessions",
&dev->dev_kobj);
@@ -69,7 +74,6 @@ put_sess_kobj:
kobject_put(dev->dev_sessions_kobj);
free_dev_kobj:
kobject_del(&dev->dev_kobj);
- kobject_put(&dev->dev_kobj);
return ret;
}
diff --git a/drivers/block/rnbd/rnbd-srv.c b/drivers/block/rnbd/rnbd-srv.c
index 79c9a5fb418f..2b0619389fc9 100644
--- a/drivers/block/rnbd/rnbd-srv.c
+++ b/drivers/block/rnbd/rnbd-srv.c
@@ -208,6 +208,9 @@ static void destroy_device(struct kref *kref)
* Destroy kobj only if it was really created.
*/
rnbd_srv_destroy_dev_sysfs(dev);
+ else if (dev->dev_kobj.state_initialized)
+ /* The files could not be created. Frees the name, too. */
+ kobject_put(&dev->dev_kobj);
else
kfree(dev);
}