Menggunakan BTRFS Sebagai Filesystem Utama Di Slackware

Submitted by w41lf0x on Wed, 04/23/2014 - 01:53

slackwareSudah pernah mendengar tentang #btrfs? Mungkin malah sudah ada yang mencobanya. Dalam tulisan ini saya akan menjelaskan pengalaman saya menggunakan filesystem btrfs sebagai filesystem utama (ROOTFS) untuk #slackware #linux 64-bit. Harap diingat, bahwa percobaan ini menggunakan sebuah kloning mesin virtual yang saya jalankan dalam emulator Qemu. Jadi saran saya buat sampeyan-sampeyan yang ingin mencoba teknik ini, harap gunakan mesin virtual karena resiko dari teknik yang teramat tidak resmi ini adalah sistem anda gagal booting. Tentu saja saya tidak akan menanggung dosa dari perbuatan anda sendiri jika anda mencobanya di mesin produksi anda. Anda sudah saya ingatkan lho ya.

Baik, saya lanjutkan ke topik. Hal pertama yang harus saya lakukan tentunya adalah menyiapkan filesystem btrfs untuk ditempati segala berkas dan direktori sistem slackware. Karena saya menggunakan sebuah kloning mesin virtual, maka saya melakukannya dengan cara yang sedikit berbeda seperti berikut ini. Kebetulan saya sudah memisahkan /boot ke partisi tersendiri sebelumnya.

Saya boot mesin virtual kloningan menggunakan installer slackware64-14.1 dengan menyertakan image harddisk dari mesin virtual asli (pertama). Image harddisk mesin virtual asli ini akan saya gunakan sebagai sumber berkas dan direktori sistem. Jadi saya menggunakan dua harddisk: vda (calon hdd oprekan) dan vdb (vm asli).

Setelah mendapat shell dari installer slackware, saya memformat partisi sistem slackware di harddisk VM kloning (partisi vda3). Saya juga membuat beberapa subvolume untuk memisahkan beberapa direktori utama sistem yang menurut saya lebih baik dipisah :-D 

# mkfs.btrfs -L SYSTEM -f /dev/vda3
# mkdir -p /mnt/SYSTEM
# mount -t btrfs /dev/vda3 /mnt/SYSTEM
# btrfs subvolume create /mnt/SYSTEM/rootfs
# btrfs subvolume create /mnt/SYSTEM/usr
# btrfs subvolume create /mnt/SYSTEM/var
# btrfs subvolume create /mnt/SYSTEM/tmp
# btrfs subvolume create /mnt/SYSTEM/home

Saya juga membuat subvolume tambahan yaitu slack32 untuk sistem slackware 32-bit yang terkadang saya gunakan untuk membangun program-program 32-bit di slackware 64-bit.

# btrfs subvolume create /mnt/SYSTEM/slack32

Kemudian saya mount semua subvolume ke dalam struktur seperti ini:

# mkdir -p /mnt/rootfs
# mount -t btrfs -o defaults,subvol=rootfs /dev/vda3 /mnt/rootfs
# mkdir -p /mnt/rootfs/usr
# mount -t btrfs -o defaults,subvol=usr /dev/vda3 /mnt/rootfs/usr
# mkdir -p /mnt/rootfs/var
# mount -t btrfs -o defaults,subvol=var /dev/vda3 /mnt/rootfs/var
# mkdir -p /mnt/rootfs/tmp
# mount -t btrfs -o defaults,subvol=tmp /dev/vda3 /mnt/rootfs/tmp
# mkdir -p /mnt/rootfs/usr
# mount -t btrfs -o defaults,subvol=usr /dev/vda3 /mnt/rootfs/usr
# mkdir -p /mnt/rootfs/home
# mount -t btrfs -o defaults,subvol=home /dev/vda3 /mnt/rootfs/home
# mkdir -p /mnt/rootfs/slack32
# mount -t btrfs -o defaults,subvol=slack32 /dev/vda3 /mnt/rootfs/slack32

Lalu saya mount vdb3 dan menduplikasi isi partisi sistem dari VM asli ke vda3:

# mkdir -p /mnt/ROOTASLI
# mount /dev/vdb3 /mnt/ROOTASLI
# cd /mnt/ROOTASLI
# tar cvpf - . | (cd /mnt/rootfs; tar xpf -)

Setelah duplikasi sistem selesai, waktunya mempersiapkan kebutuhan untuk mem-boot sistem slackware dalam filesystem btrfs. Saya mount partisi boot VM kloning ke /boot rootfs btrfs. Saya juga menautkan /dev, /proc, /sys dari sistem installer ke rootfs btrfs agar saya dapat menginisiasi boot loader VM kloning.

# mount /dev/vda1 /mnt/rootfs/boot
# mount --bind /dev /mnt/rootfs/dev
# mount --bind /proc /mnt/rootfs/proc
# mount --bind /sys /mnt/rootfs/sys
# chroot /mnt/rootfs

Pada tahap ini saya menyesuaikan /etc/fstab sesuai dengan struktur subvolume btrfs tersebut.

/dev/vda4        swap             swap        defaults         0   0
UUID="d9267b40-be1f-44a4-9294-4d9565f879b5"   /                btrfs       defaults,noatime,compress=lzo,autodefrag,subvol=rootfs   0   0
UUID="d9267b40-be1f-44a4-9294-4d9565f879b5"   /home            btrfs       defaults,noatime,compress=lzo,autodefrag,subvol=home    0    0
UUID="d9267b40-be1f-44a4-9294-4d9565f879b5"   /tmp             btrfs       defaults,noatime,compress=lzo,autodefrag,subvol=tmp    0    0
UUID="d9267b40-be1f-44a4-9294-4d9565f879b5"   /var             btrfs       defaults,noatime,compress=lzo,autodefrag,subvol=var    0    0
UUID="d9267b40-be1f-44a4-9294-4d9565f879b5"   /usr             btrfs       defaults,noatime,compress=lzo,autodefrag,subvol=usr    0    0
UUID="d9267b40-be1f-44a4-9294-4d9565f879b5"   /slack32         btrfs       defaults,noatime,compress=lzo,autodefrag,subvol=slack32    0    0
/dev/vda1        /boot            ext4        defaults         1   2
/dev/cdrom       /mnt/cdrom       auto        noauto,owner,ro,comment=x-gvfs-show 0   0
/dev/fd0         /mnt/floppy      auto        noauto,owner     0   0
devpts           /dev/pts         devpts      gid=5,mode=620   0   0
proc             /proc            proc        defaults         0   0
tmpfs            /dev/shm         tmpfs       defaults         0   0

Saya harus mengubah sedikit skrip mkinitrd milik slackware supaya saya dapat memasukkan parameter subvolume (rootflags) ke dalam initrd-tree sebelum dipadatkan menjadi initrd. Saya juga harus mengubah sedikit skrip init dari initrd-tree agar memuat parameter rootflags dalam baris mount ROOT filesystem. Berikut ini adalah perbedaan antara kedua skrip tersebut jika dibandingkan dengan yang sudah saya ubah.

--- /sbin/mkinitrd.orig	2015-04-22 00:07:40.997722836 +0700
+++ /sbin/mkinitrd	2015-04-22 08:54:26.002904829 +0700
@@ -89,6 +89,7 @@
           unlocked by the initrd using cryptsetup. All devices that must
           be unlocked in order to access the root filesystem must be
           specified. (Use with '-r' parameter).
+  -G      Btrfs ROOT subvolume
   -L      Add support for LVM partitions
   -K      Use a USB key (fat-formatted) to unlock the root LUKS volume
           The parameter value is filename of a keyfile, as well as the label
@@ -355,6 +356,10 @@
       LUKSDEV="$2"
       shift 2
       ;;
+    -G)
+      ROOTFLAGS="$2"
+      shift 2
+      ;;
     -K)
       LUKSKEY="$2"
       shift 2
@@ -414,7 +419,17 @@
   echo $ROOTDEV > $SOURCE_TREE/rootdev
 fi
 if [ ! -z "$ROOTFS" ]; then
-  echo $ROOTFS > $SOURCE_TREE/rootfs
+  if [ ! "$ROOTFS" = "btrfs" ]; then
+    echo $ROOTFS > $SOURCE_TREE/rootfs
+  else
+    if [ -z "$ROOTFLAGS" ]; then
+      echo "Failed: Please define ROOT Subvolume if using btrfs, ie. -G subvol=rootfs"
+      exit 1
+    else
+      echo $ROOTFLAGS > $SOURCE_TREE/rootflags
+      echo $ROOTFS > $SOURCE_TREE/rootfs
+    fi
+  fi
 fi
 
 # If $WAIT is not set, assume we need only one second
--- init.orig	2013-10-29 11:34:30.000000000 +0700
+++ init-btrfs	2015-04-22 08:56:11.307288474 +0700
@@ -73,6 +73,7 @@
 INITRD=$(cat /initrd-name)
 ROOTDEV=$(cat /rootdev)
 ROOTFS=$(cat /rootfs)
+ROOTFLAGS=$(cat /rootflags)
 LUKSDEV=$(cat /luksdev)
 LUKSKEY=$(cat /lukskey)
 RESUMEDEV=$(cat /resumedev)
@@ -125,6 +126,9 @@
     rootfs=*|rootfstype=*)
       ROOTFS=$(echo $ARG | cut -f2 -d=)
     ;;
+    rootflags=*)
+      ROOTFLAGS=$(echo $ARG | cut -f2- -d=)
+    ;;
     waitforroot=*|rootdelay=*)
       WAIT=$(echo $ARG | cut -f2 -d=)
     ;;
@@ -295,7 +299,12 @@
   # Switch to real root partition:
   /sbin/udevadm settle --timeout=10
   echo 0x0100 > /proc/sys/kernel/real-root-dev
-  mount -o ro -t $ROOTFS $ROOTDEV /mnt
+  if [ ! -z "$ROOTFLAGS" ]; then
+    echo "Found $ROOTFLAGS in $ROOTFS in $ROOTDEV"
+    mount -o ro,$ROOTFLAGS -t $ROOTFS $ROOTDEV /mnt
+  else
+    mount -o ro -t $ROOTFS $ROOTDEV /mnt
+  fi
   
   if [ ! -r /mnt/sbin/init ]; then
     echo "ERROR:  No /sbin/init found on rootdev (or not mounted).  Trouble ahead."

Kemudian saya menyusun initrd-tree baru dengan perintah seperti ini

mkinitrd -c -k 3.14.33 -r /dev/vda3 -f btrfs -G subvol=rootfs -m ext4:btrfs:virtio:virtio_ring:virtio_scsi:virtio_blk:virtio_pci:virtio_net:virtio_mmio:virtio_balloon:virtio_rng:virtio_console:9pnet_virtio:9pnet -u -B -o /dev/null

Setelah initrd-tree terbentuk, saya mengganti skrip initrd-tree/init (skrip init yang digunakan dalam initrd) dengan skrip init yang sudah saya ubah

# cat init-btrfs > /boot/initrd-tree/init

Lalu saya jalankan lagi mkinitrd untuk membuat file initrd tanpa membersihkan isi /boot/initrd-tree terlebih dahulu (tanpa opsi `-c') sehingga skrip init yang sudah diubah tidak diganti dengan yang asli.

mkinitrd -k 3.14.33 -r /dev/vda3 -f btrfs -G subvol=rootfs -m ext4:btrfs:virtio:virtio_ring:virtio_scsi:virtio_blk:virtio_pci:virtio_net:virtio_mmio:virtio_balloon:virtio_rng:virtio_console:9pnet_virtio:9pnet -u -B -o /boot/initrd-3.14.33

Sebelum reboot, saya memperbarui grub.cfg karena saya menggunakan boot loader grub2. Catatan: setelah melalui percobaan berulang-ulang yang berujung pada kegagalan switch_root, saya harus mengubah konfigurasi /etc/default/grub untuk menonaktifkan penggunaan UUID untuk konfigurasi grub.cfg. Saya mengetahuinya setelah berulang kali init initrd tidak dapat menampilkan ROOTDEV meskipun telah saya tuliskan dalam perintah mkinitrd dengan opsi `-r /dev/vda3'. Ternyata skrip init dari initrd-tree akan memprioritaskan parameter UUID di dalam baris perintah boot kernel punya grub2 daripada miliknya sendiri. Sedangkan setelah saya cek dengan perintah blkid dari initrd, UUID untuk vda3 yang berisi filesystem btrfs tidak terdeteksi. Mungkin PV perlu memperbarui struktur initrd-tree agar dapat mengenali UUID untuk partisi/filesystem btrfs.

# FILE: /etc/default/grub
# Uncomment if you don't want GRUB to pass "root=UUID=xxx" parameter to Linux
GRUB_DISABLE_LINUX_UUID=true
# grub-mkconfig -o /boot/grub/grub.cfg

Lalu reboot dan slackware dengan filesystem / menggunakan btrfs dapat berjalan normal.

Mudah-mudahan tidak ada yang terlewat karena sudah kemarin opreknya.

Sekali lagi jika ingin mencobanya, selalu gunakan mesin virtual atau mesin yang benar-benar diperuntukkan untuk mengoprek.

Selamat mencoba.