Re: [PATCH] fuse: propagate async RELEASE queue errno in fuse_file_put()

From: Li Wang

Date: Mon May 11 2026 - 04:45:28 EST


Hi Amir,

On 09/05/2026 22:46, Amir Goldstein wrote:
> On Sat, May 9, 2026 at 12:24 PM Li Wang <liwang@xxxxxxxxxx> wrote:
>>
>> fuse_file_put() queues asynchronous FUSE_RELEASE via fuse_simple_background().
>> When queueing fails, the failure branch always passed -ENOTCONN into
>> fuse_release_end(). fuse_simple_background() can however fail for multiple reasons
>> with different return values, such as -ENOMEM or -EINTR. Pass the actual negative
>> errno into fuse_release_end(). Currently, the callback does not interpret it,
>> but passing the real value avoids misleading future development or debug printf
>> that assumes -ENOTCONN meant disconnect.
>>
>
> Hi Li,
>
> If fuse_release_end() does not do anything with the error, just drop this
> argument.
>
> I see no point in this patch as is, serving some unknown future development.
> If future development needs the error, future developers can pass the error.
>
I would have loved to drop it, however, while fuse_file_put() calls
fuse_release_end() directly if sending the async request fails, it also
registers fuse_release_end() as the success callback. Consequently,
fuse_release_end() must strictly adhere to the callback signature; removing
any parameter would trigger a compilation error.

A similar pattern occurs when fuse_send_readpages() calls fuse_readpages_end().
In that case, if sending the request fails, fuse_readpages_end() is invoked
directly using the error value returned by the sending function as an argument.
Furthermore, the same applies to fuse_async_req_send() calling
fuse_aio_complete_req(). This patch aligns with those cases. I'll send out
a v2 patch with an updated commit message to clarify these points.
Looking forward to your feedback.

Thanks,
Li

> Thanks,
> Amir.
>
>> Add an explicit (void)error in fuse_release_end() so builds that enable
>> -Wunused-parameter (for example make W=3) stay clean.
>>
>> Signed-off-by: Li Wang <liwang@xxxxxxxxxx>
>> ---
>> fs/fuse/file.c | 11 ++++++++---
>> 1 file changed, 8 insertions(+), 3 deletions(-)
>>
>> diff --git a/fs/fuse/file.c b/fs/fuse/file.c
>> index 3bdab8d03373..8b7badb7721a 100644
>> --- a/fs/fuse/file.c
>> +++ b/fs/fuse/file.c
>> @@ -96,6 +96,8 @@ static void fuse_release_end(struct fuse_args *args, int error)
>> {
>> struct fuse_release_args *ra = container_of(args, typeof(*ra), args);
>>
>> + (void)error;
>> +
>> iput(ra->inode);
>> kfree(ra);
>> }
>> @@ -117,6 +119,8 @@ static void fuse_file_put(struct fuse_file *ff, bool sync)
>> fuse_simple_request(ff->fm, args);
>> fuse_release_end(args, 0);
>> } else {
>> + int err;
>> +
>> /*
>> * DAX inodes may need to issue a number of synchronous
>> * request for clearing the mappings.
>> @@ -124,9 +128,10 @@ static void fuse_file_put(struct fuse_file *ff, bool sync)
>> if (ra && ra->inode && FUSE_IS_DAX(ra->inode))
>> args->may_block = true;
>> args->end = fuse_release_end;
>> - if (fuse_simple_background(ff->fm, args,
>> - GFP_KERNEL | __GFP_NOFAIL))
>> - fuse_release_end(args, -ENOTCONN);
>> + err = fuse_simple_background(ff->fm, args,
>> + GFP_KERNEL | __GFP_NOFAIL);
>> + if (err)
>> + fuse_release_end(args, err);
>> }
>> kfree(ff);
>> }
>> --
>> 2.34.1
>>
>>