WARNING: You might be first to follow this guidecorrections, comments and improvements welcome.
DISCLAIMER: You follow this guide at your own risk. If your system breaks as a result, you get to keep both pieces.
Allow plenty of time - this is a major change. For help, post to this thread. >=udev-182 is only in ~ARCH at the time of writing.
If you run ~ARCH you are supposed to know what you are doing.
Credits The Gentoo Wiki which provided much of the insperation and gentoo-wiki.com which I have used for static root on lvm over raid for many years.
Aim of this guide
To keep you in control of the boot process on your system.
You need this guide if you have a separate /usr or /var partition and want to understand and have control of the boot process on your system after the upgrade to >=udev-182
The use of raid and lvm is covered as I had to make that work but encrypted filesystems are not as I have no way to test.
An initrd is required but you build it with the aid of a kernel provided script. Neither dracut nor genkernel are required, well if they were needed you would not
be in control would you?
The idea is to have a system that when it fails to boot, you can fix it yourself. Its likely that during the executopn of this procedure you will get to practice
that, so have a bootable USB stick, or CDROM handy. You will not be able to boot into an old kernel.
Prerequisties
A Gentoo system with a separate /usr and or /var partition, optionally, with everything except /boot on lvm on raid. >=udev-182 should be in your package.mask, or
you have seen emerge wanting to upgrade to it. If you already have udev-182, you box won't boot again until you make arrangeents to mount /usr and /var before udev
is started.
Overview
Preparation - you can do this now and test it. These steps are required before you reboot useing you new initrd but they can be tested and debugged before you
make the leap to >=udev-182
Initrd preparation
This can be done but not tested until your have >=udev-182 installed.
The leap to >=udev-182
Going back after this stage is pointless, long term the only way is on.
The reboot
If it doesn't work first time, fetch the boot media you hoped you would not need, get into your chroot and fix it.
Preparation
As the initrd will contain /sbin/mount change /etc/fstab to mount everything by UUID. This is a robustness improvement you get for free. You cannot yet use a UUID
in grub.conf to mount root. That's covered later, once the system boots using the initrd.
To disciver your UUIDs run the command blkid
Code: Select all
$ sudo blkid
Password:
/dev/sda1: UUID="9392926d-6408-6e7a-8663-82834138a597" TYPE="linux_raid_member"
/dev/sda2: UUID="b6633d8e-41ef-4485-9bbe-c4c2d69f4e8c" TYPE="swap"
/dev/sda5: UUID="5e3cadd4-cfd2-665d-9690-1ac76d8f5a5d" TYPE="linux_raid_member"
/dev/sda6: UUID="9657e667-5b60-f6a3-0391-65e6dcf662fa" TYPE="linux_raid_member"
[other drives omitted]
/dev/md125: UUID="741183c2-1392-4022-a1d3-d0af8ba4a2a8" TYPE="ext2"
/dev/md126: UUID="ff5730d5-c28d-4276-b300-5b0b0fc60300" TYPE="ext4"
/dev/md127: UUID="7b2KgY-NHef-kuNk-WBAp-VnLa-h03A-b4ehGy" TYPE="LVM2_member"
/dev/mapper/vg-usr: UUID="fc23601b-e2af-443f-959e-50148154a91b" TYPE="ext4"
/dev/mapper/vg-local: UUID="7e0d0ae4-2c57-44e9-995f-5723ab0670b3" TYPE="ext4"
/dev/mapper/vg-tmp: UUID="1ff5e3b5-c2d8-41a6-b172-e1ede8fe22ff" TYPE="ext2"
/dev/mapper/vg-var: UUID="57b34894-f80d-47ab-a522-46fb6e1a19b8" TYPE="ext4"
/dev/mapper/vg-vmware: UUID="e41a94cc-0817-449f-8ac8-f3055d33879c" TYPE="ext4"
/dev/mapper/vg-opt: UUID="7f0fad34-6130-42d8-8246-033de9717005" TYPE="ext4"
/dev/mapper/vg-distfiles: UUID="54b46458-d411-4ea8-8920-4c5fcdb56a81" TYPE="ext4"
/dev/mapper/vg-packages: UUID="59c06fd1-8471-4efb-b055-8f1cfb39645f" TYPE="ext4"
/dev/mapper/vg-portage: UUID="8675cb9c-4251-489f-8e9b-0244ca80176c" TYPE="ext2"
/dev/mapper/vg-home: UUID="8d5d5691-ceb7-4e58-bed3-28803cb88bfe" TYPE="ext4"
/dev/sde1: SEC_TYPE="msdos" UUID="FC30-3DA9" TYPE="vfat"Code: Select all
/etc/fstabCode: Select all
# <fs> <mountpoint> <type> <opts> <dump/pass>
# NOTE: If your BOOT partition is ReiserFS, add the notail option to opts.
#/dev/md125 /boot ext2 noauto,noatime 1 2
UUID=741183c2-1392-4022-a1d3-d0af8ba4a2a8 /boot ext2 noauto,noatime 1 2
UUID=8d5d5691-ceb7-4e58-bed3-28803cb88bfe /home ext4 noatime 1 2
UUID=7f0fad34-6130-42d8-8246-033de9717005 /opt ext4 noatime 1 2Save the changes and test with
Code: Select all
mount -aThe initrd requires some packages to be built with the static USE flag. Edit
Code: Select all
/etc/portage/package.useCode: Select all
# static bits and pieces for an initrd
sys-fs/lvm2 static
sys-fs/mdadm static
sys-apps/busybox staticbusybox will provide the shell in the initrd.
Code: Select all
emerge -uDNav world>=udev-182 depends on a kernel option
Code: Select all
| [*] Maintain a devtmpfs filesystem to mount at /dev | |
| | [*] Automount devtmpfs at /dev, after the kernel mounted the rootfsIf you are using kernel raid auto assembly, turn it off
Code: Select all
[ ] Autodetect RAID arrays during kernel boot Rebuild and reinstall your kernel. If you need to reboot, raid autoassembly users cannot reboot into this kernel without following the rest of this guide.
At the outset, I mentioned a kernel provided script. The kernel sources provide the gen_init_cpio and gen_initramfs_list.sh utilities. The gen_init_cpio utility
does not come prepackaged and needs to be built.
Code: Select all
cd /usr/src/linux/usr
make gen_init_cpioCode: Select all
chmod +x gen_init_cpio
chmod +x ../scripts/gen_initramfs_list.shWith the aid of the kernel scripts, there are two files to prepare. The init script itself and a list of files to be included in the initrd.
Old habits die hard an I like to prepare the initrd in /root/initrd
The /root/initrd/initramfs_list contains
Code: Select all
# directory structure
dir /proc 755 0 0
dir /usr 755 0 0
dir /bin 755 0 0
dir /sys 755 0 0
dir /var 755 0 0
#dir /lib 755 0 0
dir /lib64 755 0 0
dir /sbin 755 0 0
dir /mnt 755 0 0
dir /mnt/root 755 0 0
dir /etc 755 0 0
dir /root 700 0 0
dir /dev 755 0 0
# busybox
file /bin/busybox /bin/busybox 755 0 0
# for raid on lvm
file /sbin/mdadm /sbin/mdadm 755 0 0
file /sbin/lvm.static /sbin/lvm.static 755 0 0
# libraries required by /sbin/fsck.ext4 and /sbin/fsck
slink /lib /lib64 777 0 0
file /lib64/ld-linux-x86-64.so.2 /lib64/ld-linux-x86-64.so.2 755 0 0
file /lib64/libext2fs.so.2 /lib64/libext2fs.so.2 755 0 0
file /lib64/libcom_err.so.2 /lib64/libcom_err.so.2 755 0 0
file /lib64/libpthread.so.0 /lib64/libpthread.so.0 755 0 0
file /lib64/libblkid.so.1 /lib64/libblkid.so.1 755 0 0
file /lib64/libuuid.so.1 /lib64/libuuid.so.1 755 0 0
file /lib64/libe2p.so.2 /lib64/libe2p.so.2 755 0 0
file /lib64/libc.so.6 /lib64/libc.so.6 755 0 0
file /sbin/fsck /sbin/fsck 755 0 0
file /sbin/fsck.ext4 /sbin/fsck.ext4 755 0 0
# our init script
file /init /root/initrd/init 755 0 0Code: Select all
# for raid on lvm
file /sbin/mdadm /sbin/mdadm 755 0 0
file /sbin/lvm.static /sbin/lvm.static 755 0 0Use
Code: Select all
ldd <your_fsck_helper>32 bit installs do not have /lib64. See the gentoo wiki for a 32 bit initramfs_list.
If you made your initrd elsewhere, update
Code: Select all
file /init /root/initrd/init 755 0 0Code: Select all
#!/bin/busybox sh
rescue_shell() {
echo "$@"
echo "Something went wrong. Dropping you to a shell."
/bin/busybox --install -s
exec /bin/sh
}
# allow the use of UUIDs or filesystem lables
uuidlabel_root() {
for cmd in $(cat /proc/cmdline) ; do
case $cmd in
root=*)
type=$(echo $cmd | cut -d= -f2)
echo "Mounting rootfs"
if [ $type == "LABEL" ] || [ $type == "UUID" ] ; then
uuid=$(echo $cmd | cut -d= -f3)
mount -o ro $(findfs "$type"="$uuid") /mnt/root
else
mount -o ro $(echo $cmd | cut -d= -f2) /mnt/root
fi
;;
esac
done
}
check_filesystem() {
# most of code coming from /etc/init.d/fsck
local fsck_opts= check_extra= RC_UNAME=$(uname -s)
# FIXME : get_bootparam forcefsck
if [ -e /forcefsck ]; then
fsck_opts="$fsck_opts -f"
check_extra="(check forced)"
fi
echo "Checking local filesystem $check_extra : $1"
if [ "$RC_UNAME" = Linux ]; then
fsck_opts="$fsck_opts -C0 -T"
fi
trap : INT QUIT
# using our own fsck, not the builtin one from busybox
/sbin/fsck -p $fsck_opts $1
ret_val=$?
case $ret_val in
0) return 0;;
1) echo "Filesystem repaired"; return 0;;
2|3) if [ "$RC_UNAME" = Linux ]; then
echo "Filesystem repaired, but reboot needed"
reboot -f
else
rescue_shell "Filesystem still have errors; manual fsck required"
fi;;
4) if [ "$RC_UNAME" = Linux ]; then
rescue_shell "Fileystem errors left uncorrected, aborting"
else
echo "Filesystem repaired, but reboot needed"
reboot
fi;;
8) echo "Operational error"; return 0;;
16) echo "Use or Syntax Error"; return 16;;
32) echo "fsck interrupted";;
127) echo "Shared Library Error"; sleep 20; return 0;;
*) echo $ret_val; echo "Some random fsck error - continuing anyway"; sleep 20; return 0;;
esac
# rescue_shell can't find tty so its broken
rescue_shell
}
# start for real here
# temporarily mount proc and sys
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 the screen
###clear
# assemble the raid set(s) - they got renumbered from md1, md5 and md6
# /boot
/sbin/mdadm --assemble /dev/md125 --uuid=d678d02e-28ab-84e0-c44c-77eb7ee19756
# don't care if /boot fails to assemble
# / (root) I wimped out of root on lvm for this box
/sbin/mdadm --assemble /dev/md126 --uuid=ad5fe0cb-775d-38b4-7169-e221fc96089f || rescue_shell
# if root won't assemble, we are stuck
# LVM for everything else
/sbin/mdadm --assemble /dev/md127 --uuid=52be4797:edab2349:eb21497e:52035eaa || rescue_shell
# and if the LVM space won't assemble there is no /usr or /var so we are really in a mess
# TODO could auto cope with degraded raid operation
# lvm runs as whatever its called as and we need vgchange
ln -s /sbin/lvm.static /sbin/vgchange
# start the vg volume group - we only have one volume group
/sbin/vgchange -ay vg || rescue_shell
# if this failed we have no /usr or /var
# get here with raid sets assembled and logical volumes available
# mounting rootfs on /mnt/root
uuidlabel_root || rescue_shell "Error with uuidlabel_root"
# space separated list of mountpoints that ...
mountpoints="/usr /var"
# ... we want to find in /etc/fstab ...
ln -s /mnt/root/etc/fstab /etc/fstab
# ... to check filesystems and mount our devices.
for m in $mountpoints ; do
#echo $m
check_filesystem $m
echo "Mounting $m"
# mount the device and ...
mount $m || rescue_shell "Error while mounting $m"
# ... move the tree to its final location
mount --move $m "/mnt/root"$m || rescue_shell "Error while moving $m"
done
echo "All done. Switching to real root."
# clean up. The init process will remount proc sys and dev later
umount /proc
umount /sys
umount /dev
# switch to the real root and execute init
exec switch_root /mnt/root /sbin/init
Remove the mdadm and lvm items from the init script if you don't use mdadm or lvm
Read the comments in the init file - you may need to make other adjustments.
Notice that if you make a mess of your included libraries, there is a 20 second pause then fsck returns as if it had worked but without doing anything.
This avoids the need to get into your chroot to fix your initrd, provided everything else works. Fix it. Mounting unchecked filesystems is ok for debugging but not
reccomenred.
Mount /boot, so the script gen_initramfs_list.sh can install the initrd there.
Run /usr/src/linux/scripts/gen_initramfs_list.sh -o /boot/initrd.cpio.gz /root/initrd/initramfs_list
Fix grub.conf. Mount root using the UUID of the root filesystem and add in the initrd line.
Code: Select all
#3.3.1-gentoo
title=Kernel 3.3.1-gentoo (hd0)
root (hd0,0)
kernel (hd0,0)/3.3.1-gentoo root=UUID=ff5730d5-c28d-4276-b300-5b0b0fc60300 vga=0x317 video=vesafb:mtrr:3,ywrap
initrd /boot/initrd.cpio.gz
title=Kernel 3.3.1-gentoo (hd1)
root (hd1,0)
kernel (hd1,0)/3.3.1-gentoo root=/dev/md126
initrd /boot/initrd.cpio.gzUpdate udev and anything else that is manually masked due to udev. Check your /etc/portage/package.mask
be sure you have >=openrc-0.9.9.3
run
Code: Select all
etc-updateTODO: Put all the files needed in the initrd in a filesystem in /root/initrd so they don't get messed up by random system updates.
TODO: Done - Use UUIDs in the mdadm --assemble commands post updated above but initscript examples copy/pasted from a second box.
UUIDs are unique, so readers need to use their own anyay. Not the the UUIDS here are the UUIDS foing using
Code: Select all
mdadm -E <componet device>TODO: Test with a static /dev in the initrd and DEVTMPFS off in the kernel. If that works, this becomes a complex static initrd that can be hand rolled with cpio.
--- edit 1 ---
Well that should have booted but not cleanly. The filesystems that the initrd now checks and mounts the normal init system tryes to check and mount. Edit /etc/fstab to stop that.
Code: Select all
UUID=57b34894-f80d-47ab-a522-46fb6e1a19b8 /var ext4 noatime,noauto 1 0
UUID=fc23601b-e2af-443f-959e-50148154a91b /usr ext4 noatime,noauto 1 0The pass number, thats th final field on the line needs to be set to zero, which means don't check this filesystem.
--- edit 2 ---
Init script updated to use UUIDs in mdadm assemble commands




