Arch Linux 是 UEFI 从具有 GPT 和三个分区的 USB 闪存驱动器启动:
- EFI(vfat 文件系统)
- root(btrfs 文件系统,由 ext4 转换而来)
- home(btrfs 文件系统,由 ext4 转换而来)
btrfs 分区没有子卷,并且位于单个磁盘(USB 闪存驱动器)上。这里没有使用LVM。
任务
试图创建一个最小initramfs通过删除 udev 和许多其他钩子。使用 mkinitcpio 优化启动也被用作灵感。
有效的mkinitcpio
钩子是:根据,自动侦测和修改配置文件。
Btrfs 钩子
btrfs 钩子未启用,因为mkinitcpio
钩子文档btrfs 挂钩列表:
在单个设备上使用 Btrfs 不需要此挂钩。
回归
- 我尝试删除 udev -> 启动错误
- 我尝试添加 btrfs 模块 -> 启动错误
- 我添加了 btrfs 钩子 -> 启动错误
- 将 root=PARTUUID= 更改为 root=UUID= 符号 -> 启动错误
- 添加参数 rootfstype=btrfs -> 启动错误
- rootdelay=0 -> 启动错误
- rootdelay=10 -> 启动错误
- 从紧急 shell 使用 /dev/sda2 挂载 -> ok
错误
只有插入 udev 或 systemd hooks 后系统才会 root 到 btrfs 根分区,否则会出现此错误:
ERROR: device 'PARTUUID=c2...c13' not found. Skipping fsck.
:: mounting 'PARTUUID=c2...c13' on real root
mount: can't find 'PARTUUID=c2...c13'
You are now being dropped into an emergency shell.
运行时初始化调试/日志输出
启用启动参数rd.debug
并rd.log
显示“premount”调用解析设备函数并返回一个空查找。
resolve_device PARTUUID=c2...c13
local major minor dev tag device=PARTUUID=c2...c13
blkid -lt PARTUUID=c2...c13 -o device
dev=
最后一个空的开发导致设备未找到错误。
initramfs挂载命令
mount_handler=default_mount_handler
...
# Mount root at /new_root
"$mount_handler" /new_root
来源:https://git.archlinux.org/mkinitcpio.git/tree/init
default_mount_handler() {
msg ":: mounting '$root' on real root"
mount ${rootfstype:+-t $rootfstype} -o ${rwopt:-ro}${rootflags:+,$rootflags} "$root" "$1"
来源:https://git.archlinux.org/mkinitcpio.git/tree/init_functions#n375
initramfs挂载版本
[rootfs ]# mount -V
mount from util-linux 2.29.2 (libmount 2.29.2: btrfs, assert, debug)
initramfs 内容
$ lsinitcpio -a /boot/initramfs-linux-tiny.img
==> Image: /boot/initramfs-linux-tiny.img
==> Created with mkinitcpio 23
==> Kernel: 4.10.3-1-ARCH
==> Size: 3.53 MiB
==> Compressed with: lz4 -l
-> Uncompressed size: 8.32 MiB (.424 ratio)
-> Estimated extraction time: 0.028s
==> Included modules:
ahci [explicit] hid-generic [explicit] raid6_pq usbcore
atkbd [explicit] i8042 [explicit] scsi_mod usbhid [explicit]
btrfs [explicit] libahci sd_mod [explicit] xhci-hcd
crc32c-intel [explicit] libata serio xhci-pci [explicit]
crc32c_generic libcrc32c serio_raw [explicit] xor
ehci-hcd libps2 uas [explicit]
ehci-pci [explicit] ohci-hcd usb-common
hid ohci-pci [explicit] usb-storage
==> Included binaries:
blkid busybox dosfsck fsck fsck.vfat kmod mount switch_root
紧急 shell 的blkid
命令列出了正确的(部分)UUID 值。使用 (PART)UUID 进行安装是否会因为没有而失败/dev/disk/
?
问题
在没有 udev 的情况下,启动到位于 USB 闪存驱动器上的非 raid 非子卷单驱动器根 btrfs 分区需要什么?
initramfs/init
PS 此错误可能是由 RACE 条件引起的,执行命令时 UUID/PARTUUID 尚不可用mount ... UUID=...
。
答案1
原因
在版本 23 中,mkinitcpioresolve_device() 函数仅被调用一次。当执行时驱动器标签尚未读取时,blkid
无法查找/dev/...
请求标签的内核驱动器 ( ) 名称。
解决方案
通过添加“without-udev”挂钩(如下所示),resolve_device 函数保持不变。尽管标准可用 mkinitcpio 功能可以覆盖 mount_handler 添加 run_hook用于轮询直到blkid
返回一个值,或者(超时)10 秒已经过去。因此,可以从 mkinitcpio 配置中删除“udev”挂钩。
笔记
- 该解决方案是在以下人员的帮助下创建的法尔科宁迪。
- 在早期启动阶段出现涉及 fsck 的错误消息。为了删除该消息,without-udev 挂钩已被重写为使用 a
run_hook
而不是.新的代码甚至更短。mount_handler
$ cat /usr/lib/initcpio/hooks/without-udev
#!/bin/ash
# Minimal initramfs files are created without udev.
# This hooks provides a polling disk mount replacement for udev.
# Udev hook can be removed, resulting in smaller initramfs files.
run_hook () {
local dev timeout sleepval device=$root
# if udev is running then exit
[ "$udevd_running" -eq 1 ] && return
# try for (timeout * sleepval =) 10 seconds to handle slow (USB) devices
timeout=1000
sleepval=0.01
case $device in
# label to resolve, when resolved the kernel block device also exists
UUID=*|LABEL=*|PARTUUID=*|PARTLABEL=*)
while [ $timeout -gt 0 ]; do
timeout=$((timeout - 1))
dev=$(blkid -lt "$device" -o device)
[ -n "$dev" ] && timeout=0 || sleep $sleepval
done
;;
# kernel named block device, poll for existence
/dev/*)
while [ $timeout -gt 0 ]; do
timeout=$((timeout -1))
if [ -b "$device" ]; then
dev=$device
timeout=0
else
sleep $sleepval
fi
done
;;
esac
}
# vim:set syntax=sh:
$ cat /usr/lib/initcpio/install/without-udev
#!/bin/bash
build() {
add_runscript
}
help() {
cat <<HELPEOF
This hook provides support for booting without the "udev" hook,
including support for UUID, LABEL, PARTUUID, PARTLABEL.
HELPEOF
}
# vim: set ft=sh ts=4 sw=4 et: