diff mbox series

cp --reflix between subvolume

Message ID 7e39d6e5-f203-27fe-a357-f5c42e6f23ef@libero.it
State New, archived
Headers show
Series cp --reflix between subvolume | expand

Commit Message

Goffredo Baroncelli Aug. 25, 2020, 6:03 p.m. UTC
Looking at this page [1] I discovered that in BTRFS it is possible to do a cp --reflink between different subvolume *only* if these are from the same mountpoint. If the subvolumes are mounted with "subvol=" this is not possible even if these are from the same filesystem.

$ cd /var/btrfs/
$ sudo btrfs sub crea a
Create subvolume './a'
$ sudo btrfs sub crea b
Create subvolume './b'
$ sudo dd if=/dev/zero of=a/zero bs=1M count=1
1+0 records in
1+0 records out
1048576 bytes (1.0 MB, 1.0 MiB) copied, 0.0017188 s, 610 MB/s
$ sudo cp --reflink a/zero b/zero-1
$ ls b/

$ # /dev/sde3 is the btrfs filesystem /var/btrfs
$ sudo mount -o subvol=b /dev/sde3 /mnt/other
$ ls /mnt/other
$ sudo cp --reflink a/zero /mnt/other/zero-2
cp: failed to clone '/mnt/other/zero-2' from 'a/zero': Invalid cross-device link

it seems that the check that prevent 'cp --reflink' to work was inserted by you in the commit 362a20c5e27614739c46707d1c5f55c214d164ce:

$ git show 362a20c5e27614739c46707d1c5f55c214d164ce
commit 362a20c5e27614739c46707d1c5f55c214d164ce
Author: David Sterba <dsterba@suse.cz>
Date:   Mon Aug 1 18:11:57 2011 +0200

     btrfs: allow cross-subvolume file clone
     Lift the EXDEV condition and allow different root trees for files being
     cloned, then pass source inode's root when searching for extents.
     Cloning is not allowed to cross vfsmounts, ie. when two subvolumes from
     one filesystem are mounted separately.
     Signed-off-by: David Sterba <dsterba@suse.cz>

What is the rationale behind this check ? I checked that also nfs4 does the same check.
But I don't understand what is the reason (for sure there is one reason :-) ). My understanding is that
a cp --reflink should be allowed with the only condition that the filesystem are the same; and this check (== the superblock are the same)  are in place.

As also described in [1], the use case that I am looking an easy way to replace the root filesystem
with an its snapshot. So every sub-subvolume (under root) have to be moved between the different
root subvolumes and the easy way is to mount it via fstab. However doing so it prevents cp --reflink
to work.

[1] https://pagure.io/fedora-btrfs/project/issue/8

diff mbox series


diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 0e92e5763005..7011871c45b8 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -2340,6 +2340,10 @@  static noinline long btrfs_ioctl_clone(struct file *file, unsigned long srcfd,
  		goto out_drop_write;
+	ret = -EXDEV;
+	if (src_file->f_path.mnt != file->f_path.mnt)
+		goto out_fput;

Now the code is changed from the one above. But there is the same check (only in a different position)