Friday, June 1, 2012

HowTo: Converting EXT4 to BTRFS in Fedora 17

This HowTo documents the steps I used on a Fedora 17 x86_64 test machine to convert the root file system from Ext4 to Btrfs.

Anaconda (Fedora installer) doesn't support the creation or manipulation of Btrfs file systems in the graphical installer. Support for this is slated for Fedora 18, at which time, Btrfs may become the default file system!

It is possible, however, to create Btrfs file systems at install time via Kickstart.

The virtual machine was installed with Fedora 17 x86_64 using default partitioning (LVM and Ext4) and selecting the Desktop profile.

If possible, create the partitions without LVM. (see section at the bottom for an example of this and UUID)

In the examples, the root file system is a logical volume: /dev/mapper/vg_f17vm-lv_root

Following the install and the initial boot, I rebooted using the Fedora 17 x86_64 Live CD and chose the option to Try Fedora.

I initially tried to perform the conversion using the Fedora 17 DVD and rescue mode, however the btrfs-convert utility isn't included. The live CD, however, includes the Btrfs utilities.

Convert EXT4 root

All of the steps are performed using the terminal, so open a Gnome Terminal and SU to root:
$ su -

Run fsck on the file system
# fsck.ext4 -f /dev/mapper/vg_f17vm-lv_root

Convert from ext4 to btrfs. The metadata stage can take a while on a large populated file system (on an 1.5TB ext4 file system with approx 500GB of data, a good mix of large and small files, this step took about 1.5 hours)
# btrfs-convert /dev/mapper/vg_f17vm-lv_root

creating btrfs metadata.
creating ext2fs image file.
cleaning up system chunk.
conversion complete.

Mount the freshly converted btrfs root file system so that we can make some modifications (fstab, SELinux)
# mkdir /mnt/btrfs
# mount -t btrfs /dev/mapper/vg_f17vm-lv_root /mnt/btrfs

Edit fstab to change the root file system from ext4 to btrfs
# vi /mnt/btrfs/etc/fstab

#/dev/mapper/vg_f17vm-lv_root              ext4   defaults    1 1
/dev/mapper/vg_f17vm-lv_root              btrfs   defaults    1 1

Force the system to automatically relabel the SELinux context for the root file system during boot.
# touch /mnt/btrfs/.autorelabel

NOTE: In my test, the Fedora 17 system would hang with systemd library permissions errors prior to getting to the SELinux auto relabel step.

To work around this, I rebooted back into the Live CD and change the SELinux policy to "permissive" from "enforcing". During the next boot, the permission errors went by and then the SELinux autorelabel ran to completion.
# vi /mnt/btrfs/etc/selinux/config

#SELINUX=enforcing
SELINUX=permissive

The Btrfs conversion process created a subvolume of the old ext4 file system. The following commands mount the subvolume and file system, demonstrating the power of Btrfs.
# mkdir /mnt/{ext2_saved,ext4}
# mount -t btrfs -o subvol=ext2_saved /dev/mapper/vg_f17vm-lv_root /mnt/ext2_saved
# mount -t ext4 -o loop,ro /mnt/ext2_saved/image /mnt/ext4

The contents of the ext4 and btrfs mounts should be identical, sans the changes made above to fstab and config.

It's possible to roll back the conversion by first unmounting the file systems and then rolling it back using the -r switch
# umount /dev/mapper/vg_f17vm-lv_root
# btrfs-convert -r /dev/mapper/vg_f17vm-lv_root

If you decide to stay with btrfs, you can delete the subvolume snapshot of the original ext4 system
# btrfs subvolume delete /mnt/btrfs/ext2_saved

Reboot into the installed OS and the system should perform the relabel and then come up with your shiny new btrfs file system.

To make things really cool, install the yum-plugin-fs-snapshot Yum plugin. This plugin will create a btrfs subvolume of your root file system prior to installing updates. The end result, you can roll back from yum updates. Test that you can mount the snapshot of the ext4 file system

Once the system is up and running, don't forget to set the SELinux policy back to "enforcing"

Issues:
  1. It appears that some of the systemd services attempt to start prior to the SELinux .autorelabel step. This results in permission errors that prevent the system from booting. Temporarily change the SELinux policy to "permissive" to work past this.
  2. During boot, you may see errors logged by the systemd-fsck service failing for lv_root due to missing fsck.btrfs. I suspect that the btrfs-progs rpm failed to create a symlink of fsck.btrf pointing to /usr/sbin/btrfsck
systemd-fsck[858]: fsck: fsck.btrfs: not found
systemd-fsck[858]: fsck: error 2 while executing fsck.btrfs for /dev/mapper/vg_f17vm-lv_root

Convert Luks Encrypted EXT4 home

If your file system is encrypted with Luks, you'll have the additional step of decrypting the file system prior to running the conversion
# cryptsetup luksOpen /dev/mapper/vg_f17vm-lv_home luks_home
# fsck.ext4 -f /dev/mapper/luks_home
# btrfs-convert /dev/mapper/luks_home

creating btrfs metadata.
creating ext2fs image file.
cleaning up system chunk.
conversion complete.

Converting Non LVM Ext4 and UUID in /etc/fstab

If you don't use LVM (recommended based on everything I've ready, since it's not needed for btrfs), your /etc/fstab may mount the partitions using the UUID. After converting the file system to btrfs, the UUID will change.

These steps demonstrate how to convert the root file syste, a non LVM ext4 partition, /dev/sda2.
# fsck.ext4 -f /dev/sda2
# btrfs-convert /dev/sda2

creating btrfs metadata.
creating ext2fs image file.
cleaning up system chunk.
conversion complete.
Identify the UUID using blkid (can also look under /dev/disk/by-uuid
# blkid /dev/sda2

/dev/sda2: UUID="56d1e02b-3120-44c3-b8f8-d3289012e447" UUID_SUB="13f7b26b-42b1-41bb-a9dc-c928ad033f6d" TYPE="btrfs" 


# mkdir /mnt/btrfs
# mount -t btrfs /dev/sda2 /mnt/btrfs


Edit fstab to change the root file system from ext4 to btrfs and replace the UUID with the new UUID
# vi /mnt/btrfs/etc/fstab

#UUID=e14bd8d6-ac8a-4f15-8169-f0a9bdf4b69e /                       ext4    defaults        1 1
UUID=56d1e02b-3120-44c3-b8f8-d3289012e447 /                       btrfs    defaults        1 1
UUID=f4cdf95d-66eb-4428-960d-23b289ffb63e /boot                   ext4    defaults        1 2

Chroot to the real root file system and update grub.cfg using grub2-mkconfig

# mount -o bind /dev /mnt/btrfs/dev
# mount -o bind /proc /mnt/btrfs/proc
# mount -o bind /sys /mnt/btrfs/sys
# mount /dev/sda1 /mnt/btrfs/boot

# chroot /mnt/btrfs

# grub2-mkconfig -o /boot/grub2/grub.cfg 

Generating grub.cfg ...
Found linux image: /boot/vmlinuz-3.4.3-1.fc17.x86_64
Found initrd image: /boot/initramfs-3.4.3-1.fc17.x86_64.img
Found linux image: /boot/vmlinuz-3.3.4-5.fc17.x86_64
Found initrd image: /boot/initramfs-3.3.4-5.fc17.x86_64.img
Warning: Please don't use old title `Fedora Linux, with Linux 3.3.4-5.fc17.x86_64' for GRUB_DEFAULT, use `Advanced options for Fedora Linux>Fedora Linux, with Linux 3.3.4-5.fc17.x86_64' (for versions before 2.00) or `gnulinux-advanced-/dev/sda2>gnulinux-3.3.4-5.fc17.x86_64-advanced-/dev/sda2' (for 2.00 or later)
done
Exit out of the chroot and unmount the file systems
# exit
# umount /mnt/btrfs/boot
# umount /mnt/btrfs/dev
# umount /mnt/btrfs/proc
# umount /mnt/btrfs/sys
# umount /mnt/btrfs


Reboot and you should be good to go. The selinux relabeling can take a while!

References:

3 comments:

FlakRat said...

I updated the main body of the howto with an example of converting a Luks encrypted file system.

FlakRat said...

I updated the main body of the post with an example of converting a non LVM ext4 and dealing with changed UUIDs.

Bingo said...

Tried the convert from luks encrypted step. Getting core dumped message

, dmesg shows this :
[ 201.571593] btrfs-convert[1433]: segfault at ffffffffffffffc0 ip 00007fbe77b93ee5 sp 00007fffe8ee9368 error 4 in libc-2.15.so[7fbe77a35000+1ac000]

First tried on an SSD, thought might be an SSD issue, but then same issue reproduced on rotating HDD also