[PATCH v2] fuse: permit freezing while waiting for request answer

From: Sergey Senozhatsky

Date: Tue Aug 18 2026 - 22:43:00 EST


Suspend freezes tasks in random order and doesn't take into
consideration producer-consumer dependency that may exist
between tasks. One example where this can cause issues is:
fuse server getting frozen ahead of clients, which then get
stuck waiting for req answers that never come (the server
is already frozen).

Make all wait-event calls in request_wait_answer() freezer-friendly.

This, however, doesn't address all cases. E.g. in-place
PM-freeze of a request_wait_answer() task holding a contended
VFS lock still will block suspend.

Note: this uses TASK_FREEZABLE, not TASK_FREEZABLE_UNSAFE,
which may trigger debug_locks warning during suspend (if
request_wait_answer() task holds some locks at the time
of freeze.)

Signed-off-by: Sergey Senozhatsky <senozhatsky@xxxxxxxxxxxx>
---

fs/fuse/dev.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)

diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 34106f6e66a0..42098ddc2587 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -701,8 +701,9 @@ static void request_wait_answer(struct fuse_req *req)

if (!fch->no_interrupt) {
/* Any signal may interrupt this */
- err = wait_event_interruptible(req->waitq,
- test_bit(FR_FINISHED, &req->flags));
+ err = wait_event_state(req->waitq,
+ test_bit(FR_FINISHED, &req->flags),
+ (TASK_INTERRUPTIBLE | TASK_FREEZABLE));
if (!err)
return;

@@ -717,8 +718,9 @@ static void request_wait_answer(struct fuse_req *req)
bool removed;

/* Only fatal signals may interrupt this */
- err = wait_event_killable(req->waitq,
- test_bit(FR_FINISHED, &req->flags));
+ err = wait_event_state(req->waitq,
+ test_bit(FR_FINISHED, &req->flags),
+ (TASK_KILLABLE | TASK_FREEZABLE));
if (!err)
return;

@@ -740,7 +742,8 @@ static void request_wait_answer(struct fuse_req *req)
* Either request is already in userspace, or it was forced.
* Wait it out.
*/
- wait_event(req->waitq, test_bit(FR_FINISHED, &req->flags));
+ wait_event_state(req->waitq, test_bit(FR_FINISHED, &req->flags),
+ (TASK_UNINTERRUPTIBLE | TASK_FREEZABLE));
}

static void __fuse_request_send(struct fuse_req *req)
--
2.55.0.737.g08866a6d13-goog