* [PATCH 6.18.y 2/4] fuse: split off fuse_args and related definitions into a separate header
2026-08-31 16:42 ` [PATCH 6.18.y 1/4] fuse: abort related layering cleanup Sasha Levin
@ 2026-08-31 16:42 ` Sasha Levin
2026-08-31 16:42 ` [PATCH 6.18.y 3/4] fuse: remove fm arg of args->end callback Sasha Levin
` (2 subsequent siblings)
3 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-08-31 16:42 UTC (permalink / raw)
To: stable; +Cc: Miklos Szeredi, Sasha Levin
From: Miklos Szeredi <mszeredi@redhat.com>
[ Upstream commit 229f9b9b66ab5be9e015422cf30b97740cfbdc8d ]
This is going to be used by both layers (transport and filesystem)
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Stable-dep-of: 64b0b5cacbd2 ("fuse: wait for FR_FINISHED on abort_on_kill to prevent use-after-free")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/fuse/args.h | 65 ++++++++++++++++++++++++++++++++++++++++++++++++
fs/fuse/fuse_i.h | 53 +--------------------------------------
2 files changed, 66 insertions(+), 52 deletions(-)
create mode 100644 fs/fuse/args.h
diff --git a/fs/fuse/args.h b/fs/fuse/args.h
new file mode 100644
index 0000000000000..12c94ece569fb
--- /dev/null
+++ b/fs/fuse/args.h
@@ -0,0 +1,65 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef _FS_FUSE_ARGS_H
+#define _FS_FUSE_ARGS_H
+
+#include <linux/types.h>
+
+struct fuse_mount;
+
+/** One input argument of a request */
+struct fuse_in_arg {
+ unsigned size;
+ const void *value;
+};
+
+/** One output argument of a request */
+struct fuse_arg {
+ unsigned size;
+ void *value;
+};
+
+struct fuse_args {
+ u64 nodeid;
+ u32 opcode;
+ u32 uid;
+ u32 gid;
+ u32 pid;
+ u8 in_numargs;
+ u8 out_numargs;
+ u8 ext_idx;
+ bool force:1;
+ bool noreply:1;
+ bool nocreds:1;
+ bool in_pages:1;
+ bool out_pages:1;
+ bool user_pages:1;
+ bool out_argvar:1;
+ bool page_zeroing:1;
+ bool page_replace:1;
+ bool may_block:1;
+ bool is_ext:1;
+ bool is_pinned:1;
+ bool invalidate_vmap:1;
+ bool abort_on_kill:1;
+ struct fuse_in_arg in_args[4];
+ struct fuse_arg out_args[2];
+ void (*end)(struct fuse_mount *fm, struct fuse_args *args, int error);
+ /* Used for kvec iter backed by vmalloc address */
+ void *vmap_base;
+};
+
+/** FUSE folio descriptor */
+struct fuse_folio_desc {
+ unsigned int length;
+ unsigned int offset;
+};
+
+struct fuse_args_pages {
+ struct fuse_args args;
+ struct folio **folios;
+ struct fuse_folio_desc *descs;
+ unsigned int num_folios;
+};
+
+#endif /* _FS_FUSE_ARGS_H */
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 8b745045f1ab3..aa8216c9308f8 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -13,6 +13,7 @@
# define pr_fmt(fmt) "fuse: " fmt
#endif
+#include "args.h"
#include <linux/fuse.h>
#include <linux/fs.h>
#include <linux/mount.h>
@@ -296,58 +297,6 @@ struct fuse_file {
bool flock:1;
};
-/** One input argument of a request */
-struct fuse_in_arg {
- unsigned size;
- const void *value;
-};
-
-/** One output argument of a request */
-struct fuse_arg {
- unsigned size;
- void *value;
-};
-
-/** FUSE folio descriptor */
-struct fuse_folio_desc {
- unsigned int length;
- unsigned int offset;
-};
-
-struct fuse_args {
- uint64_t nodeid;
- uint32_t opcode;
- uint8_t in_numargs;
- uint8_t out_numargs;
- uint8_t ext_idx;
- bool force:1;
- bool noreply:1;
- bool nocreds:1;
- bool in_pages:1;
- bool out_pages:1;
- bool user_pages:1;
- bool out_argvar:1;
- bool page_zeroing:1;
- bool page_replace:1;
- bool may_block:1;
- bool is_ext:1;
- bool is_pinned:1;
- bool invalidate_vmap:1;
- bool abort_on_kill:1;
- struct fuse_in_arg in_args[4];
- struct fuse_arg out_args[2];
- void (*end)(struct fuse_mount *fm, struct fuse_args *args, int error);
- /* Used for kvec iter backed by vmalloc address */
- void *vmap_base;
-};
-
-struct fuse_args_pages {
- struct fuse_args args;
- struct folio **folios;
- struct fuse_folio_desc *descs;
- unsigned int num_folios;
-};
-
struct fuse_release_args {
struct fuse_args args;
struct fuse_release_in inarg;
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 6.18.y 3/4] fuse: remove fm arg of args->end callback
2026-08-31 16:42 ` [PATCH 6.18.y 1/4] fuse: abort related layering cleanup Sasha Levin
2026-08-31 16:42 ` [PATCH 6.18.y 2/4] fuse: split off fuse_args and related definitions into a separate header Sasha Levin
@ 2026-08-31 16:42 ` Sasha Levin
2026-08-31 16:42 ` [PATCH 6.18.y 4/4] fuse: wait for FR_FINISHED on abort_on_kill to prevent use-after-free Sasha Levin
2026-09-09 12:33 ` [PATCH 6.18.y 1/4] fuse: abort related layering cleanup Greg KH
3 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-08-31 16:42 UTC (permalink / raw)
To: stable; +Cc: Miklos Szeredi, Sasha Levin
From: Miklos Szeredi <mszeredi@redhat.com>
[ Upstream commit a697d95fcdbb3bbe25cdc29db5542ddcebb831c1 ]
Only used by FUSE_INIT and CUSE_INIT, these can store the relevant pointer
in their structs derived from fuse_args.
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Stable-dep-of: 64b0b5cacbd2 ("fuse: wait for FR_FINISHED on abort_on_kill to prevent use-after-free")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/fuse/args.h | 2 +-
fs/fuse/cuse.c | 7 ++++---
fs/fuse/dev.c | 7 +++----
fs/fuse/file.c | 22 +++++++++-------------
fs/fuse/inode.c | 10 ++++++----
5 files changed, 23 insertions(+), 25 deletions(-)
diff --git a/fs/fuse/args.h b/fs/fuse/args.h
index 12c94ece569fb..ecfe51a192af0 100644
--- a/fs/fuse/args.h
+++ b/fs/fuse/args.h
@@ -44,7 +44,7 @@ struct fuse_args {
bool abort_on_kill:1;
struct fuse_in_arg in_args[4];
struct fuse_arg out_args[2];
- void (*end)(struct fuse_mount *fm, struct fuse_args *args, int error);
+ void (*end)(struct fuse_args *args, int error);
/* Used for kvec iter backed by vmalloc address */
void *vmap_base;
};
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index d90f138321fe9..7d9925dd2879a 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -306,6 +306,7 @@ struct cuse_init_args {
struct cuse_init_out out;
struct folio *folio;
struct fuse_folio_desc desc;
+ struct fuse_conn *fc;
};
/**
@@ -319,11 +320,10 @@ struct cuse_init_args {
* required data structures for it. Please read the comment at the
* top of this file for high level overview.
*/
-static void cuse_process_init_reply(struct fuse_mount *fm,
- struct fuse_args *args, int error)
+static void cuse_process_init_reply(struct fuse_args *args, int error)
{
- struct fuse_conn *fc = fm->fc;
struct cuse_init_args *ia = container_of(args, typeof(*ia), ap.args);
+ struct fuse_conn *fc = ia->fc;
struct fuse_args_pages *ap = &ia->ap;
struct cuse_conn *cc = fc_to_cc(fc), *pos;
struct cuse_init_out *arg = &ia->out;
@@ -468,6 +468,7 @@ static int cuse_send_init(struct cuse_conn *cc)
ap->descs = &ia->desc;
ia->folio = folio;
ia->desc.length = ap->args.out_args[1].size;
+ ia->fc = &cc->fc;
ap->args.end = cuse_process_init_reply;
rc = fuse_simple_background(fm, &ap->args, GFP_KERNEL);
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 934f9ac5056ed..50012b0b1258a 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -512,7 +512,7 @@ void fuse_request_end(struct fuse_req *req)
}
if (test_bit(FR_ASYNC, &req->flags))
- req->args->end(fm, req->args, req->out.h.error);
+ req->args->end(req->args, req->out.h.error);
put_request:
fuse_put_request(req);
}
@@ -1859,8 +1859,7 @@ struct fuse_retrieve_args {
struct fuse_notify_retrieve_in inarg;
};
-static void fuse_retrieve_end(struct fuse_mount *fm, struct fuse_args *args,
- int error)
+static void fuse_retrieve_end(struct fuse_args *args, int error)
{
struct fuse_retrieve_args *ra =
container_of(args, typeof(*ra), ap.args);
@@ -1955,7 +1954,7 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode,
err = fuse_simple_notify_reply(fm, args, outarg->notify_unique);
if (err)
- fuse_retrieve_end(fm, args, err);
+ fuse_retrieve_end(args, err);
return err;
}
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 585dd90361b65..f3b4d6ae0858a 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -91,8 +91,7 @@ static struct fuse_file *fuse_file_get(struct fuse_file *ff)
return ff;
}
-static void fuse_release_end(struct fuse_mount *fm, struct fuse_args *args,
- int error)
+static void fuse_release_end(struct fuse_args *args, int error)
{
struct fuse_release_args *ra = container_of(args, typeof(*ra), args);
@@ -112,15 +111,15 @@ static void fuse_file_put(struct fuse_file *ff, bool sync)
if (!args) {
/* Do nothing when server does not implement 'opendir' */
} else if (args->opcode == FUSE_RELEASE && ff->fm->fc->no_open) {
- fuse_release_end(ff->fm, args, 0);
+ fuse_release_end(args, 0);
} else if (sync) {
fuse_simple_request(ff->fm, args);
- fuse_release_end(ff->fm, args, 0);
+ fuse_release_end(args, 0);
} else {
args->end = fuse_release_end;
if (fuse_simple_background(ff->fm, args,
GFP_KERNEL | __GFP_NOFAIL))
- fuse_release_end(ff->fm, args, -ENOTCONN);
+ fuse_release_end(args, -ENOTCONN);
}
kfree(ff);
}
@@ -709,8 +708,7 @@ static void fuse_io_free(struct fuse_io_args *ia)
kfree(ia);
}
-static void fuse_aio_complete_req(struct fuse_mount *fm, struct fuse_args *args,
- int err)
+static void fuse_aio_complete_req(struct fuse_args *args, int err)
{
struct fuse_io_args *ia = container_of(args, typeof(*ia), ap.args);
struct fuse_io_priv *io = ia->io;
@@ -758,7 +756,7 @@ static ssize_t fuse_async_req_send(struct fuse_mount *fm,
ia->ap.args.may_block = io->should_dirty;
err = fuse_simple_background(fm, &ia->ap.args, GFP_KERNEL);
if (err)
- fuse_aio_complete_req(fm, &ia->ap.args, err);
+ fuse_aio_complete_req(&ia->ap.args, err);
return num_bytes;
}
@@ -881,8 +879,7 @@ static int fuse_iomap_read_folio_range(const struct iomap_iter *iter,
return fuse_do_readfolio(file, folio, off, len);
}
-static void fuse_readpages_end(struct fuse_mount *fm, struct fuse_args *args,
- int err)
+static void fuse_readpages_end(struct fuse_args *args, int err)
{
int i;
struct fuse_io_args *ia = container_of(args, typeof(*ia), ap.args);
@@ -947,7 +944,7 @@ static void fuse_send_readpages(struct fuse_io_args *ia, struct file *file,
res = fuse_simple_request(fm, &ap->args);
err = res < 0 ? res : 0;
}
- fuse_readpages_end(fm, &ap->args, err);
+ fuse_readpages_end(&ap->args, err);
}
static void fuse_readahead(struct readahead_control *rac)
@@ -1950,8 +1947,7 @@ __acquires(fi->lock)
}
}
-static void fuse_writepage_end(struct fuse_mount *fm, struct fuse_args *args,
- int error)
+static void fuse_writepage_end(struct fuse_args *args, int error)
{
struct fuse_writepage_args *wpa =
container_of(args, typeof(*wpa), ia.ap.args);
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 399298816dea0..7464ee8622ac9 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1311,13 +1311,14 @@ struct fuse_init_args {
struct fuse_args args;
struct fuse_init_in in;
struct fuse_init_out out;
+ struct fuse_mount *fm;
};
-static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
- int error)
+static void process_init_reply(struct fuse_args *args, int error)
{
- struct fuse_conn *fc = fm->fc;
struct fuse_init_args *ia = container_of(args, typeof(*ia), args);
+ struct fuse_mount *fm = ia->fm;
+ struct fuse_conn *fc = fm->fc;
struct fuse_init_out *arg = &ia->out;
bool ok = true;
@@ -1486,6 +1487,7 @@ static struct fuse_init_args *fuse_new_init(struct fuse_mount *fm)
ia = kzalloc(sizeof(*ia), GFP_KERNEL | __GFP_NOFAIL);
+ ia->fm = fm;
ia->in.major = FUSE_KERNEL_VERSION;
ia->in.minor = FUSE_KERNEL_MINOR_VERSION;
ia->in.max_readahead = fm->sb->s_bdi->ra_pages * PAGE_SIZE;
@@ -1559,7 +1561,7 @@ int fuse_send_init(struct fuse_mount *fm)
if (!err)
return 0;
}
- process_init_reply(fm, &ia->args, err);
+ process_init_reply(&ia->args, err);
if (fm->fc->conn_error)
return -ENOTCONN;
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH 6.18.y 4/4] fuse: wait for FR_FINISHED on abort_on_kill to prevent use-after-free
2026-08-31 16:42 ` [PATCH 6.18.y 1/4] fuse: abort related layering cleanup Sasha Levin
2026-08-31 16:42 ` [PATCH 6.18.y 2/4] fuse: split off fuse_args and related definitions into a separate header Sasha Levin
2026-08-31 16:42 ` [PATCH 6.18.y 3/4] fuse: remove fm arg of args->end callback Sasha Levin
@ 2026-08-31 16:42 ` Sasha Levin
2026-09-09 12:33 ` [PATCH 6.18.y 1/4] fuse: abort related layering cleanup Greg KH
3 siblings, 0 replies; 6+ messages in thread
From: Sasha Levin @ 2026-08-31 16:42 UTC (permalink / raw)
To: stable
Cc: Rochan Avlur, syzbot+d6540a3fa1626e11360d, Miklos Szeredi,
Sasha Levin
From: Rochan Avlur <rochan.avlur@gmail.com>
[ Upstream commit 64b0b5cacbd2fea88001464cb712c9dfc795b26e ]
The abort_on_kill path in request_wait_answer() calls fuse_abort_conn()
and returns without waiting for FR_FINISHED. If fuse_dev_do_write() is
concurrently processing the same request (FR_LOCKED set), the caller
frees req->args while it is still being accessed, causing a
use-after-free.
Fix this by jumping to the existing wait_event(FR_FINISHED) instead of
returning early. The wait will not hang because fuse_abort_conn()
ensures all requests are ended.
Reported-by: syzbot+d6540a3fa1626e11360d@syzkaller.appspotmail.com
Fixes: 204aa22a686b ("fuse: abort on fatal signal during sync init")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Rochan Avlur <rochan.avlur@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/fuse/dev.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 50012b0b1258a..9f1f81e66cace 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -580,7 +580,7 @@ static void request_wait_answer(struct fuse_req *req)
if (req->args->abort_on_kill) {
fuse_chan_abort(fch, false);
- return;
+ goto wait_for_finish;
}
if (test_bit(FR_URING, &req->flags))
@@ -591,6 +591,7 @@ static void request_wait_answer(struct fuse_req *req)
return;
}
+wait_for_finish:
/*
* Either request is already in userspace, or it was forced.
* Wait it out.
--
2.53.0
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH 6.18.y 1/4] fuse: abort related layering cleanup
2026-08-31 16:42 ` [PATCH 6.18.y 1/4] fuse: abort related layering cleanup Sasha Levin
` (2 preceding siblings ...)
2026-08-31 16:42 ` [PATCH 6.18.y 4/4] fuse: wait for FR_FINISHED on abort_on_kill to prevent use-after-free Sasha Levin
@ 2026-09-09 12:33 ` Greg KH
3 siblings, 0 replies; 6+ messages in thread
From: Greg KH @ 2026-09-09 12:33 UTC (permalink / raw)
To: Sasha Levin; +Cc: stable, Miklos Szeredi
On Mon, Aug 31, 2026 at 12:42:53PM -0400, Sasha Levin wrote:
> From: Miklos Szeredi <mszeredi@redhat.com>
>
> [ Upstream commit 4eeb5e6cb0fd89b343fcf755ae3aad76fdb5b2c2 ]
>
> - rename fuse_abort_conn() to fuse_chan_abort(), pass fuse_chan pointer
> instead of fuse_conn
>
> - pass an abort_with_err argument that tells fuse_dev_(read|write) to
> return with ECONNABORTED instead of ENODEV
>
> - move fc->aborted to fch->abort_with_err
>
> - rename fuse_wait_aborted() to fuse_chan_wait_aborted()
>
> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
>
> [ 6.18 has no "struct fuse_chan" -- the connection object still plays
> that role, and the surrounding series that splits it out is not in
> stable. Adapted as follows:
>
> - the renames (fuse_abort_conn() -> fuse_chan_abort(),
> fuse_wait_aborted() -> fuse_chan_wait_aborted(), the "abort_conn"
> label in fuse_check_timeout() -> "chan_abort") and the new
> abort_with_err argument are taken as-is, but both helpers keep
> taking "struct fuse_conn *".
>
> - the "move fc->aborted to fch->abort_with_err" bullet is dropped:
> there is no fuse_chan to move the flag into, so fc->aborted stays
> in struct fuse_conn. fuse_chan_abort() only ever *sets* it, as
> control.c did before, rather than assigning the new argument
> unconditionally the way upstream does: on this tree the flag is
> write-once and is what makes fuse_dev_do_read() and
> fuse_uring_cmd() report ECONNABORTED instead of ENODEV, so letting
> a later abort with abort_with_err=false clear it (umount -f,
> fuse_conn_destroy(), fuse_dev_release(), the timeout worker) would
> change what userspace sees after a sysfs abort on an abort_err
> mount. Consequently the fuse_dev_i.h and dev_uring.c hunks, which
> only rename the field access, are dropped as well.
>
> - fs/fuse/dev.h and fs/fuse/req_timeout.c do not exist here: the
> declarations stay in fuse_i.h and fuse_check_timeout() lives in
> dev.c, so those two hunks were replayed there.
>
> - in request_wait_answer() the connection pointer is named "fch",
> matching the name upstream gives it in 28d733cc3ecad ("fuse: change
> req->fm to req->chan"), so that the follow-up fix applies here
> unchanged. ]
>
> [ sashal: Reduced backport -- upstream 4eeb5e6cb0fd8 touches 9 file(s), this
> backport carries 5. Not backported here:
> fs/fuse/dev.h
> fs/fuse/dev_uring.c
> fs/fuse/fuse_dev_i.h
> fs/fuse/req_timeout.c
> This note is generated from the file lists only; see the resolution record
> for the reasoning. ]
>
> Stable-dep-of: 64b0b5cacbd2 ("fuse: wait for FR_FINISHED on abort_on_kill to prevent use-after-free")
> Signed-off-by: Sasha Levin <sashal@kernel.org>
> ---
> fs/fuse/control.c | 4 +---
> fs/fuse/cuse.c | 4 ++--
> fs/fuse/dev.c | 35 +++++++++++++++++++----------------
> fs/fuse/fuse_i.h | 4 ++--
> fs/fuse/inode.c | 6 +++---
> 5 files changed, 27 insertions(+), 26 deletions(-)
>
> diff --git a/fs/fuse/control.c b/fs/fuse/control.c
> index 2e300f6d646c3..5536d6ee65514 100644
> --- a/fs/fuse/control.c
> +++ b/fs/fuse/control.c
> @@ -37,9 +37,7 @@ static ssize_t fuse_conn_abort_write(struct file *file, const char __user *buf,
> {
> struct fuse_conn *fc = fuse_ctl_file_conn_get(file);
> if (fc) {
> - if (fc->abort_err)
> - fc->aborted = true;
> - fuse_abort_conn(fc);
> + fuse_chan_abort(fc, fc->abort_err);
> fuse_conn_put(fc);
> }
> return count;
> diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
> index 2bb98bf81b079..d90f138321fe9 100644
> --- a/fs/fuse/cuse.c
> +++ b/fs/fuse/cuse.c
> @@ -425,7 +425,7 @@ static void cuse_process_init_reply(struct fuse_mount *fm,
> err_region:
> unregister_chrdev_region(devt, 1);
> err:
> - fuse_abort_conn(fc);
> + fuse_chan_abort(fc, false);
> goto out;
> }
>
> @@ -593,7 +593,7 @@ static ssize_t cuse_class_abort_store(struct device *dev,
> {
> struct cuse_conn *cc = dev_get_drvdata(dev);
>
> - fuse_abort_conn(&cc->fc);
> + fuse_chan_abort(&cc->fc, false);
> return count;
> }
> static DEVICE_ATTR(abort, 0200, NULL, cuse_class_abort_store);
> diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
> index 77c3982bca3d7..934f9ac5056ed 100644
> --- a/fs/fuse/dev.c
> +++ b/fs/fuse/dev.c
> @@ -87,13 +87,13 @@ void fuse_check_timeout(struct work_struct *work)
> expired = fuse_request_expired(fc, &fiq->pending);
> spin_unlock(&fiq->lock);
> if (expired)
> - goto abort_conn;
> + goto chan_abort;
>
> spin_lock(&fc->bg_lock);
> expired = fuse_request_expired(fc, &fc->bg_queue);
> spin_unlock(&fc->bg_lock);
> if (expired)
> - goto abort_conn;
> + goto chan_abort;
>
> spin_lock(&fc->lock);
> if (!fc->connected) {
> @@ -107,7 +107,7 @@ void fuse_check_timeout(struct work_struct *work)
> fuse_fpq_processing_expired(fc, fpq->processing)) {
> spin_unlock(&fpq->lock);
> spin_unlock(&fc->lock);
> - goto abort_conn;
> + goto chan_abort;
> }
>
> spin_unlock(&fpq->lock);
> @@ -115,15 +115,15 @@ void fuse_check_timeout(struct work_struct *work)
> spin_unlock(&fc->lock);
>
> if (fuse_uring_request_expired(fc))
> - goto abort_conn;
> + goto chan_abort;
>
> out:
> queue_delayed_work(system_percpu_wq, &fc->timeout.work,
> fuse_timeout_timer_freq);
> return;
>
> -abort_conn:
> - fuse_abort_conn(fc);
> +chan_abort:
> + fuse_chan_abort(fc, false);
> }
>
> static void fuse_request_init(struct fuse_mount *fm, struct fuse_req *req)
> @@ -180,7 +180,7 @@ static void fuse_drop_waiting(struct fuse_conn *fc)
> {
> /*
> * lockess check of fc->connected is okay, because atomic_dec_and_test()
> - * provides a memory barrier matched with the one in fuse_wait_aborted()
> + * provides a memory barrier matched with the one in fuse_chan_wait_aborted()
> * to ensure no wake-up is missed.
> */
> if (atomic_dec_and_test(&fc->num_waiting) &&
> @@ -551,11 +551,11 @@ bool fuse_remove_pending_req(struct fuse_req *req, spinlock_t *lock)
>
> static void request_wait_answer(struct fuse_req *req)
> {
> - struct fuse_conn *fc = req->fm->fc;
> - struct fuse_iqueue *fiq = &fc->iq;
> + struct fuse_conn *fch = req->fm->fc;
> + struct fuse_iqueue *fiq = &fch->iq;
> int err;
>
> - if (!fc->no_interrupt) {
> + if (!fch->no_interrupt) {
> /* Any signal may interrupt this */
> err = wait_event_interruptible(req->waitq,
> test_bit(FR_FINISHED, &req->flags));
> @@ -579,7 +579,7 @@ static void request_wait_answer(struct fuse_req *req)
> return;
>
> if (req->args->abort_on_kill) {
> - fuse_abort_conn(fc);
> + fuse_chan_abort(fch, false);
> return;
> }
>
> @@ -1491,7 +1491,7 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
> spin_lock(&fpq->lock);
> /*
> * Must not put request on fpq->io queue after having been shut down by
> - * fuse_abort_conn()
> + * fuse_chan_abort()
> */
> if (!fpq->connected) {
> req->out.h.error = err = -ECONNABORTED;
> @@ -2475,10 +2475,13 @@ static void end_polls(struct fuse_conn *fc)
> * is OK, the request will in that case be removed from the list before we touch
> * it.
> */
> -void fuse_abort_conn(struct fuse_conn *fc)
> +void fuse_chan_abort(struct fuse_conn *fc, bool abort_with_err)
> {
> struct fuse_iqueue *fiq = &fc->iq;
>
> + if (abort_with_err)
> + fc->aborted = true;
> +
> spin_lock(&fc->lock);
> if (fc->connected) {
> struct fuse_dev *fud;
> @@ -2547,9 +2550,9 @@ void fuse_abort_conn(struct fuse_conn *fc)
> spin_unlock(&fc->lock);
> }
> }
> -EXPORT_SYMBOL_GPL(fuse_abort_conn);
> +EXPORT_SYMBOL_GPL(fuse_chan_abort);
>
> -void fuse_wait_aborted(struct fuse_conn *fc)
> +void fuse_chan_wait_aborted(struct fuse_conn *fc)
> {
> /* matches implicit memory barrier in fuse_drop_waiting() */
> smp_mb();
> @@ -2579,7 +2582,7 @@ int fuse_dev_release(struct inode *inode, struct file *file)
> /* Are we the last open device? */
> if (atomic_dec_and_test(&fc->dev_count)) {
> WARN_ON(fc->iq.fasync != NULL);
> - fuse_abort_conn(fc);
> + fuse_chan_abort(fc, false);
> }
> fuse_dev_free(fud);
> }
> diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
> index c288f28f6c6ea..8b745045f1ab3 100644
> --- a/fs/fuse/fuse_i.h
> +++ b/fs/fuse/fuse_i.h
> @@ -1272,8 +1272,8 @@ void fuse_request_assign_unique(struct fuse_iqueue *fiq, struct fuse_req *req);
> void fuse_request_end(struct fuse_req *req);
>
> /* Abort all requests */
> -void fuse_abort_conn(struct fuse_conn *fc);
> -void fuse_wait_aborted(struct fuse_conn *fc);
> +void fuse_chan_abort(struct fuse_conn *fc, bool abort_with_err);
> +void fuse_chan_wait_aborted(struct fuse_conn *fc);
>
> /* Check if any requests timed out */
> void fuse_check_timeout(struct work_struct *work);
> diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
> index e9ed693fc7b37..399298816dea0 100644
> --- a/fs/fuse/inode.c
> +++ b/fs/fuse/inode.c
> @@ -621,7 +621,7 @@ static void fuse_umount_begin(struct super_block *sb)
> if (fc->no_force_umount)
> return;
>
> - fuse_abort_conn(fc);
> + fuse_chan_abort(fc, false);
>
> // Only retire block-device-based superblocks.
> if (sb->s_bdev != NULL)
> @@ -2099,8 +2099,8 @@ void fuse_conn_destroy(struct fuse_mount *fm)
> if (fc->destroy)
> fuse_send_destroy(fm);
>
> - fuse_abort_conn(fc);
> - fuse_wait_aborted(fc);
> + fuse_chan_abort(fc, false);
> + fuse_chan_wait_aborted(fc);
>
> if (!list_empty(&fc->entry)) {
> mutex_lock(&fuse_mutex);
> --
> 2.53.0
>
>
Series did not apply :(
^ permalink raw reply [flat|nested] 6+ messages in thread