From 4caa9af06265aef40239847d14b2182f5dd35a44 Mon Sep 17 00:00:00 2001 From: Scott B Date: Fri, 18 Feb 2022 16:15:23 -0800 Subject: [PATCH] fs: allow cross-vfsmount reflink/dedupe Squashed commit of the following: commit d053c48ab87a8668d5eb27765b9ff10573053091 Author: Josef Bacik Date: Fri Feb 18 09:38:14 2022 -0500 fs: allow cross-vfsmount reflink/dedupe Currently we disallow reflink and dedupe if the two files aren't on the same vfsmount. However we really only need to disallow it if they're not on the same super block. It is very common for btrfs to have a main subvolume that is mounted and then different subvolumes mounted at different locations. It's allowed to reflink between these volumes, but the vfsmount check disallows this. Instead fix dedupe to check for the same superblock, and simply remove the vfsmount check for reflink as it already does the superblock check. Reviewed-by: Darrick J. Wong Reviewed-by: Nikolay Borisov Reviewed-by: David Sterba Signed-off-by: Josef Bacik commit 8d92b5b06130d1557e200dd64bb901f94ff661ea Author: Josef Bacik Date: Fri Feb 18 09:38:13 2022 -0500 btrfs: remove the cross file system checks from remap The sb check is already done in do_clone_file_range, and the mnt check (which will hopefully go away in a subsequent patch) is done in ioctl_file_clone(). Remove the check in our code and put an ASSERT() to make sure it doesn't change underneath us. Signed-off-by: Josef Bacik --- fs/btrfs/reflink.c | 4 +--- fs/ioctl.c | 4 ---- fs/remap_range.c | 7 +------ 3 files changed, 2 insertions(+), 13 deletions(-) diff --git a/fs/btrfs/reflink.c b/fs/btrfs/reflink.c index e0f93b357548..5804f4af2629 100644 --- a/fs/btrfs/reflink.c +++ b/fs/btrfs/reflink.c @@ -772,9 +772,7 @@ static int btrfs_remap_file_range_prep(struct file *file_in, loff_t pos_in, if (btrfs_root_readonly(root_out)) return -EROFS; - if (file_in->f_path.mnt != file_out->f_path.mnt || - inode_in->i_sb != inode_out->i_sb) - return -EXDEV; + ASSERT(inode_in->i_sb == inode_out->i_sb); } /* Don't make the dst file partly checksummed */ diff --git a/fs/ioctl.c b/fs/ioctl.c index 504e69578112..79550f5f4c45 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c @@ -236,9 +236,6 @@ static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd, if (!src_file.file) return -EBADF; - ret = -EXDEV; - if (src_file.file->f_path.mnt != dst_file->f_path.mnt) - goto fdput; cloned = vfs_clone_file_range(src_file.file, off, dst_file, destoff, olen, 0); if (cloned < 0) @@ -247,7 +244,6 @@ static long ioctl_file_clone(struct file *dst_file, unsigned long srcfd, ret = -EINVAL; else ret = 0; -fdput: fdput(src_file); return ret; } diff --git a/fs/remap_range.c b/fs/remap_range.c index 6d4a9beaa097..264ec4541a6c 100644 --- a/fs/remap_range.c +++ b/fs/remap_range.c @@ -368,11 +368,6 @@ loff_t do_clone_file_range(struct file *file_in, loff_t pos_in, WARN_ON_ONCE(remap_flags & REMAP_FILE_DEDUP); - /* - * FICLONE/FICLONERANGE ioctls enforce that src and dest files are on - * the same mount. Practically, they only need to be on the same file - * system. - */ if (file_inode(file_in)->i_sb != file_inode(file_out)->i_sb) return -EXDEV; @@ -464,7 +459,7 @@ loff_t vfs_dedupe_file_range_one(struct file *src_file, loff_t src_pos, goto out_drop_write; ret = -EXDEV; - if (src_file->f_path.mnt != dst_file->f_path.mnt) + if (file_inode(src_file)->i_sb != file_inode(dst_file)->i_sb) goto out_drop_write; ret = -EISDIR; -- 2.35.1