Skip to content

Commit

Permalink
fuse: fix copy_file_range() in the writeback case
Browse files Browse the repository at this point in the history
Prior to sending COPY_FILE_RANGE to userspace filesystem, we must flush all
dirty pages in both the source and destination files.

This patch adds the missing flush of the source file.

Tested on libfuse-3.5.0 with:

  libfuse/example/passthrough_ll /mnt/fuse/ -o writeback
  libfuse/test/test_syscalls /mnt/fuse/tmp/test

Fixes: 88bc7d5 ("fuse: add support for copy_file_range()")
Cc: <[email protected]> # v4.20
Signed-off-by: Miklos Szeredi <[email protected]>
  • Loading branch information
Miklos Szeredi committed May 28, 2019
1 parent 4a2abf9 commit a2bc923
Showing 1 changed file with 12 additions and 0 deletions.
12 changes: 12 additions & 0 deletions fs/fuse/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -3110,6 +3110,7 @@ static ssize_t fuse_copy_file_range(struct file *file_in, loff_t pos_in,
{
struct fuse_file *ff_in = file_in->private_data;
struct fuse_file *ff_out = file_out->private_data;
struct inode *inode_in = file_inode(file_in);
struct inode *inode_out = file_inode(file_out);
struct fuse_inode *fi_out = get_fuse_inode(inode_out);
struct fuse_conn *fc = ff_in->fc;
Expand All @@ -3133,6 +3134,17 @@ static ssize_t fuse_copy_file_range(struct file *file_in, loff_t pos_in,
if (fc->no_copy_file_range)
return -EOPNOTSUPP;

if (fc->writeback_cache) {
inode_lock(inode_in);
err = filemap_write_and_wait_range(inode_in->i_mapping,
pos_in, pos_in + len);
if (!err)
fuse_sync_writes(inode_in);
inode_unlock(inode_in);
if (err)
return err;
}

inode_lock(inode_out);

if (fc->writeback_cache) {
Expand Down

0 comments on commit a2bc923

Please sign in to comment.