Hi,
We are seeing a number of cases when blocked fuse requests prevent
the system from suspending, which is a little important on laptops.
Usually something like this:
[ 36.281038] Freezing user space processes
[ 56.284961] Freezing user space processes failed after 20.003 seconds (1 tasks refusing to freeze, wq_busy=0):
[ 56.285069] task:secagentd state:D stack:0 pid:1792 ppid:1711 flags:0x00004006
[ 56.285084] Call Trace:
[ 56.285091] <TASK>
[ 56.285111] schedule+0x612/0x2230
[ 56.285136] fuse_get_req+0x108/0x2d0
[ 56.285179] fuse_simple_request+0x40/0x630
[ 56.285203] fuse_getxattr+0x15d/0x1c0
[...]
Which looks like wait_event_killable_exclusive() in fuse_get_req().
And we were wondering if we could do something about it. For example,
perhaps, something like:
---
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index f182a4ca1bb32..587cea3a0407d 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -241,7 +241,7 @@ static struct fuse_req *fuse_get_req(struct fuse_conn *fc, bool for_background)
if (fuse_block_alloc(fc, for_background)) {
err = -EINTR;
- if (wait_event_killable_exclusive(fc->blocked_waitq,
+ if (wait_event_freezable_killable_exclusive(fc->blocked_waitq,
!fuse_block_alloc(fc, for_background)))
goto out;
}
diff --git a/include/linux/wait.h b/include/linux/wait.h
index 5b65f720261a9..1c8fdf1e02785 100644
--- a/include/linux/wait.h
+++ b/include/linux/wait.h
@@ -628,6 +628,19 @@ do { \
__ret; \
})
+#define __wait_event_freezable_killable_exclusive(wq, condition) \
+ ___wait_event(wq, condition, TASK_KILLABLE, 1, 0, \
+ freezable_schedule())
+
+#define wait_event_freezable_killable_exclusive(wq, condition) \
+({ \
+ int __ret = 0; \
+ might_sleep(); \
+ if (!(condition)) \
+ __ret = __wait_event_freezable_killable_exclusive(wq, \
+ condition); \
+ __ret; \
+})
#define __wait_event_freezable_exclusive(wq, condition) \
___wait_event(wq, condition, TASK_INTERRUPTIBLE, 1, 0, \
---
Would this be a terrible idea?
On Fri, 6 Jun 2025 at 07:57, Sergey Senozhatsky
<senozhatsky@chromium.org> wrote:
>
> Hi,
>
> We are seeing a number of cases when blocked fuse requests prevent
> the system from suspending, which is a little important on laptops.
> Usually something like this:
>
> [ 36.281038] Freezing user space processes
> [ 56.284961] Freezing user space processes failed after 20.003 seconds (1 tasks refusing to freeze, wq_busy=0):
> [ 56.285069] task:secagentd state:D stack:0 pid:1792 ppid:1711 flags:0x00004006
> [ 56.285084] Call Trace:
> [ 56.285091] <TASK>
> [ 56.285111] schedule+0x612/0x2230
> [ 56.285136] fuse_get_req+0x108/0x2d0
> [ 56.285179] fuse_simple_request+0x40/0x630
> [ 56.285203] fuse_getxattr+0x15d/0x1c0
> [...]
>
> Which looks like wait_event_killable_exclusive() in fuse_get_req().
> And we were wondering if we could do something about it. For example,
> perhaps, something like:
>
> ---
>
> diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
> index f182a4ca1bb32..587cea3a0407d 100644
> --- a/fs/fuse/dev.c
> +++ b/fs/fuse/dev.c
> @@ -241,7 +241,7 @@ static struct fuse_req *fuse_get_req(struct fuse_conn *fc, bool for_background)
>
> if (fuse_block_alloc(fc, for_background)) {
> err = -EINTR;
> - if (wait_event_killable_exclusive(fc->blocked_waitq,
> + if (wait_event_freezable_killable_exclusive(fc->blocked_waitq,
> !fuse_block_alloc(fc, for_background)))
> goto out;
> }
This looks fine. We can turn each wait into a freezable one inside
fuse. But that still would leave core locks (inode lock, rename lock,
page lock, etc) unfreezable. Turning those into freezable isn't
realistic...
But a partial solution might still be better than no solution.
Thanks,
Miklos
On (25/06/06 10:26), Miklos Szeredi wrote:
> > @@ -241,7 +241,7 @@ static struct fuse_req *fuse_get_req(struct fuse_conn *fc, bool for_background)
> >
> > if (fuse_block_alloc(fc, for_background)) {
> > err = -EINTR;
> > - if (wait_event_killable_exclusive(fc->blocked_waitq,
> > + if (wait_event_freezable_killable_exclusive(fc->blocked_waitq,
> > !fuse_block_alloc(fc, for_background)))
> > goto out;
> > }
>
> This looks fine. We can turn each wait into a freezable one inside
> fuse. But that still would leave core locks (inode lock, rename lock,
> page lock, etc) unfreezable. Turning those into freezable isn't
> realistic...
>
> But a partial solution might still be better than no solution.
Thanks Miklos, I sent out a simple patch set [1]
[1] https://lore.kernel.org/linux-kernel/20250610045321.4030262-1-senozhatsky@chromium.org
© 2016 - 2025 Red Hat, Inc.