12

From what I understand, btrfs subvolumes share the same file system "storage", so I was surprised to know that moving files between different subvolumes is an expensive operation, like moving between different filesystems (copy + delete).

I was especially surprised when someone suggested this work-around: reflink-copy files between subvolumes, then delete the original ones. This is said to be a cheap operation (moving around metadata only). How is that different subvolumes can share data blocks when using COW, but not in the should-be easier operation of moving data?

5
  • 5
    This doesn't answer your question, but you may be interested to know that from coreutils 8.24 (released July 3, 2015) onward, mv will try a reflink before falling back to a standard copy (changelog).
    – Vincent Yu
    Aug 1, 2015 at 10:10
  • @VincentYu thanks for the information. But shouldn't a move/rename operation be managed by the filesystem itself, instead of user space utils? From what I read, this move behaviour is the same even if done inside the same mount point, i.e. not having the subvolume mounted in another directory so the kernel could not perhaps recognize it's the same file system. Aug 1, 2015 at 11:20
  • 1
    @VincentYu just for information, and awakened by the new answer, I tried moving a large file between subvolumes with more up-to-date system (debian testing, kernel 4.6.0, coreutils 8.25-2), but nothing changed. Jul 12, 2016 at 7:50
  • 2
    @m.alessandrini I just found that in order to be able to use cp --reflink between two subvolumes I was forced to mount the top level subvolume and issue the cp command inside that namespace, otherwise cp would exit with an error saying ...Invalid cross-device link May 29, 2018 at 12:33
  • @DzamoNorton the fact is that previously it did not work even in the configuration you describe (all subdirs of current dir), where reflink-copy worked. But I just tried and today the move is a zero-time operation, too (kernel 4.16), so I guess this has been addressed. May 30, 2018 at 19:09

1 Answer 1

11

How is that different subvolumes can share data blocks when using COW, but not in the should-be easier operation of moving data?

mv uses the rename syscall to attempt the move. btrfs's kernel rename impl detects the cross subvolumes move and explicitly disallows this (even if under the same mount point):

/* we only allow rename subvolume link between subvolumes */
if (old_ino != BTRFS_FIRST_FREE_OBJECTID && root != dest)
    return -EXDEV;

This probably has to do with subvolume inode accounting and the code paths these operations take. The reflink-copy is actually creating new metadata (but the data itself is CoW) accounted in the new subvolume. In theory they probably could make rename "move" the metadata by doing something similar to what copy --reflink followed by rm source does... simply no one has taken the effort to do it.

3
  • Thanks, I browsed the kernel code for curiosity, and apart not understanding it at a first glance (obviously), I really don't understand that sentence in the comment. Do you know what it may mean? Jul 12, 2016 at 7:46
  • 6
    Subvolumes appear as directory entries (aka "subvolume link") anywhere in the filesystem. The comment is saying you can only rename (aka move) the subvolume directory entries between subvolumes and not actual dirs/files.
    – Will Brown
    Jul 13, 2016 at 5:44
  • Since inode namespaces are separate between subvolumes, hardlinking cannot be done in principle, it's not a matter of "doing the work". Similarly, rename is guaranteed to return EXDEV when crossing inode namespaces, so there is no alternative than to fail with EXDEV. Mar 19 at 17:19

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .