summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Mason <mason@kernel.org>2026-10-28 10:41:43 -0600
committerJens Axboe <axboe@kernel.dk>2026-10-29 07:23:20 -0600
commit08ebf69c78a02afb39b7728f3358c09bc4cf067d (patch)
tree5b6deadc6cc4a6f765899b0a1d78f461d5ad6c5a
parent4912dab88baa5f7034dc9e38807804d470ae5438 (diff)
downloadlinux-08ebf69c78a02afb39b7728f3358c09bc4cf067d.tar.gz
linux-08ebf69c78a02afb39b7728f3358c09bc4cf067d.zip
rnbd-srv: publish the sess_dev at the end of OPEN
rnbd_sess_dev_alloc() stores the empty sess_dev in the XArray as its first step. An IO message with the new ID from another connection can find it before bdev_file is set, or hold a reference while a failing OPEN frees it after a mere RCU grace period. Both are reachable from any host that can open a device. Reserve the ID with a NULL entry and store the sess_dev once nothing can fail anymore. The error path still erases the ID, and no longer needs synchronize_rcu(). Fixes: 2de6c8de192b ("block/rnbd: server: main functionality") Cc: "Md. Haris Iqbal" <haris.iqbal@ionos.com> Cc: Jack Wang <jinpu.wang@ionos.com> Signed-off-by: Chris Mason <mason@kernel.org> Link: https://patch.msgid.link/20261028164415.1262013-41-axboe@kernel.dk Signed-off-by: Jens Axboe <axboe@kernel.dk>
-rw-r--r--drivers/block/rnbd/rnbd-srv.c10
1 files changed, 8 insertions, 2 deletions
diff --git a/drivers/block/rnbd/rnbd-srv.c b/drivers/block/rnbd/rnbd-srv.c
index 1cfa2c580759..1c80e8fe0267 100644
--- a/drivers/block/rnbd/rnbd-srv.c
+++ b/drivers/block/rnbd/rnbd-srv.c
@@ -431,7 +431,7 @@ static struct rnbd_srv_sess_dev
if (!sess_dev)
return ERR_PTR(-ENOMEM);
- error = xa_alloc(&srv_sess->index_idr, &sess_dev->device_id, sess_dev,
+ error = xa_alloc(&srv_sess->index_idr, &sess_dev->device_id, NULL,
xa_limit_32b, GFP_NOWAIT);
if (error < 0) {
pr_warn("Allocating idr failed, err: %d\n", error);
@@ -802,6 +802,13 @@ static int process_msg_open(struct rnbd_srv_session *srv_sess,
list_add(&srv_sess_dev->dev_list, &srv_dev->sess_dev_list);
mutex_unlock(&srv_dev->lock);
+ /*
+ * Nothing fails from here on, so let I/O messages find the sess_dev.
+ * The ID is reserved, so this store allocates nothing.
+ */
+ xa_store(&srv_sess->index_idr, srv_sess_dev->device_id, srv_sess_dev,
+ GFP_KERNEL);
+
rnbd_srv_info(srv_sess_dev, "Opened device '%s'\n", srv_dev->name);
kfree(full_path);
@@ -813,7 +820,6 @@ fill_response:
free_srv_sess_dev:
xa_erase(&srv_sess->index_idr, srv_sess_dev->device_id);
- synchronize_rcu();
kfree(srv_sess_dev);
srv_dev_put:
if (open_msg->access_mode != RNBD_ACCESS_RO) {