[PATCH v1 2/2] fuse: publish io-uring queues with release semantics
Joanne Koong <[email protected]> Mon, 13 Jul 2026 10:53:45 -0700
| Newsgroups | dev.linux.lists.fuse-devel,org.kernel.vger.stable |
|---|---|
| Message-ID | <[email protected]> |
fuse_uring_create_queue() initializes a fuse_ring_queue and then
publishes the pointer into ring->queues[qid] with WRITE_ONCE() under the
fch->lock. On the reader side, fuse_uring_register() reads that pointer
on a fast path locklessly with
queue = ring->queues[qid];
There's no barrier that orders the initialization/setup of the queue's
fields and the WRITE_ONCE() that publishes the queue. As a result, the
lockless concurrent reader can see a non-null queue but uninitialized
queue fields (eg spinlock and list heads) and then operate on
uninitialized memory.
Publish the queue with smp_store_release() and read it on the lockless
fast path with smp_load_acquire().
Fixes: 24fe962c86f5 ("fuse: {io-uring} Handle SQEs - register commands")
Cc: [email protected]
Signed-off-by: Joanne Koong <[email protected]>
---
fs/fuse/dev_uring.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c
index 77c8cec43d9c..0ea142d6670b 100644
--- a/fs/fuse/dev_uring.c
+++ b/fs/fuse/dev_uring.c
@@ -321,9 +321,12 @@ static struct fuse_ring_queue *fuse_uring_create_queue(struct fuse_ring *ring,
}
/*
- * write_once and lock as the caller mostly doesn't take the lock at all
+ * fch->lock serializes concurrent creators for this qid.
+ * smp_store_release() is for the lockless reader in
+ * fuse_uring_register(), which pairs it with smp_load_acquire() and
+ * must see the fully initialized queue if it sees a non-null queue
*/
- WRITE_ONCE(ring->queues[qid], queue);
+ smp_store_release(&ring->queues[qid], queue);
spin_unlock(&fch->lock);
return queue;
@@ -1191,7 +1194,8 @@ static int fuse_uring_register(struct io_uring_cmd *cmd,
return -EINVAL;
}
- queue = ring->queues[qid];
+ /* Pairs with smp_store_release() in fuse_uring_create_queue() */
+ queue = smp_load_acquire(&ring->queues[qid]);
if (!queue) {
queue = fuse_uring_create_queue(ring, qid);
if (!queue)
--
2.52.0