Sunday, May 15, 2011

Convert your ext4 Ubuntu 11.04 to btrfs without doing a clean install

I've mentioned before that I was planning to convert my current Ubuntu installation to btrfs. So, here's a step in that direction. Instead of doing the actual conversion, I'm testing things out in VirtualBox first to see how things go.
Warning: Btrfs currently doesn't have reliable fsck so it's a good idea to not do the conversion just yet. This post is based on my experiments in VirtualBox to help figure out the steps needed for the conversion. Nothing more. Proceed with extreme caution.
This guide was written while referencing information available from this forum post and this community documentation. I certainly didn't come up with it myself. I merely made use of readily available information, and adapted it to my own purposes.

For testing the conversion process, I'm clean installing Ubuntu 11.04 in VirtualBox using all default options. Then, I'll do the conversion from ext4 to btrfs. Clean installing Ubuntu 11.04 is straightforward so I'll skip that part. There's nothing of particular interesting there. It's what comes after that is of interest.

Converting the ext4 partition to btrfs

Here, I'm assuming a single boot installation of Ubuntu 11.04 so the Ubuntu partition is sda1. Replace sda1 with the correct partition as necessary.

After installing Ubuntu as usual, start a terminal. There's no need for a reboot before attempting this.

$ sudo fsck -f /dev/sda1
$ sudo btrfs-convert /dev/sda1

ext4 to btrfs conversion process in terminal

Running fsck with the -f option is important here. For some reason, not doing so results in an error while mounting /.

Once conversion is complete, you'll need to find out the new UUID for the freshly converted btrfs partition. Note down the UUID listed by the blkid command below.

$ sudo blkid /dev/sda1


Next up is to login to chroot, then update /etc/fstab while you're in there.

$ sudo mount -t btrfs /dev/sda1 /mnt
$ sudo mount --bind /dev  /mnt/dev
$ sudo mount --bind /dev/pts  /mnt/dev/pts
$ sudo mount --bind /proc /mnt/proc
$ sudo mount --bind /sys  /mnt/sys
$ sudo chroot /mnt
# nano /etc/fstab 

My /etc/fstab before manual editing
For some reason, my clean install of Ubuntu uses the old /dev/sda1 in the fstab entry. Either way, it's more flexible to use uuid when referring to partitions, so we'll just change it to use uuid instead. It should look something like this:

UUID=
25a9e1b2-d460-4734-83cb-caaf7c5cfe35  /  btrfs  defaults  0  1

Replace the uuid string with yours. Save changes and exit nano. The rest of the instructions all run within the chroot environment.

Updating Grub

Now you'll need to update grub to reflect the changes you've made. To do that, you'll need to install and patch grub2 first. The default grub doesn't detect btrfs partitions currently.

# apt-get install patch grub2
# wget http://launchpadlibrarian.net/36483885/legacy_detection.patch
# dpkg-divert --local --add /usr/sbin/grub-mkconfig
# dpkg-divert --local --add /usr/lib/grub/grub-mkconfig_lib
# nano legacy_detection.patch

Find the following two lines,

grub2-1.97~beta4/util/grub-mkconfig.in
grub2-1.97~beta4/util/grub-mkconfig_lib.in

and replace them with the following, respectively.

/usr/sbin/grub-mkconfig
/usr/lib/grub/grub-mkconfig_lib

Save your changes and apply the patch. Then, update grub's configuration files with the update-grub command.

# patch -p0 < legacy_detection.patch
# update-grub

Finally, remember to install grub2 into the root device. You'll get a grub error, otherwise, and won't even get to see the Ubuntu splash.

# grub-install /dev/sda

Press Ctrl+D to exit chroot, then reboot.

All done. Enjoy!

Partition layout and info, as seen in Disk Utility