Btrfs/System Root Guide

Converting to a btrfs Based System
This exercise is one example for re-basing a gentoo installation's root filesystem to use btrfs. In this case, the existing system is an mdadm based mirror set using two 2tb drives at /dev/sda and /dev/sdb. Two fresh 2tb drives have been added at /dev/sdc and /dev/sdd.

Existing Layout

 * Simple two way mdadm mirror (raid1)
 * 250mb /boot partition as ext3 with metadata=0.90
 * 75gb / partition as ext4 with metadata=0.90
 * 750gb /home partition as ext4 with metadata=1.2
 * 1tb+ /vm partition as ext4 with metadata=1.2

The use of the older metadata format for /boot and / partitions allows grub-0.97 to find and boot the system without needing to resort to an initial ram device.

New Layout

 * 250mb /boot partition as ext3 with metadata=0.90
 * 1.9gb+ btfs partition with raid1 metadata and data

We are keeping the /boot as a simple software mirror in order to stay with grub-0.97 but will now need to use an initial ram filesystem. The kernel will otherwise panic when it attempts to mount btrfs filesystems that need to have a btfs device scan done first. We will be following the writeup for Early Userspace Mounting to build that filesystem.

Btrfs has been built into the kernel (not a module) along with lzo compression/decompression as that will be used to optimize space utilization and read performance on the system volumes. Likewise, the raid modules used by mdadm are also builtins.

There are a number of places where lzo is part of a module name in the kernel .config.

It's unclear what kernel options are pickable to make sure that the lzo module btrfs relies on will be enabled. The likely suspect is CONFIG_HAVE_KERNEL_LZO which comes in to play for the compression of the kernel image itself:

The default selection of Gzip causes CONFIG_KERNEL_LZO to not be set as shown above. There doesn't appear to be a way to control the setting of CONFIG_HAVE_KERNEL_LZO short of editing .config directly.

Partitioning
cfdisk was used to partition /dev/sdc with the 250mb and remainder partitions by hand. sfdisk then can be used to apply the same scheme to /dev/sdd

Setting up boot
The warning about /boot partition alignment might have been avoided with some more care with cfdisk. It will be interesting to see what happens when the btrfs filesystem is created. Grub must be installed on each of the new mirrors by hand as shown

/boot transfer

Transfer of /
We assume that a "hot" transfer of the system will be okay and thus do a remount of / to /mnt/rawroot to grab the basics without pulling in any additional baggage from /proc, udev and other mounts. The new btfs will have the rootfs as a subvolume. Other existing filesystem such as /home and /vm will become other subvolumes. We edit /etc/fstab on an interim basis to provide mountpoints for the new filesystem and its subvolumes. The compression and auto defragmentation features of btrfs may or may not be applicable for the underlying data. The lzo compressor has been turned off for /mnt/newdistfiles since it will be getting the contents of /usr/portage/distfiles where files are already compressed. The /mnt/newvm filesystem leaves out autodefrag as an option since it interferes with the performance of virtual machines and copy on write.

/etc/fstab additions

btrfs creation

We kick off the root fs transfer and come back after a cup of whatever.

root fs copy (roughly 30 mins)

Copy over the /home and other files as necessary. In this particular install, /usr/portage/distfiles had been a softlink to a directory on the old /home filesystem. If it was to have been split off from a physical directory instead, the transfer from the new root subvolume's usr/portage/distfiles to the newdistfiles subvolume is effectively a move between filesystems that would involve a copy and then a delete. It would be more efficient to make judicious use of the -exclude switch on tar when doing the initial copy to the new mirror set.

Edit Config on New Mirror
Edit the grub.conf and fstab on the new mirror set to reflect the way things should look when the new mirror set becomes the boot set. That includes editing /etc/mdadm.conf to assemble only the /dev/md1 device now. It's also probably cleaner to do a mountpoint for /distfiles as shown and then have /usr/portage/distfiles be a softlink to it.

/etc/fstab changes on new mirror

Generate a new mdadm.conf file to include the new /dev/md5 /boot mirror but then edit it to rename that to /dev/md1. The other existing arrays are stubbed out, but the information is there in case the old mirror set is put back on again.

new mdadm.conf

If this was a simple one disk based btrfs root filesystem the following process would probably work just fine. Edit the new grub.conf to use the new btrfs based root filesystem. Use rootflags to pull in the mount options from your new fstab for the root device. Because we had used a label BTRFSMIRROR when making the new mirror set, we can pass that as the root to have the kernel automatically scan for and find the default volume.

grub.conf on new boot mirror

However it turns out the kernel panics when it gets around to working with /rootfs. So we will have to use an initial ram filesystem and an embedded init to mount the mirror set. Following the wiki entry for Early Userspace Mounting, we create the following files in /usr/src/linux/initramfs

Note - You will probably need to create the /usr/src/linux/initramfs directory before introducing the above files.
 * 1) cd /usr/src/linux
 * 2) scripts/gen_initramfs_list.sh -o /mnt/altboot/initrd_btrfs.cpio.gz /usr/src//linux/initramfs/initramfs_list

The init script is a hacked up version from the Early Userspace Mounting and will probably be cleaned up in a later edit. The mount_root does a btrfs device scan which takes about 5-10 seconds depending on the drives being used. That is the crucial piece that apparently doesn't get done when grub processes the kernel directive, and thus it can't figure out that btrfs is spanning more than one drive.

It would be a good idea to balance the new btrfs filesystems before booting into the new mirror set. It isn't crucial to do it now, but it will speed up performance of the initial boot. The balance can just as easily be done on the live volumes after the new mirror set is booted.