Re: [PATCH v5 4/7] fuse: {io-uring} Allow reduced number of ring queues
Bernd Schubert <[email protected]> Tue, 23 Jun 2026 01:52:13 +0200
| Newsgroups | dev.linux.lists.fuse-devel |
|---|---|
| Message-ID | <[email protected]> |
On 6/23/26 01:32, Joanne Koong wrote: > zOn Fri, Jun 12, 2026 at 7:24 PM Joanne Koong <[email protected]> wrote: >> >> On Thu, May 28, 2026 at 3:55 PM Bernd Schubert via B4 Relay >> <[email protected]> wrote: >>> >>> From: Bernd Schubert <[email protected]> >>> >>> Queues selection (fuse_uring_get_queue) can handle reduced number >>> queues - using io-uring is possible now even with a single >>> queue and entry. >>> >>> The FUSE_URING_REDUCED_Q flag is introduced tell fuse server that >>> reduced queues are possible, i.e. if the flag is set, fuse server >>> is free to reduce number queues. >>> >>> Notheworth is also that a fuse-io-uring is now marked as ready >>> after the fist queue was created. >>> >>> Signed-off-by: Bernd Schubert <[email protected]> >>> --- >>> fs/fuse/dev_uring.c | 171 +++++++++++++++++++++++++++------------------- >>> fs/fuse/dev_uring_i.h | 3 + >>> fs/fuse/inode.c | 2 +- >>> include/uapi/linux/fuse.h | 10 ++- >>> 4 files changed, 112 insertions(+), 74 deletions(-) >>> >>> diff --git a/fs/fuse/dev_uring.c b/fs/fuse/dev_uring.c >>> index 497093384c31e729053d2f5046c9ec59461ac035..d02266b483c89d105bd6301133820697f7caba9c 100644 >>> --- a/fs/fuse/dev_uring.c >>> +++ b/fs/fuse/dev_uring.c >>> @@ -373,6 +397,30 @@ 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 >>> */ >>> WRITE_ONCE(ring->queues[qid], queue); >>> + >>> + /* Static mapping from cpu to per numa queues */ >>> + node = cpu_to_node(qid); >>> + fuse_uring_cpu_qid_mapping(ring, qid, &ring->numa_q_map[node], node); >> >> Hi Bernd, >> >> I don't think we can assume node is within the bounds of numa_q_map. >> numa_q_map gets allocated with num_online_nodes() # of entries but I >> think the node returned in cpu_to_node() can exceed that if some nodes >> were offline when we computed num_online_nodes() (eg num_online_nodes >> = 2, thhe 2 online nodes are 0 and 3, while 1 and 2 are offline). >> >>> + >>> + /* global mapping */ >>> + fuse_uring_cpu_qid_mapping(ring, qid, &ring->q_map, -1); >>> + >>> + /* >>> + * Pairs with smp_load_acquire() in fuse_uring_select_queue(). >>> + * Released before the per-numa bump below so that observing >>> + * numa_q_map[node].nr_queues > 0 implies q_map.nr_queues > 0. >>> + */ >>> + smp_store_release(&ring->q_map.nr_queues, >>> + ring->q_map.nr_queues + 1); >>> + >>> + /* >>> + * smp_store_release, as the variable is read without fc->lock and >>> + * we need to avoid compiler re-ordering of updating the nr_queues >>> + * and setting ring->numa_queues[node].cpu_to_qid above >>> + */ >>> + smp_store_release(&ring->numa_q_map[node].nr_queues, >>> + ring->numa_q_map[node].nr_queues + 1); >>> + >>> spin_unlock(&fch->lock); >>> >>> return queue; >>> >>> @@ -1186,7 +1180,19 @@ static int fuse_uring_register(struct io_uring_cmd *cmd, >>> if (IS_ERR(ent)) >>> return PTR_ERR(ent); >>> >>> - fuse_uring_do_register(ent, cmd, issue_flags); >>> + fuse_uring_prepare_cancel(cmd, issue_flags, ent); >>> + if (!READ_ONCE(ring->ready)) { >>> + WRITE_ONCE(fiq->ops, &fuse_io_uring_ops); >>> + WRITE_ONCE(ring->ready, true); >>> + wake_up_all(&fch->blocked_waitq); >>> + } >> >> I thought we had agreed at LSF that userspace would declare the number >> of queues upfront and dispatch would be gated until all of them have >> finished setup/registration rather than going ready when the first >> entry in a queue gets registered? Did the plan change or am I >> misremembering? >> >> I still have the same thoughts as previously [1] about it. I really >> don't think we should allow requests to go through io-uring while >> io-uring setup is still happening. If we want to add dynamic queue >> addition in the future, we could always do that later through a new > > Hi Bernd, > > What do you think about dropping FUSE_URING_REDUCED_Q and reframing > this series around dynamic queue addition instead? I don't mean to add > more work to your plate, but my main reason is the uapi. REDUCED_Q is > a narrow flag that's a subset of dynamic addition. Exposing general > queue addition would line up with the decoupled queue-creation uapi > the bufpool work will use, and it'd be more cohesive with the future > feature to dynamically remove queues. > > I think this series already has the bulk of the logic for dynamic > addition anyways. The main missing piece looks like adding > infrastructure to publish the mapping as an immutable RCU snapshot > rather than mutating it in place, so a reader never sees a > partially-built mapping. > > What are your thoughts? Except of libfuse not being ready to create queues on demand, the series basically supports that in kernel. And I was also thinking to use CU to update the mapping. However, I'm lost about the relation of buf pools. I very much disagree that adding buf pools has a relation to queues. Unless you want to make it 2D, which gets complex to find the right queue. Reasons: 1) If I start a queue in libfuse with a 1MB buffer and later see that it gets used, libfuse should add more buffers. However, I would not want it to add queues, unless I see that that ring threads occupy all of the core. 2) Lowest latency is still achieved with one queue per cpu - especially here it makes sense to have a very low buffer usage and to increase it if needed. 3) At least one customer at DDN sets a very specific cpu configuration, using more cores is strictly forbidden. Thanks, Bernd