I recently decided to try out the snapshotting capabilities of the
relatively new BTRFS filesystem. I
have been using the snapshot and rollback capability of LVM (using
lvconvert --merge
) for a while now so I figured I would check out
BTRFS to see how it stacks up.
To get up to speed on how to use BTRFS I found the BTRFS
Fun web page a good reference. I
converted an existing Fedora 17 virtual machine to use BTRFS for the
filesystems (I may cover how I did this in a later post). The disk
inside the virtual machine contains three partitions as is shown below:
\
[root@guest1 ~]# lsblk
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
sr0 11:0 1 4.2G 0 rom
vda 252:0 0 20G 0 disk
├─vda1 252:1 0 500M 0 part /boot
├─vda2 252:2 0 4G 0 part [SWAP]
└─vda3 252:3 0 15.6G 0 part /
[root@guest1 ~]#
As you can see from the output, vda1
is for /boot
while vda3
is
for /
; the root partition. After converting from ext4, both vda1
and
vda3
have BTRFS volumes (filesystems) on them. Now I am free to
snapshot them as I please.\
Taking The Snapshots
In BTRFS snapshots are actually subvolumes (see
here
for an explanation of subvolumes). This means when I create a snapshot
of /boot
and /
it is actually creating a subvolume.
To create the snapshots you use the btrfs subvolume snapshot
command
and you must specify where in the filesystem you want the snapshot to
reside. To help myself not get confused I created a /boot/.snapshots
directory and a /.snapshots
directory which is where I will create the
snapshots. The creation of the snapshots is shown below:
\
[root@guest1 ~]# mkdir /boot/.snapshots
[root@guest1 ~]# mkdir /.snapshots
[root@guest1 ~]#
[root@guest1 ~]# btrfs subvolume snapshot /boot /boot/.snapshots/snap1
Create a snapshot of '/boot' in '/boot/.snapshots/snap1'
[root@guest1 ~]#
[root@guest1 ~]# btrfs subvolume snapshot / /.snapshots/snap1
Create a snapshot of '/' in '/.snapshots/snap1'
[root@guest1 ~]#
[root@guest1 ~]#
[root@guest1 ~]# btrfs subvolume list /boot
ID 256 top level 5 path .snapshots/snap1
[root@guest1 ~]#
[root@guest1 ~]# btrfs subvolume list /
ID 270 top level 5 path .snapshots/snap1
[root@guest1 ~]#
If you notice in the output of the btrfs subvolume list
commands
above, the subvolumes (snapshots) that were created have a unique ID
associated with them. For each BTRFS filesystem there is also an
implicit “root subvolume” with an ID of 0
.
These IDs can be used to set which subvolume is the one that is used
when the BTRFS filesystem is mounted. In order to be able to easily
identify if I had mounted a snapshot or the root subvolume, I placed a
single file snap1_sub
into the root directory of each snapshot.
\
[root@guest1 ~]# touch /boot/.snapshots/snap1/snap1_sub
[root@guest1 ~]#
[root@guest1 ~]# touch /.snapshots/snap1/snap1_sub
Upgrade From F17 to F18 Beta
At this point the snapshots were all set up and I could go ahead with
upgrading from Fedora 17 to the Fedora 18 beta. I followed the steps
from the Fedora Web
Site on how
to do this. After rebooting I indeed had upgraded to Fedora 18:\
[root@guest1 ~]# cat /etc/redhat-release
Fedora release 18 (Spherical Cow)
[root@guest1 ~]#
However, as usual the upgrade didn’t yield a perfectly working system.
As far as the command line was concerned everything seemed to be fine
but my desktop session was a no go and the logs indicated there was
something awry with the X configuration.
No need to fear! The snapshots are there!
Reverting The Snapshots
What we want to do now is revert the changes and go back to Fedora 17.
How do we do that?
One way is to make the snapshot subvolume be the default subvolume that
is used when the filesystem is mounted. I set both /boot
and /
to
default to their snapshots by using the btrfs subvolume set-default
command:
\
[root@guest1 ~]# btrfs subvolume list /boot/
ID 256 gen 29 top level 5 path .snapshots/snap1
[root@guest1 ~]#
[root@guest1 ~]# btrfs subvolume set-default 256 /boot/
[root@guest1 ~]#
[root@guest1 ~]#
[root@guest1 ~]#
[root@guest1 ~]# btrfs subvolume list /
ID 270 gen 139 top level 5 path .snapshots/snap1
[root@guest1 ~]#
[root@guest1 ~]# btrfs subvolume set-default 270 /
[root@guest1 ~]#
[root@guest1 ~]# reboot
After a quick reboot I was back up and running. I wanted to verify I was
in the snapshot so I checked to see if the files I had created were in
the root of the filesystems:
\
[root@guest1 ~]# ls -l /boot/snap1_sub
-rw-r--r-- 1 root root 0 Jan 4 23:20 /boot/snap1_sub
[root@guest1 ~]#
[root@guest1 ~]# ls -l /snap1_sub
-rw-r--r-- 1 root root 0 Jan 4 23:20 /snap1_sub
[root@guest1 ~]#
[root@guest1 ~]# cat /etc/redhat-release
Fedora release 17 (Beefy Miracle)
The next step was to restore the root subvolume (ID=0) of each
filesystem. I started with /boot
(from vda1
). To do this you mount
the root subvolume and then use rsync
to restore any files that were
changed.
NOTE: In the rsync
command I was careful to exclude the file that
I created to let me know I was in the snapshot as well as the directory
that is used for the snapshots.
\
[root@guest1 ~]# mount -o subvolid=0 /dev/vda1 /mnt
[root@guest1 ~]#
[root@guest1 ~]# time rsync --delete -avHAX --exclude=snap1_sub --exclude=/.snapshots /boot/ /mnt/
sending incremental file list
./
deleting vmlinuz-3.6.10-4.fc18.x86_64
deleting initrd-plymouth.img
deleting initramfs-3.6.10-4.fc18.x86_64.img
deleting config-3.6.10-4.fc18.x86_64
deleting System.map-3.6.10-4.fc18.x86_64
deleting .vmlinuz-3.6.10-4.fc18.x86_64.hmac
grub/
grub/splash.xpm.gz
grub2/
grub2/grub.cfg
grub2/themes/
grub2/themes/system/
deleting grub2/themes/system/unicode.pf2
deleting grub2/themes/system/fireworks.png
deleting grub2/themes/system/DejaVuSans-Bold-14.pf2
deleting grub2/themes/system/DejaVuSans-12.pf2
deleting grub2/themes/system/DejaVuSans-10.pf2
grub2/themes/system/background.png
grub2/themes/system/dejavu.pf2
grub2/themes/system/theme.txt
sent 4216333 bytes received 234 bytes 8433134.00 bytes/sec
total size is 36454169 speedup is 8.65
real 0m0.135s
user 0m0.023s
sys 0m0.018s
[root@guest1 ~]#
From the output we can see that upgrading caused about 34M (36454169
bytes) of changes to the filesystem and it took less than a second to
revert the changes.
Now that the /boot
filesystem has been restored we need to set the
default subvolume to mount again. We need to reset it back to
automatically mount the root subvolume.
NOTE: When setting the default subvolume you have to be careful and
make sure to specify the location where the root subvolume is mounted
(in this case /mnt
). There is a small bit of text that attempts to
explain why this is necessary on the BTRFS
Fun
web page.\
[root@guest1 ~]# btrfs subvolume set-default 0 /mnt
[root@guest1 ~]# umount /mnt
Now on to the /
filesystem. For this one I needed to tweak the rsync
command to make sure that it didn’t attempt to sync anything outside of
the filesystem; we don’t care to sync fake filesystems like /dev
/proc
/sys
etc.. Also we wanted to exclude /mnt
since that is
where the root subvolume is mounted.
\
[root@guest1 ~]# mount -o subvolid=0 /dev/vda3 /mnt
[root@guest1 ~]#
[root@guest1 ~]# time rsync --one-file-system --delete -avHAX --exclude=/snap1_sub --exclude=/.snapshots --exclude=/mnt / /mnt
sending incremental file list
...
...
sent 2822450331 bytes received 3425590 bytes 5429156.43 bytes/sec
total size is 3109809657 speedup is 1.10
real 8m40.348s
user 0m19.899s
sys 0m36.568s
[root@guest1 ~]#
[root@guest1 ~]#
[root@guest1 ~]# btrfs subvolume set-default 0 /mnt
[root@guest1 ~]# umount /mnt
[root@guest1 ~]#
[root@guest1 ~]# reboot
And we are done.. It took less than 10 minutes to revert ~3G of changes
that were made. After the reboot my Fedora 17 instance was fully
restored and we were in the root subvolumes as can be seen below from
the absence of the snap1_sub
files that I had created.
\
[root@guest1 ~]# cat /etc/redhat-release
Fedora release 17 (Beefy Miracle)
[root@guest1 ~]#
[root@guest1 ~]# ls -l /boot/snap1_sub
ls: cannot access /boot/snap1_sub: No such file or directory
[root@guest1 ~]#
[root@guest1 ~]# ls -l /snap1_sub
ls: cannot access /snap1_sub: No such file or directory
[root@guest1 ~]#
[root@guest1 ~]#
The final step was to delete the snapshots as they are no longer
needed.
\
[root@guest1 ~]# btrfs subvolume delete /boot/.snapshots/snap1
Delete subvolume '/boot/.snapshots/snap1'
[root@guest1 ~]#
[root@guest1 ~]# btrfs subvolume delete /.snapshots/snap1
Delete subvolume '/.snapshots/snap1'
Conclusions
Overall I believe the snapshotting feature of BTRFS is quite useful. I
like the fact that you don’t have to carve out new storage for the
snapshots like in LVM, but at the same time I don’t like how it doesn’t
seem to be very easy to detect how much space the snapshots are using
up. I also don’t like the fact that reverting the snapshots are a bit
manual and require an external tool like rsync
. In LVM it is handled
all in one command: lvconvert --merge
. That being said, just from
experience it does seem that reverting the snapshots seems to be a bit
faster with BTRFS than with LVM snapshots. I would have to run another
test to be sure of this.
Happy New Year Everyone!
Dusty
References:
http://www.funtoo.org/wiki/BTRFS_Fun
https://c59951.ssl.cf2.rackcdn.com/4376-bacik_0.pdf