Thursday, November 29, 2012

How To Convert An ext3/ext4 Root File System To btrfs

http://www.howtoforge.com/how-to-convert-an-ext3-ext4-root-file-system-to-btrfs-on-ubuntu-12.10


ext3 and ext4 file systems can be converted to btrfs. For non-root file systems, this can be done online (i.e., without reboot), while for root file systems we need to boot into some kind of rescue system or Live CD. This guide explains how to convert an ext3 or ext4 root file system into btrfs on Ubuntu 12.10 and how to roll back to ext3/ext4 again if desired.
I do not issue any guarantee that this will work for you!

1 Preliminary Note

I'm using a system here with one large / partition (i.e., no /boot partition) and without LVM. During initial installation, it was installed with the option Guided - Use entire disk. For different partition schemes, the procedure might differ.
My hard drive is named /dev/sda in this tutorial, my system partition is /dev/sda1.
I will use an Ubuntu 12.10 Desktop Live-CD as the rescue system throughout this tutorial.
I will show two ways of doing the conversion: one where we simply convert the system partition and change /etc/fstab, and one where we create the subvolumes @ and @home according to Ubuntu's btrfs partition layout (see https://help.ubuntu.com/community/btrfs) - this is slightly more complicated, but a must if you want to use apt-btrfs-snapshot which requires this subvolume layout.
A note for Ubuntu users:
Because we must run all the steps from this tutorial with root privileges, we can either prepend all commands in this tutorial with the string sudo, or we become root right now by typing
sudo su

2 Install btrfs-tools

On the original system, before we boot into the rescue system, install btrfs-tools so that the package is available when we chroot to the system partition in the rescue system (it is possible that we don't have a network connection for installing the package when we are chrooted into the system partition in the rescue system, that's why we should install it now):
apt-get install btrfs-tools
Now we must boot into some kind of rescue system with btrfs support. For example, you can insert the Ubuntu 12.10 Desktop CD into the CD drive (make sure it has the same architecture - i386 or x86_64 - as this system) and reboot:
reboot

3 Doing A Simple Conversion (No @ And @home Subvolumes)

In the rescue system, log in as root. Make sure that btrfs-tools are installed:
apt-get install btrfs-tools
Do a file system check...
fsck -f /dev/sda1
... and then run the conversion tool:
btrfs-convert /dev/sda1
root@ubuntu:~# btrfs-convert /dev/sda1
creating btrfs metadata.
creating ext2fs image file.
cleaning up system chunk.
conversion complete.
root@ubuntu:~#
Next we mount our system partition and chroot to it:
mount /dev/sda1 /mnt
for fs in proc sys dev dev/pts; do mount --bind /$fs /mnt/$fs; done
chroot /mnt
ls -l
As you see, there's now a folder called ext2_saved which contains an image of our system partition before the conversion (with the original ext3 or ext4 file system). This image can be used to do a rollback later on.
root@ubuntu:/# ls -l
total 20
drwxr-xr-x   1 root root 1938 Nov 22 13:15 bin
drwxr-xr-x   1 root root  326 Nov 23 18:38 boot
drwxr-xr-x  14 root root 4060 Nov 23 18:38 dev
drwxr-xr-x   1 root root 2820 Nov 23 18:38 etc
dr-xr-xr-x   1 root root   10 Nov 23 18:40 ext2_saved
drwxr-xr-x   1 root root   26 Nov 22 13:16 home
lrwxrwxrwx   1 root root   32 Nov 22 13:11 initrd.img -> boot/initrd.img-3.5.0-17-generic
lrwxrwxrwx   1 root root   33 Nov 22 13:11 initrd.img.old -> /boot/initrd.img-3.5.0-17-generic
drwxr-xr-x   1 root root  982 Nov 22 13:15 lib
drwxr-xr-x   1 root root   40 Nov 22 13:10 lib64
drwx------   1 root root    0 Nov 22 13:10 lost+found
drwxr-xr-x   1 root root   10 Nov 22 13:10 media
drwxr-xr-x   1 root root    0 Oct  9 17:03 mnt
drwxr-xr-x   1 root root    0 Oct 17 18:22 opt
dr-xr-xr-x 186 root root    0 Nov 23 18:38 proc
drwx------   1 root root   68 Nov 23 18:38 root
drwxr-xr-x   1 root root    0 Nov 22 13:16 run
drwxr-xr-x   1 root root 3094 Nov 23 18:38 sbin
drwxr-xr-x   1 root root    0 Jun 11 20:36 selinux
drwxr-xr-x   1 root root    0 Oct 17 18:22 srv
dr-xr-xr-x  13 root root    0 Nov 23 18:38 sys
drwxrwxrwt   1 root root    0 Nov 23 18:38 tmp
drwxr-xr-x   1 root root   70 Nov 22 13:10 usr
drwxr-xr-x   1 root root  114 Nov 23 18:38 var
lrwxrwxrwx   1 root root   29 Nov 22 13:11 vmlinuz -> boot/vmlinuz-3.5.0-17-generic
lrwxrwxrwx   1 root root   29 Nov 22 13:11 vmlinuz.old -> boot/vmlinuz-3.5.0-17-generic
root@ubuntu:/#
Run
blkid /dev/sda1
root@ubuntu:/# blkid /dev/sda1
/dev/sda1: UUID="63accb30-95b9-4268-ae1e-6d0ad3ef3a9d" UUID_SUB="d9521f58-91e5-44a7-a52e-9cfb0b3056ca" TYPE="btrfs"
root@ubuntu:/#
We need the UUID from the output for modifying /etc/fstab:
vi /etc/fstab
Comment out the old / partition line and add a new one. Replace the UUID with the UUID from the blkid output, then replace ext4 (or ext3) with btrfs, and finally replace the mount options (e.g. errors=remount-ro) with the string defaults:
# /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).
#
#                
# / was on /dev/sda1 during installation
#UUID=ad50ef37-797d-44ea-a8fa-ae61abe4d00f /               ext4    errors=remount-ro 0       1
UUID=63accb30-95b9-4268-ae1e-6d0ad3ef3a9d /               btrfs   defaults 0       1
# swap was on /dev/sda5 during installation
UUID=4dc578f3-c65c-4013-b643-72e70455b21b none            swap    sw              0       0
Next open /etc/grub.d/00_header...
vi /etc/grub.d/00_header
... and comment out line 93 (if [ -n "\${have_grubenv}" ]; then if [ -z "\${boot_once}" ]; then save_env recordfail; fi; fi):
[...]
function recordfail {
  set recordfail=1
  #if [ -n "\${have_grubenv}" ]; then if [ -z "\${boot_once}" ]; then save_env recordfail; fi; fi
}
[...]
If you don't do this, you will get the error...
error: sparse file not allowed
... when you boot from the btrfs file system, and you have to press ENTER to proceed with the boot process (see Ubuntu 12.10 + btrfs: error: sparse file not allowed).
Next run
update-grub
grub-install /dev/sda
and exit from the chroot:
exit
Reboot into the normal system (make sure you remove the Live CD from the CD drive):
reboot
If everything goes well, the system should come up without problems, now running on btrfs.
ls -l /
As you see, there's still the ext2_saved folder with the image of the original system in case you want to do a rollback:
root@server1:~# ls -l /
total 20
drwxr-xr-x   1 root root 1938 Nov 22 13:15 bin
drwxr-xr-x   1 root root  326 Nov 23 18:38 boot
drwxr-xr-x  14 root root 4080 Nov 23 18:43 dev
drwxr-xr-x   1 root root 2820 Nov 23 18:43 etc
dr-xr-xr-x   1 root root   10 Nov 23 18:40 ext2_saved
drwxr-xr-x   1 root root   26 Nov 22 13:16 home
lrwxrwxrwx   1 root root   32 Nov 22 13:11 initrd.img -> boot/initrd.img-3.5.0-17-generic
lrwxrwxrwx   1 root root   33 Nov 22 13:11 initrd.img.old -> /boot/initrd.img-3.5.0-17-generic
drwxr-xr-x   1 root root  982 Nov 22 13:15 lib
drwxr-xr-x   1 root root   40 Nov 22 13:10 lib64
drwx------   1 root root    0 Nov 22 13:10 lost+found
drwxr-xr-x   1 root root   10 Nov 22 13:10 media
drwxr-xr-x   1 root root    0 Oct  9 17:03 mnt
drwxr-xr-x   1 root root    0 Oct 17 18:22 opt
dr-xr-xr-x 100 root root    0 Nov 23 18:43 proc
drwx------   1 root root   84 Nov 23 18:42 root
drwxr-xr-x  17 root root  620 Nov 23 18:43 run
drwxr-xr-x   1 root root 3094 Nov 23 18:38 sbin
drwxr-xr-x   1 root root    0 Jun 11 20:36 selinux
drwxr-xr-x   1 root root    0 Oct 17 18:22 srv
dr-xr-xr-x  13 root root    0 Nov 23 18:43 sys
drwxrwxrwt   1 root root    0 Nov 23 18:42 tmp
drwxr-xr-x   1 root root   70 Nov 22 13:10 usr
drwxr-xr-x   1 root root  114 Nov 23 18:38 var
lrwxrwxrwx   1 root root   29 Nov 22 13:11 vmlinuz -> boot/vmlinuz-3.5.0-17-generic
lrwxrwxrwx   1 root root   29 Nov 22 13:11 vmlinuz.old -> boot/vmlinuz-3.5.0-17-generic
root@server1:~#
ls -l /ext2_saved/
root@server1:~# ls -l /ext2_saved/
total 1594360
-r-------- 1 root root 31137464320 Jan  1  1970 image
root@server1:~#
In fact, this is not a folder, it's a btrfs subvolume:
btrfs subvolume list /
root@server1:~# btrfs subvolume list /
ID 256 top level 5 path ext2_saved
root@server1:~#
If you are sure you want to stay with btrfs and don't want to do a rollback, you can delete that subvolume to free up some space:
btrfs subvolume delete /ext2_saved
Afterwards, the image should be gone:
ls -l /
root@server1:~# ls -l /
total 16
drwxr-xr-x  1 root root 1938 Nov 22 13:15 bin
drwxr-xr-x  1 root root  326 Nov 23 18:38 boot
drwxr-xr-x 14 root root 4080 Nov 23 18:43 dev
drwxr-xr-x  1 root root 2820 Nov 23 18:43 etc
drwxr-xr-x  1 root root   26 Nov 22 13:16 home
lrwxrwxrwx  1 root root   32 Nov 22 13:11 initrd.img -> boot/initrd.img-3.5.0-17-generic
lrwxrwxrwx  1 root root   33 Nov 22 13:11 initrd.img.old -> /boot/initrd.img-3.5.0-17-generic
drwxr-xr-x  1 root root  982 Nov 22 13:15 lib
drwxr-xr-x  1 root root   40 Nov 22 13:10 lib64
drwx------  1 root root    0 Nov 22 13:10 lost+found
drwxr-xr-x  1 root root   10 Nov 22 13:10 media
drwxr-xr-x  1 root root    0 Oct  9 17:03 mnt
drwxr-xr-x  1 root root    0 Oct 17 18:22 opt
dr-xr-xr-x 98 root root    0 Nov 23 18:43 proc
drwx------  1 root root   84 Nov 23 18:42 root
drwxr-xr-x 17 root root  620 Nov 23 18:43 run
drwxr-xr-x  1 root root 3094 Nov 23 18:38 sbin
drwxr-xr-x  1 root root    0 Jun 11 20:36 selinux
drwxr-xr-x  1 root root    0 Oct 17 18:22 srv
dr-xr-xr-x 13 root root    0 Nov 23 18:43 sys
drwxrwxrwt  1 root root    0 Nov 23 18:42 tmp
drwxr-xr-x  1 root root   70 Nov 22 13:10 usr
drwxr-xr-x  1 root root  114 Nov 23 18:38 var
lrwxrwxrwx  1 root root   29 Nov 22 13:11 vmlinuz -> boot/vmlinuz-3.5.0-17-generic
lrwxrwxrwx  1 root root   29 Nov 22 13:11 vmlinuz.old -> boot/vmlinuz-3.5.0-17-generic
root@server1:~#

4 Doing A Conversion According To Ubuntu Subvolume Layout (With @ And @home Subvolumes)

 
This is a bit more complicated and took me some time to figure out. It is absolutely necessary to follow each step in the same order as described!
In the rescue system, log in as root. Make sure that btrfs-tools are installed:
apt-get install btrfs-tools
Do a file system check...
fsck -f /dev/sda1
... and then run the conversion tool:
btrfs-convert /dev/sda1
root@ubuntu:~# btrfs-convert /dev/sda1
creating btrfs metadata.
creating ext2fs image file.
cleaning up system chunk.
conversion complete.
root@ubuntu:~#
Next we mount our system partition and chroot to it:
mount /dev/sda1 /mnt
for fs in proc sys dev dev/pts; do mount --bind /$fs /mnt/$fs; done
chroot /mnt
ls -l
As you see, there's now a folder called ext2_saved which contains an image of our system partition before the conversion (with the original ext3 or ext4 file system). This image can be used to do a rollback later on.
root@ubuntu:/# ls -l
total 20
drwxr-xr-x   1 root root 1938 Nov 22 13:15 bin
drwxr-xr-x   1 root root  326 Nov 23 18:38 boot
drwxr-xr-x  14 root root 4060 Nov 23 18:38 dev
drwxr-xr-x   1 root root 2820 Nov 23 18:38 etc
dr-xr-xr-x   1 root root   10 Nov 23 18:40 ext2_saved
drwxr-xr-x   1 root root   26 Nov 22 13:16 home
lrwxrwxrwx   1 root root   32 Nov 22 13:11 initrd.img -> boot/initrd.img-3.5.0-17-generic
lrwxrwxrwx   1 root root   33 Nov 22 13:11 initrd.img.old -> /boot/initrd.img-3.5.0-17-generic
drwxr-xr-x   1 root root  982 Nov 22 13:15 lib
drwxr-xr-x   1 root root   40 Nov 22 13:10 lib64
drwx------   1 root root    0 Nov 22 13:10 lost+found
drwxr-xr-x   1 root root   10 Nov 22 13:10 media
drwxr-xr-x   1 root root    0 Oct  9 17:03 mnt
drwxr-xr-x   1 root root    0 Oct 17 18:22 opt
dr-xr-xr-x 186 root root    0 Nov 23 18:38 proc
drwx------   1 root root   68 Nov 23 18:38 root
drwxr-xr-x   1 root root    0 Nov 22 13:16 run
drwxr-xr-x   1 root root 3094 Nov 23 18:38 sbin
drwxr-xr-x   1 root root    0 Jun 11 20:36 selinux
drwxr-xr-x   1 root root    0 Oct 17 18:22 srv
dr-xr-xr-x  13 root root    0 Nov 23 18:38 sys
drwxrwxrwt   1 root root    0 Nov 23 18:38 tmp
drwxr-xr-x   1 root root   70 Nov 22 13:10 usr
drwxr-xr-x   1 root root  114 Nov 23 18:38 var
lrwxrwxrwx   1 root root   29 Nov 22 13:11 vmlinuz -> boot/vmlinuz-3.5.0-17-generic
lrwxrwxrwx   1 root root   29 Nov 22 13:11 vmlinuz.old -> boot/vmlinuz-3.5.0-17-generic
root@ubuntu:/#
Run
blkid /dev/sda1
root@ubuntu:/# blkid /dev/sda1
/dev/sda1: UUID="d6c9b57b-caa1-4a88-b659-930c130b337f" UUID_SUB="ea7b087e-683f-4f43-8007-bb5281f64e4c" TYPE="btrfs"
root@ubuntu:/#
We need the UUID from the output for modifying /etc/fstab:
vi /etc/fstab
Comment out the old / partition line and add a new one. Replace the UUID with the UUID from the blkid output, then replace ext4 (or ext3) with btrfs, and finally replace the mount options (e.g. errors=remount-ro) with the string defaults,subvol=@ - this makes the system boot from the subvolume @ (which is to e created yet) instead of the top-level volume:
# /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).
#
#                
# / was on /dev/sda1 during installation
#UUID=ad50ef37-797d-44ea-a8fa-ae61abe4d00f /               ext4    errors=remount-ro 0       1
UUID=d6c9b57b-caa1-4a88-b659-930c130b337f /               btrfs   defaults,subvol=@ 0       1
# swap was on /dev/sda5 during installation
UUID=4dc578f3-c65c-4013-b643-72e70455b21b none            swap    sw              0       0
Next open /etc/grub.d/00_header...
vi /etc/grub.d/00_header
... and comment out line 93 (if [ -n "\${have_grubenv}" ]; then if [ -z "\${boot_once}" ]; then save_env recordfail; fi; fi):
[...]
function recordfail {
  set recordfail=1
  #if [ -n "\${have_grubenv}" ]; then if [ -z "\${boot_once}" ]; then save_env recordfail; fi; fi
}
[...]
If you don't do this, you will get the error...
error: sparse file not allowed
... when you boot from the btrfs file system, and you have to press ENTER to proceed with the boot process (see Ubuntu 12.10 + btrfs: error: sparse file not allowed).
Before we update the GRUB boot loader, we must make sure that it will include the boot option rootflags=subvol=@. Check the output of
grub-mkconfig | grep " ro "
If it looks like this (i.e., it contains rootflags=subvol=@), everything is ok, and you can proceed with the update-grub command a few lines below:
root@ubuntu:/# grub-mkconfig | grep " ro "
Generating grub.cfg ...
Found linux image: /boot/vmlinuz-3.5.0-17-generic
Found initrd image: /boot/initrd.img-3.5.0-17-generic
        linux   /boot/vmlinuz-3.5.0-17-generic root=UUID=d6c9b57b-caa1-4a88-b659-930c130b337f ro rootflags=subvol=@
                linux   /boot/vmlinuz-3.5.0-17-generic root=UUID=d6c9b57b-caa1-4a88-b659-930c130b337f ro rootflags=subvol=@
                linux   /boot/vmlinuz-3.5.0-17-generic root=UUID=d6c9b57b-caa1-4a88-b659-930c130b337f ro recovery nomodeset rootflags=subvol=@
Found memtest86+ image: /boot/memtest86+.bin
done
root@ubuntu:/#
But if the output looks as follows (no appearance of rootflags=subvol=@)...
root@ubuntu:/# grub-mkconfig | grep " ro "
Generating grub.cfg ...
Found linux image: /boot/vmlinuz-3.5.0-17-generic
Found initrd image: /boot/initrd.img-3.5.0-17-generic
        linux   /boot/vmlinuz-3.5.0-17-generic root=UUID=d6c9b57b-caa1-4a88-b659-930c130b337f ro
                linux   /boot/vmlinuz-3.5.0-17-generic root=UUID=d6c9b57b-caa1-4a88-b659-930c130b337f ro
                linux   /boot/vmlinuz-3.5.0-17-generic root=UUID=d6c9b57b-caa1-4a88-b659-930c130b337f ro recovery nomodeset
Found memtest86+ image: /boot/memtest86+.bin
done
root@ubuntu:/#
... we must modify /etc/grub.d/10_linux:
vi /etc/grub.d/10_linux
Comment out lines 67 and 68 and add rootsubvol="@" in line 69:
[...]
case x"$GRUBFS" in
    xbtrfs)
        #rootsubvol="`make_system_path_relative_to_its_root /`"
        #rootsubvol="${rootsubvol#/}"
        rootsubvol="@"
        if [ "x${rootsubvol}" != x ]; then
            GRUB_CMDLINE_LINUX="rootflags=subvol=${rootsubvol} ${GRUB_CMDLINE_LINUX}"
        fi;;
    xzfs)
        rpool=`${grub_probe} --device ${GRUB_DEVICE} --target=fs_label 2>/dev/null || true`
        bootfs="`make_system_path_relative_to_its_root / | sed -e "s,@$,,"`"
        LINUX_ROOT_DEVICE="ZFS=${rpool}${bootfs}"
        ;;
esac
[...]
Now we continue with updating the GRUB boot loader:
update-grub
grub-install /dev/sda
Now we create the @ subvolume as a snapshot of the top level volume:
btrfs subvolume snapshot / /@
Then we create the @home subvolume...
btrfs subvolume create /@home
... and copy the contents from /home to it and make sure that /home and /@/home (which contains the same contents as /home because /@ is a snapshot of /) are empty so that the @home subvolume can be mounted to /home when we reboot the system:
rsync --progress -aHAX /home/* /@home
rm -fr /home/*
rm -fr /@/home/*
Then open /etc/fstab...
vi /etc/fstab
... and add the line UUID=d6c9b57b-caa1-4a88-b659-930c130b337f /home btrfs defaults,subvol=@home 0 2 (make sure you use the same UUID as for the / partition!) to it:
# /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).
#
#                
# / was on /dev/sda1 during installation
#UUID=ad50ef37-797d-44ea-a8fa-ae61abe4d00f /               ext4    errors=remount-ro 0       1
UUID=d6c9b57b-caa1-4a88-b659-930c130b337f /               btrfs   defaults,subvol=@ 0       1
UUID=d6c9b57b-caa1-4a88-b659-930c130b337f /home               btrfs   defaults,subvol=@home 0       2
# swap was on /dev/sda5 during installation
UUID=4dc578f3-c65c-4013-b643-72e70455b21b none            swap    sw              0       0
Next copy the modifed fstab to our @ subvolume:
cp /etc/fstab /@/etc/fstab
Leave the chroot:
exit
Unmount /mnt and mount the @ subvolume to it:
umount /mnt/dev/pts
umount /mnt/dev
umount /mnt/sys
umount /mnt/proc
umount /mnt
mount -o subvol=@ /dev/sda1 /mnt
for fs in proc sys dev dev/pts; do mount --bind /$fs /mnt/$fs; done
chroot /mnt
grub-mkconfig | grep " ro "

No comments:

Post a Comment