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

Li Wang posted 1 patch 1 month ago
There is a newer version of this series
fs/fuse/file.c | 11 ++++++++---
1 file changed, 8 insertions(+), 3 deletions(-)
[PATCH] fuse: propagate async RELEASE queue errno in fuse_file_put()
Posted by Li Wang 1 month ago
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.

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@kylinos.cn>
---
 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
Re: [PATCH] fuse: propagate async RELEASE queue errno in fuse_file_put()
Posted by Amir Goldstein 1 month ago
On Sat, May 9, 2026 at 12:24 PM Li Wang <liwang@kylinos.cn> 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.

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@kylinos.cn>
> ---
>  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
>
>
Re: [PATCH] fuse: propagate async RELEASE queue errno in fuse_file_put()
Posted by Li Wang 1 month ago
Hi Amir,

On 09/05/2026 22:46, Amir Goldstein wrote:
> On Sat, May 9, 2026 at 12:24 PM Li Wang <liwang@kylinos.cn> 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@kylinos.cn>
>> ---
>>  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
>>
>>

[PATCH v2] fuse: propagate async RELEASE queue errno in fuse_file_put()
Posted by Li Wang 1 month ago
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(). 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.

The parameter "error" is currently unused in fuse_release_end().
While removing it seems like the better choice, 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. 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@kylinos.cn>
---
Changes since v1:
- Amend commit message to clarify the reasoning behind the code changes.

 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
Re: [PATCH v2] fuse: propagate async RELEASE queue errno in fuse_file_put()
Posted by Joanne Koong 1 month ago
On Mon, May 11, 2026 at 3:14 AM Li Wang <liwang@kylinos.cn> 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(). 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.
>
> The parameter "error" is currently unused in fuse_release_end().
> While removing it seems like the better choice, 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. 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@kylinos.cn>
> ---
> Changes since v1:
> - Amend commit message to clarify the reasoning behind the code changes.
>
>  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);
>                 }

Hi Li,

I'm not sure I see how this change is needed since fuse_release_end()
does nothing with the error arg today. afaict the (void)error pattern
isn't typical in-kernel since W=3 isn't a standard build target. I
think it might be best to just keep the existing code as is to reduce
churn, and then if fuse_release_end() later in the future gets updated
to use the error arg, this would make more sense as part of that
change.

Thanks,
Joanne

>                 kfree(ff);
>         }
> --
> 2.34.1
>