Todd Poynor <toddpoynor@...> writes:
> Suspend attempts can abort when the FUSE daemon is already frozen
> and a client is waiting uninterruptibly for a response, causing
> freezing of tasks to fail.
> Use the freeze-friendly wait API, but disregard other signals.
> Signed-off-by: Todd Poynor <toddpoynor@...>
> Have seen reports in which repeated suspend attempts were aborted
> due to a task waiting uninterruptibly in this function, but
> have only reproduced this artificially, by causing the daemon to
> sleep. Only modified the normal request path, not request aborts
> and such, under the assumption that these should be rare and
> should make progress upon resume. Certain apps that read or
> write a lot of data on the filesystem may apparently run into
> this case rather frequently.
Yes, this is a well known problem with no (known) trivial solutions.
Problem with the patch is, it's going to solve only a subset of the
suspend aborts. It will allow any operation sent to userspace to
freeze, which is fine. But imagine that such a request is holding a VFS
lock (e.g. write(2) is hoding i_mutex) and another operation is waiting
on that lock. That one still won't be freezable and will prevent
suspend to proceed.
I'm not sure it's really worth fixing only a subset of the problematic
cases. We should definitely be thinking about solving it properly, in
> fs/fuse/dev.c | 6 +++++-
> 1 files changed, 5 insertions(+), 1 deletions(-)
> diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
> index 168a80f..bded2e5 100644
> --- a/fs/fuse/dev.c
> +++ b/fs/fuse/dev.c
> @@ -19,6 +19,7 @@
> #include <linux/pipe_fs_i.h>
> #include <linux/swap.h>
> #include <linux/splice.h>
> +#include <linux/freezer.h>
> @@ -383,7 +384,10 @@ __acquires(fc->lock)
> * Wait it out.
> - wait_event(req->waitq, req->state == FUSE_REQ_FINISHED);
> + while (req->state != FUSE_REQ_FINISHED)
> + wait_event_freezable(req->waitq,
> + req->state == FUSE_REQ_FINISHED);
> if (!req->aborted)