Installation on BTRFS

Hi there,

please apologize if this has already been asked, but I really did not understand the things I read about this.

I made an encrypted install on BTRFS/LUKS via Calamares without any special settings apart from a separate boot-partition:

├─sdb2                                       8:18   0     1G  0 part  /boot
├─sdb3                                       8:19   0 231,9G  0 part  
│ └─luks-ee898297-c1a1-4572-9a52-58a622494302
│                                          254:0    0 231,9G  0 crypt /home

First question: why is the sdb3 listed as mounted on /home?

sudo btrfs subvolume list /

gives

ID 256 gen 163 top level 5 path @
ID 258 gen 163 top level 5 path @home

Second question: what is the proper/best way to create a snapshot and to revert to this snapshot?

Thanks in advance,

Christoph

Question one: Not sure, this doesn’t look right.
Can you post your /etc/fstab ?

As far as the second question is concerned I am not sure what the best way is but I can surely explain my best practice with a bit of additional detail to clarify why I do what I do :slight_smile:
I also like to point out that at the core this is based on some excellent advice I received on the Kubuntu forum a while back. Praise to whom praise is due

So here we go:
(My) Btrfs best practice

Some context
The thing which confused me the most with btrfs was that I couldn’t figure out how these odd @ and @home folders/subvolumes/whatever which everyone seems to be talking about related to my traditional understanding of hierarchical file systems. Where do they come from, what are they, etc.?

Well, the important point to understand is that like any other hierarchical file system btrfs has got a root! But what you see when you do a ls / running btrfs isn’t the real root of your file system but rather a subvolume called @, created during installation of the OS.
The preceding @ is just a naming convention which people adhered to, you can call your subvolumes whatever you like.

During installation the OS installer automatically creates two subvolumes (one for “/” called @, and one for /home, called @home) and mounts these two subvolumes as / and /home via fstab.

Post installation your fstab will look like similar to below, please note the subvol=@ parameter which tells the OS to not mount the uuid but rather the subvolumes inside this uuid with the names @ and @home.

/dev/e74269dd-8612-4b09-b59b-3145959fc5bd / btrfs subvol=@,defaults,ssd,noatime,space_cache,autodefrag 0 1

/dev/e74269dd-8612-4b09-b59b-3145959fc5bd /home btrfs subvol=@home,defaults,ssd,noatime,space_cache,autodefrag 0 2

Without the changes explained further down the consequence is that you will never get to see the real root of btrfs, but rather stay inside the respective subvolumes!

Complicated? Not really, and it comes with significant benefits!

To bring the benefits of btrfs to live I mount the real root of btrfs to /mnt. Real root means, I mount the partition uuid instead of the snapshot of "/" created during installation.
This means you move yourself a level higher to what you get with ls /
I do this again through fstab, but this time without the subvol parameter:

/dev/e74269dd-8612-4b09-b59b-3145959fc5bd /mnt btrfs defaults,ssd,noatime 0 2

When you now run ls /mnt you should see this:

~$ ls /mnt
@ @home

And when you dig into @ via ls /mnt/@ you will find that this the same as what you get with ls /. With ls /mnt/@ you are basically looking at your root from outside in. Same with @home

Now, the cool thing about this is that you can now very easily create a snapshot of your / and /home with these two simple commands:

sudo btrfs subvolume snapshot -r /mnt/@ /mnt/snapshots/@$(date +%Y-%m-%d)
sudo btrfs subvolume snapshot -r /mnt/@home /mnt/snapshots/@home
$(date +%Y-%m-%d)

You can call your snapshots whatever you want and put them wherever you want, but I use the name of the source subvolume (@, @home) and add the current date as reference which is this $(date +%Y-%m-%d) variable. I also created a new folder "snapshots" in /mnt to keep things clean.

Your real / file system (ls /mnt) will now look like this:

/
/@
/@home
/snapshots

Why would you want to do this?

Here are my prime scenarios:

  • 1 GB of new OS updates, cool! Let’s install and cross fingers…
  • Need to install this brandnew app which may break things…

With btrfs you run the two commands above to take a snapshot of your OS (…which will take less than a second) , before you take an action which may break you system (Put the command into bash script if it’s too much typing).

If you don’t like the update you simply go to /mnt, mv @ to let’s say @old, mv the snapshot you just took to @, reboot and you are back in business. Same for @home.

Full backup and restore of / and /home in less than 5 minutes!

Snapshots are usually read only which means that the full set of commands for a complete system restore looks like this:

#Move the broken stuff aside
mv /mnt/@ /mnt/@old
mv /mnt/@home /mnt/@homeold

#Make the snapshot rw
btrfs property set -ts /mnt/snapshots/@_yourname ro false
btrfs property set -ts /mnt/snapshots/@home_yourname ro false

#Replace the current @ with your snapshots
mv snapshots/@_yoursnapshot /mnt/@
mv snapshots/@home_yoursnapshot /mnt/@home
reboot now

By the way, from my experience it’s only desktop OS installers (Calamares?) which will automatically create the @ and @home subvolumes. I know Kubuntu and Manjaro do.
Arch (obviously) and my Ubuntu server did not, which confused the hell out of me until I finally understood what was going on. If @ and @home are not created during installation you can create them manually.

Important! Snapshots are not a backup! If your drive dies your snapshots die with it! Hence to turn a snapshot into a backup you need to send them off to a different drive via btrfs send/receive. I can write up something in this respect as well if there’s interest.

Quite a long chunk of text but I hope this all makes sense…

6 Likes

Nice summary! I may try out btrfs (again) after all.

Thanks for your excellent answer!

Here is my fstab:

# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a device; this may
# be used with UUID= as a more robust way to name devices that works even if
# disks are added and removed. See fstab(5).
#
# <file system>             <mount point>  <type>  <options>  <dump>  <pass>
UUID=6EEE-D591                            /boot/efi      vfat    defaults,noatime 0 2
UUID=15ab90c1-303e-4446-a5c0-d72d8fd9c753 swap           swap    defaults,noatime,discard 0 2
UUID=890256d1-327d-45bc-a341-0807dddfe7d8 /boot          ext4    defaults,noatime,discard 0 2
/dev/mapper/luks-ee898297-c1a1-4572-9a52-58a622494302 /              btrfs   subvol=@,defaults,noatime,space_cache,autodefrag,discard,compress=lzo 0 1
/dev/mapper/luks-ee898297-c1a1-4572-9a52-58a622494302 /home          btrfs   subvol=@home,defaults,noatime,space_cache,autodefrag,discard,compress=lzo 0 2
tmpfs                                     /tmp           tmpfs   defaults,noatime,mode=1777 0 0

Is this

the same as

btrfs subvol snapshot /mnt/snapshots/@_basic_install /mnt/@

I’m really surprised how easy it is. The main point I did not understand before your explanation was

Not quite, the first section is about moving an existing snapshot to replace the currently running OS.
The second section is about creating a snapshot.
But I think you got your example the wrong way round?

The syntax for btrfs snapshots is

btrfs subvol snapshot “source” “target”

So your example should read:

btrfs subvol snapshot /mnt/@ /mnt/snapshots/@_basic_install

That’s exactly how I felt, once you understand the subvolume concept it become pretty straight forward, as always I guess :slight_smile:

Your fstab looks ok to me, exactly what I would expect? Not sure why lsblk shows just /home?
Here’s what mine looks like:

$ lsblk
NAME         MAJ:MIN RM   SIZE RO TYPE  MOUNTPOINT
sda            8:0    0   1,8T  0 disk  
├─sda1         8:1    0  97,7G  0 part  /media/Win10
└─sda2         8:2    0   1,7T  0 part  
  └─luksData 254:1    0   1,7T  0 crypt /media/data
zram0        253:0    0   7,9G  0 disk  [SWAP]
nvme0n1      259:0    0   477G  0 disk  
├─nvme0n1p1  259:1    0   511M  0 part  /boot
└─nvme0n1p2  259:2    0 476,4G  0 part  
  └─luksOS   254:0    0 476,4G  0 crypt /mnt

How about mapping your luks-ee898297-c1a1-4572-9a52-58a622494302 to /mnt in fstab and check again?

I have to admit I don’t have years of experience with btrfs and I read about stability issues when I started looking into it, but my experience is just positive.

In fact, when I started with btrfs I was struggling with extremely annoying OS freezes, sometimes multiple times an hour hour, which in the end had nothing to do with the file system but turned out to be an issue with my Samsung nvme drive.
But the filesystem didn’t blink despite the drive constantly locking up. Btrfs always came back just fine even though the OS crashed left and right.

So I guess the early stability issues have been ironed out since the days you tried it?

2 Likes

Hmmm … would this

btrfs subvol snapshot /mnt/@ /mnt/snapshots/@_basic_install
mv /mnt/@ /mnt/@old
btrfs subvol snapshot /mnt/snapshots/@_basic_install /mnt/@

yield the same after a reboot as your method?

I read that using “discard” is not a good idea on BTRFS if using a SSD. In your fstab there is “ssd”. So I guess replacing “discard” by “ssd” would be ok here?

Not quite, your last command tries to create a snapshot of a snapshot? Won’t work and is not necessary. All you need is “mv”
Means your command sequence should look like this:

btrfs subvol snapshot /mnt/@ /mnt/snapshots/@_basic_install
...do all the things which may break your system
# Return to a good state
mv /mnt/@ /mnt/@old
mv /mnt/snapshots/@_basic_install /mnt/@
reboot

This is a little more complicated I am afraid, to make this work correctly a few things need to happen.
You need to make sure the entries in crypttab, fstab and grub (if you are using grub) match.
This may need a separate post here?

Would it be possible to post your fstab in order to have an example here? I really appreciate your help here.

As far as I understand

btrfs subvolume snapshot -r /mnt/@ /mnt/snapshots/@_basic_install

creates the snapshot where @_basic_install is basically a subvolume. I read (but did not try) that it is even possible to boot the snapshot. By

mv /mnt/@ /mnt/@old
btrfs subvol snapshot /mnt/snapshots/@_basic_install /mnt/@

it must be a snapshot i.e. subvolume at /mnt/@, that would be standard root again?!?

Yes and no, @ is your subvolume, @_basic_install is the new snapshot
But a snapshot is a subvolume like any other, with given initial content:
https://btrfs.wiki.kernel.org/index.php/Manpage/btrfs-subvolume

You can test this by adding a file in e.g. /, and check where it appears:

sudo btrfs subvolume snapshot -r /mnt/@ /mnt/snapshots/@_basic_install
sudo touch /test    # Create a empty file named "test"
ls /              # You will see "test"
ls /mnt/@   # You will see "test"
ls /mnt/snapshots/@basic_install   # No "test" because the snapshot was taken before test was created!

I guess you could create a snapshot from a snapshot, Had to try just now to see if that even works :slight_smile:,
It does work, need to get my head around when I would want to use this…

Yes, whatever you map/rename to /mnt/@ will be treated as new root during the next boot, because that’s what you told the OS to do via fstab.

Here’s what the btrfs part of my fstab looks like:

UUID=4ce6d8ef-ba9c-46c8-9c69-e95a6848b054       /               btrfs           rw,noatime,nodiratime,compress=lzo,ssd,space_cache,subvolid=257,subvol=/@,subvol=@      0 0
UUID=6B05-8F8F                                  /boot           vfat            rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=iso8859-1,shortname=mixed,utf8,errors=remount-ro       0 2
UUID=4ce6d8ef-ba9c-46c8-9c69-e95a6848b054       /home           btrfs           rw,noatime,nodiratime,compress=lzo,ssd,space_cache,subvolid=258,subvol=/@home,subvol=@home      0 0
UUID=4ce6d8ef-ba9c-46c8-9c69-e95a6848b054       /var            btrfs           rw,noatime,nodiratime,compress=lzo,ssd,space_cache,subvolid=259,subvol=/@var,subvol=@var        0 0

Ok, I guess I will marked this as solved checking your first reply since I cannot check every answer. This was really one of the steepest learning curves so far while using Linux!

1 Like