Re: [PATCH v7 1/6] fuse: decouple fuse_ring creation from ent registration

Bernd Schubert <[email protected]>
Newsgroups dev.linux.lists.fuse-devel
Message-ID <[email protected]>

On 8/19/26 22:29, Joanne Koong wrote:
> On Wed, Aug 19, 2026 at 1:05 PM Bernd Schubert <[email protected]> wrote:
>>
>>
>>
>> On 8/19/26 19:56, Joanne Koong wrote:
>>> On Wed, Aug 19, 2026 at 4:35 AM Miklos Szeredi <[email protected]> wrote:
>>>>
>>>> On Fri, 14 Aug 2026 at 21:00, Joanne Koong <[email protected]> wrote:
>>>>>
>>>>> Currently, the connection's fuse_ring is created lazily on the first
>>>>> FUSE_IO_URING_CMD_REGISTER command. A server registers entries from one
>>>>> thread per queue (one per CPU) and those threads issue their first
>>>>> REGISTER command concurrently. They then race to create the single
>>>>> per-connection fuse_ring, which required open-coded handling in
>>>>> fuse_uring_create() to detect and protect against concurrent creations.
>>>>>
>>>>> Decouple fuse_ring creation from ent registration and move it to
>>>>> FUSE_INIT reply processing after a server has negotiated and set
>>>>> FUSE_OVER_IO_URING. The ring is published before the connection is
>>>>> marked initialized. fuse_uring_register() no longer creates the ring and
>>>>> it instead uses the ring set up at init time.
>>>>
>>>> I tested this with loraw (a "raw" loopback tester that doesn't use
>>>> libfuse) and it fails with
>>>>
>>>> root@kvm:~# ./loraw -u  /mnt/fuse
>>>> loraw: loraw.c:1010: lo_start_uring: Assertion `!cqe->res' failed.
>>>>
>>>> cqe->res is -22 (EINVAL).
>>>>
>>>> Attaching the reproducer.  To compile:
>>>>
>>>> cp $(KERNEL_TREE)/include/uapi/linux/fuse.h fuse_kernel.h
>>>> gcc loraw.c -oloraw -luring
>>>>
>>>
>>> Thanks for attaching the repro.
>>>
>>> This is happening because this patch uses the FUSE_OVER_IO_URING init
>>> reply as a signal that the ring should be created, but I missed that
>>> the FUSE_OVER_IO_URING reply is *optional*.
>>>
>>> Prior to this patch, there's two scenarios:
>>> a) server sets FUSE_OVER_IO_URING reply at init time - requests will
>>> automatically block until fuse-io-uring is completely set up
>>> b) server does not set FUSE_OVER_IO_URING but later sends uring
>>> register request - requests will continue along /dev/fuse path until
>>> fuse-io-uring is completely set up
>>>
>>> Libfuse sets FUSE_OVER_IO_URING in the reply, but the loraw.c server does not.
>>>
>>> I think the best way to fix this is to have the ring creation happen
>>> when the kernel receives the first io-uring command instead of at
>>> FUSE_INIT or at FUSE_IO_URING_CMD_REGISTER ent creation time, given
>>> that FUSE_IO_URING_ADD_QUEUE needs the ring to exist:
>>
>> I don't think we should allow io-uring without FUSE_OVER_IO_URING and
>> I really thought that was disabled.
> 
> This is pre-existing behavior that's been there since the beginning
> (kernel version 6.14) [1]. I don't think we can change this now, or
> it'll break backwards compatibility, like Miklos's loraw program.
> 
>>
>> <... checking the code ...>
>>
>> I'm on a ublk branch without your commits a applied, i.e. plain upstream 7.2 fuse
>>
>> fuse_uring_cmd()
>>         /* Once a connection has io-uring enabled on it, it can't be disabled */
>>         if (!enable_uring && !fch->io_uring) {
>>                 pr_info_ratelimited("fuse-io-uring is disabled\n");
>>                 return -EOPNOTSUPP;
>>         }
>>
>>
>>
>> In process_init_reply()
>>
>> if (flags & FUSE_OVER_IO_URING && fuse_uring_enabled())
>>     fuse_chan_io_uring_enable(fc->chan);
>>
> 
> The condition check in fuse_uring_cmd() is an && and not an ||. It

Aaaarg. That makes the entire condition useless :(

> doesn't enforce that the server must have sent over FUSE_OVER_IO_URING
> in the init reply to use fuse io-uring. With enable_uring=1 (which is
> needed for the kernel to advertise FUSE_OVER_IO_URING in the init
> request in the first place), the fuse io-uring logic proceeds
> regardless of whether the server replied with the FUSE_OVER_IO_URING
> flag or not.
> 
> Thanks,
> Joanne
> 
> [1] https://elixir.bootlin.com/linux/v6.14-rc1/source/fs/fuse/inode.c#L1455

The comment there is definitely outdated, at least it was *supposed* to.

Well, then we have a problem because we have a lock order inversion
issue. After adding in the reduce-queue series I had planned to work on
distributing fch->num_background among queues, so that each queue gets
its own num_background, so that holding two locks like in
fuse_uring_queue_bq_req() wouldn't be needed anymore.

Also again, without FUSE_OVER_IO_URING reply the condition in
fuse_block_alloc() doesn't make any sense.


Thanks,
Bernd
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.