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?