A couple weeks ago I started using Solus after breaking my two-year old Kubuntu install. I've been using Btrfs for a while and the snapshot and checksum utility to give me peace of mind on the installations where I set it up properly. If you want enumerated reasons why Btrfs is probably better than the standard Linux filesystem Ext4, there are lots of articles out there, like this one.

Solus only installs itself on Ext4. Even if you format a partition as another filesystem in the installer, the installer will overwrite it to Ext4. Wanting to keep the advantages of Btrfs and because it was a little project to keep myself occupied, I kept track of the steps to get Solus root partition on Btrfs. I haven't seen any posts specifically about how to put Solus on Btrfs, so here we are.

If you already installed Solus and want to convert to Btrfs, no problem! Just boot into any modern Linux live environment where you can get Btrfs tools and start at Conversion.


Installation

Install Solus with the recommended options. Choose the automatic partitioning or make your own partition sizes, it doesn't matter for the purposes of Btrfs. That said, I never make a /home partition because I can make that a subvolume within the root partition.

After installing, while still in the Solus live USB environment, crack open a terminal and get root powers with a simple sudo -i, the live user password is blank. Yes running around as root is bad practice, but I don't like typing sudo before every command. Use those superpowers to install btrfs-progs and a text editor (vim for me):

# eopkg install btrfs-progs vim

Conversion

Make sure that you've identified the root partition of where you installed Solus. For me, that was /dev/sdb2. I made sure the Ext4 partition was ok with fsck /dev/sdb2 because the Btrfs wiki told me to. Then, it's the big moment:

# btrfs-convert /dev/sdb2

This will do the actual conversion. Rather anticlimactic, honestly. It works by copying the Ext4 metadata to unused space within the partition that Btrfs can use as metadata, and then just pointing to the same data blocks as Ext4. It's extremely cool and if you want more info, including a graphic showing how it works, you can find it at the Btrfs wiki here.

From this, mount the new Btrfs filesystem and the boot partition under the /mnt directory. You'll need to tinker with them. Oh and know what your boot partition is. Since I installed Solus on /dev/sdb, my boot partition is /dev/sdb1.

# mount -t btrfs /dev/sdb2 /mnt
# mount /dev/sdb1 /mnt/boot

Next, find the UUID of your root partition and paste it into /mnt/etc/fstab. The system needs to know the new UUID of the root partition or it won't boot. Reasonably important. Then edit the /mnt/etc/fstab and replace the old Ext4 UUID with the new Btrfs one. Be sure to also change the root filesystem from ext4 to btrfs and change the mount options. I chose defaults,autodefrag,ssd,compress=lzo,noatime. Change the final number on the root partition line to 0 as you don't need fsck on boot.

# blkid /dev/sdb2 | cut -d '"' -f 2 >> /mnt/etc/fstab

Install btrfs-progs - IMPORTANT!

It's very important to make sure the Solus installation also has btrfs-progs installed or your Solus won't boot. Bind mount the /etc/resolv.conf into the already mounted partition and install the package:

# mount --bind /etc/resolv.conf /mnt/etc/resolv.conf
# chroot /mnt /bin/bash
[Solus]# eopkg install btrfs-progs
[Solus]# exit
# umount /mnt/etc/resolv.conf

Boot Manager Round 1

Solus uses clr-boot-manager as its boot manager, which uses systemd-boot as the bootloader behind the scenes (on UEFI; on BIOS systems clr-boot-manager uses syslinux). This means you don't have to worry about updating grub or looking at impenatrable grub.cfg lines trying to make sure it has the right UUID; editing the entry in /boot/loader/entries/[most recent kernel].conf is enough. On the fourth line of that file, beginning with options, change the root=PARTUUID to root=UUID and paste in the same Btrfs UUID as in the fstab. Use file /mnt/usr/lib/kernel/default-current to find the most recent kernel.

# vim /mnt/boot/loader/entries/[default kernel].conf

title Solus [Solus release]
linux /EFI/com.solus-project/kernel-[default kernel]
initrd /EFI/com.solus-project/initrd-[default kernel]
options root=UUID=900...ede72 quiet loglevel=3 splash
  systemd.show_status=false rw

clr-boot-manager does not support Btrfs as a root filesystem yet, so please read Bootloader Round 2 below for how to deal with that.

The btrfs-convert command "creates a snapshot in Btrfs that references all of the blocks used by ext[4]" in case you want to roll back to the Ext4 system. In this case, blow it away and don't look back:

# btrfs subvolume delete /mnt/ext2_saved

Subvolumes

At this point, you have a working Solus install on Btrfs. Congrats! You can reboot into the installation for the first time and play around. Before you do reboot, I recommend that you add subvolumes. This will allow you to easily use tools like Snapper and Timeshift to take snapshots and back up your Btrfs partition. You can still do that without subvolumes, but they give you flexibility to snapshot, clone, and rollback parts of the file tree amoung other useful things.

I use the @ symbol for the root subvolume and name every toplevel subvolume as @something. This is the naming convention that Timeshift requires and it's easy to identify @ as meaning a top-level subvolume. Creating a "@" subvolume and a "@home" subvolume will make your life easier. Since Btrfs is a Copy-on-Write filesystem, you can just snapshot the Btrfs root to @, and copy the /home folder to @home:

# btrfs subvolume snapshot /mnt /mnt/@
# cp -R --reflink /mnt/home/[user you created] /mnt/@home
# rm -rf /mnt/{bin,dev,etc,home,lib,lib64,\
media,mnt,opt,proc,root,run,sbin,srv,sys,tmp,usr,var}

You'll need to edit /mnt/etc/fstab again to add the correct subvolumes and /home partition. Add subvol=@ to the mount options for root, copy the root line, and change the / to /home and subvol=@ to subvol=@home:

# vim /mnt/etc/fstab

## /etc/fstab static file system information.

UUID=900...ede72	/	btrfs
  defaults,subvol=@,autodefrag,ssd,compress=lzo,noatime	0	0
UUID=900...ede72	/home	btrfs
  defaults,subvol=@home,autodefrag,ssd,compress=lzo,noatime	0	0

Editing the bootloader entry again is crucial. If you forget this step you will be like me and wonder why the system is dumping you into an emergency shell on boot. Add rootflags=subvol=@ to the options line right after the UUID:

# vim /mnt/boot/loader/entries/[default kernel].conf

title Solus [Solus release]
linux /EFI/com.solus-project/kernel-[default kernel]
initrd /EFI/com.solus-project/initrd-[default kernel]
options root=UUID=900...ede72 rootflags=subvol=@ quiet loglevel=3 splash
  systemd.show_status=false rw 

If you don't want RAID 0, you're almost done! You can just skip down to Bootloader Round 2.

RAID 0

Reboot into the shiny new Solus on Btrfs. If it dumps you into an emergency shell on boot, you probably forgot to add the root=subvol=@ to the loader entry options line, or subvol=@ to the root line in the fstab. Boot back into the Solus live environment, mount the root partition with mount -t btrfs -o subvol=@ /dev/[your root partition] /mnt and check those two files.

To make a RAID 0, Btrfs needs another partition on another drive (you technically can use another partition on the same hard drive but that would defeat the whole purpose). I just made an unformatted partition with Gparted; my second partition is /dev/sda2. Add the partition to the Btrfs pool and convert it to RAID 0. Since you are now using the installed system with the user you set up, sudo is back:

$ sudo btrfs device add -f /dev/sda2 /
$ sudo btrfs balance start -dconvert=raid0 -mconvert=raid1 /

-dconvert is for data, and -mconvert is metadata. 

Tada! You've got Solus on Btrfs and an inadvisable tradeoff between data safety and speed! Seriously though, RAID 0 is more prone to failure than a single disk, so please make backups of your data.


Bootloader Round 2

As I mentioned above, Solus uses the clr-boot-manager from the Intel project Clear Linux (a version from early 2018 ??). It does not support Btrfs so you must work around it. The first time do an upgrade on Solus (always do it from the command line) it will give you a scary warning about not being able to update the clr-boot-manager configuration. Don't worry about it, you can do that bit yourself.

It took me a long time to understand clr-boot-manager from the sparce documentation, so I dug through the source code on Gituhub. My knowledge of C is approaching zero on a good day, so it didn't do me much good.

The clr-boot-manager, as far as I can tell, copies the kernel initrd from where they are installed by the package manager, /usr/lib/kernel/, to the /boot/EFI/com.solus-project folder. It also makes a configuration file for each kernel in /boot/loader/entries and sets the default boot option in the /boot/loader/loader.conf file. These files are very easy to read and understand, and the strict location requirements of clr-boot-manager means it is simple to reproduce some of what it does.

Using the shell script /usr/lib/kernel/install/90-loaderentry.install as a reference I wrote my first ever real script. I have no expertice or experience writing scripts, so please don't treat it as reliable or trustworthy. There is no error or sanity checking and it might break things. I made this for myself and give it to you freely with no warranty or guarantee.

#!/bin/bash

## A script to copy the latest Solus kernel to /boot

# make sure we are using root powers
if [ "$(id -u)" != "0" ]; then
	exec sudo "$0" "$@"
fi

# gotta mount /boot!
echo "mounting /boot"
mount /dev/sdb1 /boot

KERNEL_CURRENT=$(ls -l /usr/lib/kernel/default-current | cut -d ' ' -f 11)
KERNEL_LINE="kernel-${KERNEL_CURRENT}"
KERNEL_VER=$(echo ${KERNEL_CURRENT} | cut -d . -f 4-6)
INITRD_CURRENT="initrd-com.solus-project.current.${KERNEL_VER}"

sleep 1
echo "The kernel you are updating is ${KERNEL_CURRENT}"
sleep 1
echo "Copying kernel and initrd to /boot"
cp /usr/lib/kernel/${KERNEL_CURRENT} /boot/EFI/com.solus-project/${KERNEL_LINE}
cp /usr/lib/kernel/${INITRD_CURRENT} /boot/EFI/com.solus-project/${INITRD_CURRENT}

SOLUS_VER=$(grep PRETTY /etc/os-release | cut -d '"' -f 2)
INITRD_OPTS=$(cat /usr/lib/kernel/cmdline-$KERNEL_VER.current)

sleep 1
echo "Writing conf file in /boot/loader/entries"
{
	echo title ${SOLUS_VER}
	echo linux /EFI/com.solus-project/${KERNEL_LINE}
	echo initrd /EFI/com.solus-project/${INITRD_CURRENT}
	echo options root=UUID=900f0d65-730a-45b4-afb3-992b583ede72 rootflags=subvol=@ ${INITRD_OPTS}

} > /boot/loader/entries/Solus-current-${KERNEL_VER}.conf

sleep 2
echo "Writing default boot option in /boot/loader/loader.conf"
echo "default Solus-current-${KERNEL_VER}" > /boot/loader/loader.conf

sleep 1
echo
echo "Check /boot/EFI/com.solus-project directory"
ls /boot/EFI/com.solus-project

sleep 5
echo 
echo "Check Solus-current-${KERNEL_VER}.conf to make sure it looks good"
cat /boot/loader/entries/Solus-current-${KERNEL_VER}.conf
echo

sleep 5
echo "Check loader.conf to make sure it looks good"
cat /boot/loader/loader.conf
sleep 2

echo
echo Unmounting /boot
sleep 1
umount /boot

~/copy-kernel.sh

Solus keeps the /boot partition unmounted by default so the script mounts it first. Be sure to change the boot partition to fit your setup. You can delete all the sleep lines if you don't want them; I like them just to look at the config files and see if there are any glaring errors.

clr-boot-manager has commands to get and set options in the /boot/loader/loader.conf file in addition to copying over kernels and configurations to the /boot partition. If you want to see what those options are and change them in the file itself, have yourself a quick man clr-boot-manager.

Running the script

The reason I said above that you should do all your upgrades through the command line is becaue you need to watch for linux kernel upgrades. Since clr-boot-manager does not support Btrfs, the normal Solus method of updating the boot loader is now broken. After a kernel upgrade you must run the script manually from the command line to copy the kernel, initrd, and configuration to the proper places for the boot loader.

Copy and paste the script into a file in your home directory called copy-kernel.sh. Mark the file as executable, and then run it.

$ chmod u+x ~/copy-kernel.sh
$ ./copy-kernel.sh

The script will ask for your sudo password as it need root permissions to write to /boot. To reinterate, you must run it after every kernel upgrade. I might rewrite it as a wrapper to the eopkg command so it will be automagic, as there appears to be no way to have hooks for eopkg.

Using Btrfs on root means that you can't use clr-boot-manager for anything. I don't know what knock-on effects this has on the rest of Solus; it might even screw up release upgrades. So be warned.

And that's it! You're done! This took me a lot of research as Solus documentation is hit and miss and I've never used it before, so I'm pretty proud of this work. If you want to tell me my script and suggestions are awful or wonderful, do go off in the comments.