Super User is a question and answer site for computer enthusiasts and power users. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

How can make a full copy of the contents of a btrfs filesystem? By full copy I mean not only the current data, but also different subvolumes with their snapshots, ideally preserving their CoW structures (i.e.: not duplicating blocks with the same content.

It seems a block-level copy (such as with dd) is not a good idea, since it duplicates the UUID, and there isn't a way to easily change it, apparently.

share|improve this question
up vote 1 down vote accepted

I have not found any ready-made solution as of today (2016-05-06), but solved the problem for my purposes, including Copy-on-Write handling. The steps to "clone" /source to /target are:

  1. Get a list of subvolumes ordered by ogen: btrfs subvolumes list -qu --sort ogen /source. Sorting is probably enough to guarantee that snapshots or subvolumes which depend on previous ones are handled first. This is important for dealing with Copy-on-Write, because we need to have the base volumes transferred first.

  2. Make all subvolumes read-only using btrfs property set -ts /source/some-volume ro.

  3. Now, for each subvolume from the list above, starting at the top, do the following:

    1. If the volume does not have a parent UUID (displayed as -) or the parent UUID does not exist anymore in the list, run: btrfs send /source/some/volume | btrfs receive /target/some/

    2. If the volume does have a parent UUID which still exists, we should have transferred it already because of --sort ogen and we can use that as a base to avoid data duplication. Hence, find the parent UUID's path in the list and run: btrfs send -p /source/parent/volume/ -c /source/parent/volume/ /source/some/volume/ | btrfs receive /target/some/ (btrfs would probably guess the -p argument automatically, but I prefer to be explicit).

    3. After running one of the above commands make the target and source read-write again: btrfs property set -ts /source/some/volume ro false; btrfs property set -ts /target/some/volume ro false. This step can be skipped if the source has been previously read-only.

This should handle many cases. Caveats:

  1. There might be some complications with respect to ordering when nesting subvolumes/snapshots.

  2. The whole process is obviously more fun when scripted.

  3. btrfs send accepts multiple clone source (-c) arguments. It may be advantageous to not only specify the parent's volume path, but also those of any ancestors or simply any previously sent volumes. It did not make any difference here, but it might — just a guess — help to avoid data duplication in some cases.

  4. I am unsure if any meta information on snapshots or subvolumes is lost along the way, but just about everything interesting else for most use cases should be preserved.

The whole process helped me transfer an 800 GB filesystem with 3.8 GB used (according to df) to a 10 GB image with 3.8 GB used. Transferring without -p and -c would have used about 190 GB, so data duplication was indeed avoided.

share|improve this answer

There is a similar question on unix.stackexchange.com that points to partclone.btrfs, but I do not know any specifics about this.

There is also a discussion on the kernel mailing list, not really looking promising...

share|improve this answer

With btrfs-send, which last I saw, was still experimental patches floating around on the btrfs mailing list.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.