lkml.org 
[lkml]   [2018]   [Dec]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 39/52] Release file in process context
    Date
    fuse_file_put(sync) can be called with sync=true/false. If sync=true,
    it waits for release request response and then calls iput() in the
    caller's context. If sync=false, it does not wait for release request
    response, frees the fuse_file struct immediately and req->end function
    does the iput().

    iput() can be a problem with DAX if called in req->end context. If this
    is last reference to inode (VFS has let go its reference already), then
    iput() will clean DAX mappings as well and send REMOVEMAPPING requests
    and wait for completion. (All the the worker thread context which is
    processing fuse replies from daemon on the host).

    That means it blocks worker thread and it stops processing further
    replies and system deadlocks.

    So for now, force sync release of file in case of DAX inodes.

    Signed-off-by: Vivek Goyal <vgoyal@redhat.com>
    ---
    fs/fuse/file.c | 15 ++++++++++++++-
    1 file changed, 14 insertions(+), 1 deletion(-)

    diff --git a/fs/fuse/file.c b/fs/fuse/file.c
    index 6421c94cef46..d86f6e5c4daf 100644
    --- a/fs/fuse/file.c
    +++ b/fs/fuse/file.c
    @@ -451,6 +451,7 @@ void fuse_release_common(struct file *file, int opcode)
    {
    struct fuse_file *ff = file->private_data;
    struct fuse_req *req = ff->reserved_req;
    + bool sync = false;

    fuse_prepare_release(ff, file->f_flags, opcode);

    @@ -471,8 +472,20 @@ void fuse_release_common(struct file *file, int opcode)
    * Make the release synchronous if this is a fuseblk mount,
    * synchronous RELEASE is allowed (and desirable) in this case
    * because the server can be trusted not to screw up.
    + *
    + * For DAX, fuse server is trusted. So it should be fine to
    + * do a sync file put. Doing async file put is creating
    + * problems right now because when request finish, iput()
    + * can lead to freeing of inode. That means it tears down
    + * mappings backing DAX memory and sends REMOVEMAPPING message
    + * to server and blocks for completion. Currently, waiting
    + * in req->end context deadlocks the system as same worker thread
    + * can't process REMOVEMAPPING reply it is waiting for.
    */
    - fuse_file_put(ff, ff->fc->destroy_req != NULL);
    + if (IS_DAX(req->misc.release.inode) || ff->fc->destroy_req != NULL)
    + sync = true;
    +
    + fuse_file_put(ff, sync);
    }

    static int fuse_open(struct inode *inode, struct file *file)
    --
    2.13.6
    \
     
     \ /
      Last update: 2018-12-10 18:17    [W:3.836 / U:0.176 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site