Skip to content

Instantly share code, notes, and snippets.

@jirutka
Last active March 15, 2021 04:07
Show Gist options
  • Star 10 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jirutka/990d25662e729669b3ce to your computer and use it in GitHub Desktop.
Save jirutka/990d25662e729669b3ce to your computer and use it in GitHub Desktop.
Btrfs in RAID1 as a root filesystem on Gentoo

Btrfs in RAID1 as a root filesystem on Gentoo

Partitioning scheme

Partition Filesystem Size Description
sd*1 ext2 (md/raid1) 256 MiB boot (kernel etc.)
sd*2 sw (md/raid1) 4 GiB swap
sd*3 Btrfs (raid1) * Btrfs

A. Create GPT partitions and filesystems

  1. Create GPT partition table on each disk:

    parted -a optimal
    unit MiB
    mklabel gpt
    mkpart primary 1 256
    mkpart primary 256 4352
    mkpart primary btrfs 4352 -1
    set 1 legacy_boot on
    quit
    
  2. Create Btrfs filesystem in raid1 mode on the third partitions, create subvolume for / and mount it into /mnt/gentoo:

    mkfs.btrfs -L btrfsvol -d raid1 -m raid1 /dev/sda3 /dev/sdb3
    mkdir /mnt/btrfs
    mount -t btrfs -o defaults,noatime,compress=lzo,autodefrag -L btrfsvol /mnt/btrfs
    btrfs subvolume create /mnt/btrfs/root
    umount /mnt/btrfs
    mount -t btrfs -o defaults,noatime,compress=lzo,autodefrag,subvol=root -L btrfsvol /mnt/gentoo
  3. Create md raid1 array with ext2 filesystem on the first partitions and mount it to /mnt/gentoo/boot:

    mdadm --create /dev/md0 --name boot --level 1 --metadata 1.0 --raid-devices=2 /dev/sda1 /dev/sdb1
    mkfs.ext2 -L boot /dev/md0
    mkdir -p /mnt/gentoo/boot
    mount /dev/md0 /mnt/gentoo/boot

    Note: extlinux cannot boot from md with metadata v1.2 (read here)!

  4. Create md raid1 array with swap on the second partitions:

    mdadm --create /dev/md1 --name swap --level 1 --metadata 1.2 --raid-devices=2 /dev/sda2 /dev/sdb2
    mkswap -L swap /dev/md1

B. Install Gentoo

Read handbook ;)

C. Create initramfs

  1. Install busybox and mdadm with USE="static", and btrfs-progs:

    USE="static -pam" emerge -av sys-apps/busybox
    USE="static" emerge -av sys-fs/mdadm
    emerge -av sys-fs/btrfs-progs
  2. Create directory /usr/src/initramfs and copy files initramfs_list and init into it.

  3. Generate mdadm.conf:

    mdadm --detail --scan > /usr/src/initramfs/mdadm.conf
  4. Build initramfs:

    cd /usr/src/linux
    make -C /usr/src/linux/usr/ gen_init_cpio
    ./scripts/gen_initramfs_list.sh -o /boot/initrd.cpio.gz /usr/src/initramfs/initramfs_list

D. Install syslinux bootloader

  1. Install syslinux package:

    emerge -va sys-boot/syslinux
  2. Copy extlinux MBR for GPT to physical disks (not partions!):

    cat /usr/share/syslinux/gptmbr.bin > /dev/sda
    cat /usr/share/syslinux/gptmbr.bin > /dev/sdb
  3. Install extlinux to /boot/extlinux:

    mkdir -p /boot/extlinux
    extlinux --raid --install /boot/extlinux
  4. Copy provided extlinux.conf to /boot/extlinux/ and modify path of the kernel file if needed.

default linux
# Always display boot prompt.
prompt 1
# Wait 5 seconds unless the user types something.
timeout 50
label linux
kernel /current-kernel
initrd /initrd.cpio.gz
append root=LABEL=btrfsvol rootfstype=btrfs rootflags=defaults,noatime,compress=lzo,autodefrag,subvol=root net.ifnames=0
# /etc/fstab: static file system information.
#
# The root filesystem should have a pass number of either 0 or 1.
# All other filesystems should have a pass number of 0 or greater than 1.
#
# See the manpage fstab(5) for more information.
#
# <fs> <mountpoint> <type> <opts> <dump/pass>
LABEL="boot" /boot ext2 noauto,noatime 1 2
LABEL="btrfsvol" / brtfs defaults,noatime,compress=lzo,autodefrag,subvol=root 0 1
LABEL="swap" none swap sw 0 0
#!/bin/busybox sh
ROOT_MOUNT_LABEL="btrfsvol"
ROOT_MOUNT_OPTS="defaults,noatime,compress=lzo,autodefrag,subvol=root"
SWAP_MOUNT_LABEL="swap"
rescue_shell() {
echo "$@"
echo "Something went wrong. Dropping you to a shell."
busybox --install -s
exec /bin/sh
}
mount_root() {
echo "Mounting root filesystem"
/sbin/btrfs device scan || return 1
mount -t btrfs -o $ROOT_MOUNT_OPTS \
$(dev_by_label "$ROOT_MOUNT_LABEL") /mnt/root
}
mount_swap() {
echo "Assembling RAID arrays and enabling swap"
/sbin/mdadm --assemble --scan || return 1
swapon $(dev_by_label "$SWAP_MOUNT_LABEL")
}
dev_by_label() {
findfs LABEL="$1" || {
echo "FS with LABEL=$1 not found"
return 1
}
}
# Temporarily mount /proc, /sys and /dev filesystems.
mount -t proc none /proc
mount -t sysfs none /sys
mount -t devtmpfs none /dev
# Disable kernel messages from popping onto the screen.
echo 0 > /proc/sys/kernel/printk
clear
mount_root || rescue_shell "Failed to mount root filesystem!"
mount_swap || echo "Failed to mount swap. This is not critical, so keep going."
echo "All done, switching to real root."
# Clean up; the init process will remount them later.
umount /proc
umount /sys
umount /dev
# Switch to the real root and execute init.
exec switch_root /mnt/root /sbin/init
# directory structure
dir /bin 755 0 0
dir /dev 755 0 0
dir /etc 755 0 0
dir /lib64 755 0 0
dir /mnt 755 0 0
dir /mnt/root 755 0 0
dir /proc 755 0 0
dir /root 700 0 0
dir /sbin 755 0 0
dir /sys 755 0 0
dir /usr 755 0 0
dir /usr/lib64 755 0 0
dir /var 755 0 0
# busybox (compiled with USE="static")
file /bin/busybox /bin/busybox 755 0 0
# mdadm (compiled with USE="static")
file /sbin/mdadm /sbin/mdadm 755 0 0
# btrfs-progs
file /sbin/btrfs /sbin/btrfs 755 0 0
file /sbin/btrfs-debug-tree /sbin/btrfs-debug-tree 755 0 0
file /sbin/btrfs-find-root /sbin/btrfs-find-root 755 0 0
file /sbin/btrfs-image /sbin/btrfs-image 755 0 0
file /sbin/btrfs-map-logical /sbin/btrfs-map-logical 755 0 0
file /sbin/btrfs-show-super /sbin/btrfs-show-super 755 0 0
file /sbin/btrfs-zero-log /sbin/btrfs-zero-log 755 0 0
file /sbin/btrfsck /sbin/btrfsck 755 0 0
file /sbin/btrfstune /sbin/btrfstune 755 0 0
file /sbin/fsck.btrfs /sbin/fsck.btrfs 755 0 0
# btrfs-progs dependencies
file /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2 755 0 0
file /lib64/libblkid.so.1 /lib64/libblkid.so.1 755 0 0
file /lib64/libc.so.6 /lib64/libc.so.6 755 0 0
file /lib64/libpthread.so.0 /lib64/libpthread.so.0 755 0 0
file /lib64/libuuid.so.1 /lib64/libuuid.so.1 755 0 0
file /lib64/libz.so.1 /lib64/libz.so.1 755 0 0
file /usr/lib64/liblzo2.so.2 /usr/lib64/liblzo2.so.2 755 0 0
# init script
file /init /usr/src/initramfs/init 755 0 0
# config for md RAID
file /etc/mdadm.conf /usr/src/initramfs/mdadm.conf 644 0 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment