lkml.org 
[lkml]   [2020]   [Jan]   [22]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.4 032/222] fuse: fix fuse_send_readpages() in the syncronous read case
    Date
    From: Miklos Szeredi <mszeredi@redhat.com>

    commit 7df1e988c723a066754090b22d047c3225342152 upstream.

    Buffered read in fuse normally goes via:

    -> generic_file_buffered_read()
    -> fuse_readpages()
    -> fuse_send_readpages()
    ->fuse_simple_request() [called since v5.4]

    In the case of a read request, fuse_simple_request() will return a
    non-negative bytecount on success or a negative error value. A positive
    bytecount was taken to be an error and the PG_error flag set on the page.
    This resulted in generic_file_buffered_read() falling back to ->readpage(),
    which would repeat the read request and succeed. Because of the repeated
    read succeeding the bug was not detected with regression tests or other use
    cases.

    The FTP module in GVFS however fails the second read due to the
    non-seekable nature of FTP downloads.

    Fix by checking and ignoring positive return value from
    fuse_simple_request().

    Reported-by: Ondrej Holy <oholy@redhat.com>
    Link: https://gitlab.gnome.org/GNOME/gvfs/issues/441
    Fixes: 134831e36bbd ("fuse: convert readpages to simple api")
    Cc: <stable@vger.kernel.org> # v5.4
    Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    fs/fuse/file.c | 4 +++-
    1 file changed, 3 insertions(+), 1 deletion(-)

    --- a/fs/fuse/file.c
    +++ b/fs/fuse/file.c
    @@ -882,6 +882,7 @@ static void fuse_send_readpages(struct f
    struct fuse_args_pages *ap = &ia->ap;
    loff_t pos = page_offset(ap->pages[0]);
    size_t count = ap->num_pages << PAGE_SHIFT;
    + ssize_t res;
    int err;

    ap->args.out_pages = true;
    @@ -896,7 +897,8 @@ static void fuse_send_readpages(struct f
    if (!err)
    return;
    } else {
    - err = fuse_simple_request(fc, &ap->args);
    + res = fuse_simple_request(fc, &ap->args);
    + err = res < 0 ? res : 0;
    }
    fuse_readpages_end(fc, &ap->args, err);
    }

    \
     
     \ /
      Last update: 2020-01-22 14:32    [W:4.041 / U:0.020 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site