如何在沒有 udev 掛鉤的情況下使用最少的 initramfs 引導到根 btrfs 文件系統?
Arch Linux 是從帶有 GPT 和三個分區的 USB 快閃記憶體驅動器啟動的 UEFI:
- EFI(vfat 文件系統)
- root(btrfs 文件系統,由 ext4 轉換而來)
- home(btrfs 文件系統,由 ext4 轉換而來)
btrfs 分區沒有子卷並且位於單個磁碟(USB 快閃記憶體驅動器)上。此處未使用 LVM。
任務
嘗試通過刪除 udev 和許多其他鉤子來創建最小的 initramfs 。使用 mkinitcpio 優化啟動也被用作靈感。
有效的
mkinitcpio
鉤子是:base、autodetect和modconf。Btrfs 鉤子
btrfs 鉤子未啟用,因為 btrfs 鉤子的
mkinitcpio
鉤子文件列表:在單個設備上使用 Btrfs 不需要此掛鉤。
回歸
- 我試圖刪除 udev -> 啟動錯誤
- 我試圖添加 btrfs 模組 -> 啟動錯誤
- 我添加了 btrfs 掛鉤 -> 啟動錯誤
- 將 root=PARTUUID= 更改為 root=UUID= 表示法 -> 引導錯誤
- 添加參數 rootfstype=btrfs -> 啟動錯誤
- rootdelay=0 -> 啟動錯誤
- rootdelay=10 -> 啟動錯誤
- 從緊急外殼使用 /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函式並返回空查找。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
命令列出了正確的 (PART)UUID 值。使用 (PART)UUID 安裝會失敗,因為沒有/dev/disk/
?問題
在沒有 udev 的情況下引導到位於 USB 快閃記憶體驅動器上的非 RAID 非子卷單驅動器根 btrfs 分區需要什麼?
initramfs/init
PS 此錯誤可能是由 RACE 條件引起的,執行mount ... UUID=...
命令時 UUID/PARTUUID 尚不可用。
原因
在版本 23 中,mkinitcpio resolve_device() 函式只被呼叫一次。在執行時尚未讀取驅動器標籤時,無法為請求的標籤
blkid
查找核心驅動器 ( ) 名稱。/dev/...
解決方案
通過添加“without-udev”鉤子,如下所示,resolve_device 函式保持不變。儘管覆蓋 mount_handler 的標準可用 mkinitcpio 功能添加了一個 run_hook用於輪詢,直到
blkid
返回一個值,或者(超時)10 秒過去。因此“udev”鉤子可以從 mkinitcpio 配置中刪除。筆記
- *這個解決方案是在falconindy*的幫助下創建的。
- 在涉及 fsck 的早期引導階段出現錯誤消息。要刪除該消息,無 udev 掛鉤已被重寫為使用 a
run_hook
而不是 amount_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: