Skip to content

Commit 8fba54a

Browse files
author
Miklos Szeredi
committed
fuse: direct-io: don't dirty ITER_BVEC pages
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. Reported-by: Sheng Yang <[email protected]> Fixes: aa4d861 ("block: loop: switch to VFS ITER_BVEC") Signed-off-by: Miklos Szeredi <[email protected]> Cc: <[email protected]> # v4.1+ Reviewed-by: Sheng Yang <[email protected]> Reviewed-by: Ashish Samant <[email protected]> Tested-by: Sheng Yang <[email protected]> Tested-by: Ashish Samant <[email protected]>
1 parent fa8410b commit 8fba54a

File tree

1 file changed

+4
-3
lines changed

1 file changed

+4
-3
lines changed

fs/fuse/file.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -530,13 +530,13 @@ void fuse_read_fill(struct fuse_req *req, struct file *file, loff_t pos,
530530
req->out.args[0].size = count;
531531
}
532532

533-
static void fuse_release_user_pages(struct fuse_req *req, int write)
533+
static void fuse_release_user_pages(struct fuse_req *req, bool should_dirty)
534534
{
535535
unsigned i;
536536

537537
for (i = 0; i < req->num_pages; i++) {
538538
struct page *page = req->pages[i];
539-
if (write)
539+
if (should_dirty)
540540
set_page_dirty_lock(page);
541541
put_page(page);
542542
}
@@ -1320,6 +1320,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter,
13201320
loff_t *ppos, int flags)
13211321
{
13221322
int write = flags & FUSE_DIO_WRITE;
1323+
bool should_dirty = !write && iter_is_iovec(iter);
13231324
int cuse = flags & FUSE_DIO_CUSE;
13241325
struct file *file = io->file;
13251326
struct inode *inode = file->f_mapping->host;
@@ -1363,7 +1364,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter,
13631364
nres = fuse_send_read(req, io, pos, nbytes, owner);
13641365

13651366
if (!io->async)
1366-
fuse_release_user_pages(req, !write);
1367+
fuse_release_user_pages(req, should_dirty);
13671368
if (req->out.h.error) {
13681369
err = req->out.h.error;
13691370
break;

0 commit comments

Comments
 (0)