]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
fuse: direct-io: don't dirty ITER_BVEC pages
authorAshish Samant <ashish.samant@oracle.com>
Thu, 18 Aug 2016 20:54:26 +0000 (13:54 -0700)
committerChuck Anderson <chuck.anderson@oracle.com>
Sun, 30 Oct 2016 19:12:25 +0000 (12:12 -0700)
When reading from a loop device backed by a fuse file it deadlocks on
lock_page().

This is because the page is already locked by the read() operation done on
the loop device.  In this case we don't want to either lock the page or
dirty it.

So do what fs/direct-io.c does: only dirty the page for ITER_IOVEC vectors.

Orabug : 22652336

Reported-by: Alexey Kodanev <alexey.kodanev@oracle.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Signed-off-by: Ashish Samant <ashish.samant@oracle.com>
Acked-by: Srinivas Eeda <srinivas.eeda@oracle.com>
fs/fuse/file.c

index 46d7242b568a3c28c98de0d774efd814231c9f33..19aa68c4b9115a7ece905a6c1b56a6e5ab6c899e 100644 (file)
@@ -516,13 +516,13 @@ void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos,
        req->out.args[0].size = count;
 }
 
-static void fuse_release_user_pages(struct fuse_req *req, int write)
+static void fuse_release_user_pages(struct fuse_req *req, bool should_dirty)
 {
        unsigned i;
 
        for (i = 0; i < req->num_pages; i++) {
                struct page *page = req->pages[i];
-               if (write)
+               if (should_dirty)
                        set_page_dirty_lock(page);
                put_page(page);
        }
@@ -1300,6 +1300,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter,
                       loff_t *ppos, int flags)
 {
        int write = flags & FUSE_DIO_WRITE;
+       bool should_dirty = !write && iter_is_iovec(iter);
        int cuse = flags & FUSE_DIO_CUSE;
        struct file *file = io->file;
        struct inode *inode = file->f_mapping->host;
@@ -1343,7 +1344,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter,
                        nres = fuse_send_read(req, io, pos, nbytes, owner);
 
                if (!io->async)
-                       fuse_release_user_pages(req, !write);
+                       fuse_release_user_pages(req, should_dirty);
                if (req->out.h.error) {
                        if (!res)
                                err = req->out.h.error;