From d9667ade40f986c565769a900ced6ee95edd33c6 Mon Sep 17 00:00:00 2001 From: Josef Bacik Date: Wed, 28 Oct 2026 10:41:19 -0600 Subject: [PATCH] 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" Cc: Jack Wang Signed-off-by: Josef Bacik Link: https://patch.msgid.link/20261028164415.1262013-17-axboe@kernel.dk Signed-off-by: Jens Axboe --- drivers/block/rnbd/rnbd-srv-sysfs.c | 16 ++++++++++------ drivers/block/rnbd/rnbd-srv.c | 3 +++ 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 @@ int rnbd_srv_create_dev_sysfs(struct rnbd_srv_dev *dev, 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); }