This posts describes how to create subvolumes in btrfs retrospectively (with existing data).
Iām using archlinux, but most of the things should be applicable to other distors as well.
It is mostly a list of the required commands, with a tiny bit of explanations :).
All the commands are real world examples from my system, so you need to adapt device names etc. to your setup.
Move the top-level volume to a subvolume
- create a snapshot
1
sudo btrfs subvol snapshot / /@
(ā@ā seems to be a common name for the main subvolume)
set the new snapshot as default subvolume
1
2
3
4sudo btrfs subvol list /
# outputs: ID 330 gen 1354 top level 5 path @
# use the id from the output above to
sudo btrfs subvol set-default 330 /if it is not the root volume, skip to the last point of this section
adapt grub to boot from the new subvolume
mount the new subvolume
1
2
3cd /mnt
sudo mkdir newroot
sudo mount -o subvol=@ /dev/mapper/cryptroot newrootedit newroot/etc/fstab to include subvol=@ in the / options
This should not be needed theoretically since it is the default volume, but grub-mkconfig did not produce a correct config for me without it.1
2UUID=2240f8f3-3dfa-4aad-a62f-899f5970cb3d / btrfs defaults,subvol=@,noatime,discard,space_cache,autodefrag,compress=lzo
0 0chroot into the new subvolume and update grub
1
2
3
4
5
6
7for i in /dev /dev/pts /proc /sys /run; do sudo mount --bind $i newroot$i; done
sudo mount /dev/mapper/cryptboot newroot/boot
sudo mount /dev/sdc1 newroot/boot/efi
sudo mount --bind /sys/firmware/efi/efivars newroot/sys/firmware/efi/efivars
sudo chroot /mnt/newroot
grub-mkconfig -o /boot/grub/grub.cfg
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=arch-grub --recheckunmount and reboot (at your own risk of course :D)
delete the old data from the toplevel
1
2
3
4
5cd /mnt
sudo mkdir oldroot
sudo mount -o subvolid=5 /dev/mapper/cryptroot oldroot
cd oldroot
# CAREFULLY delete everything except @ subvolume
Move existing directory to a subvolume
In this example the directory /home/martin/develop will be replaced with a subvolume.
create the new subvolume
1
2
3sodo mkdir /mnt/toplevel
sudo mount -o subvolid=5 /dev/mapper/cryptroot /mnt/toplevel
sudo btrfs subvol create /mnt/toplevel/@developmove the data to the new subvolume in the most efficient way (as far as I know) by creating reflinks
1
sudo cp -ax --reflink=always /mnt/toplevel/@/home/martin/develop/. /mnt/toplevel/@develop
delete the old directory
1
2# DO THIS AT YOUR OWN RISK
rm -rf /home/martin/developmount the new subvolume instead
1
2mkdir /home/martin/develop
sudo mount -o subvol=@develop /dev/mapper/cryptroot /home/martin/developadd new fstab entry to mount the new subvolume automatically
1
2UUID=2240f8f3-3dfa-4aad-a62f-899f5970cb3d /home/martin/develop btrfs defaults,subvol=@develop,noatime,discard,space_cac
he,autodefrag,compress=lzo 0 0
Note that the top-level volume always has the ID 5.
Reference: https://btrfs.wiki.kernel.org/index.php/UseCases#Can_I_take_a_snapshot_of_a_directory.3F
Thanks for reading, I hope it was helpful to you :)