udev 후크 없이 최소 initramfs를 사용하여 루트 btrfs 파일 시스템으로 부팅하는 방법은 무엇입니까?

udev 후크 없이 최소 initramfs를 사용하여 루트 btrfs 파일 시스템으로 부팅하는 방법은 무엇입니까?

Arch Linux는 GPT와 세 개의 파티션이 있는 USB 플래시 드라이브에서 UEFI 부팅이 가능합니다.

  1. EFI(vfat 파일 시스템)
  2. 루트(btrfs 파일 시스템, ext4에서 변환됨)
  3. 홈(btrfs 파일 시스템, ext4에서 변환됨)

btrfs 파티션에는 하위 볼륨이 없으며 단일 디스크(USB 플래시 드라이브)에 있습니다. 여기서는 LVM이 사용되지 않습니다.

만들려고 노력 중최소 initramfsudev 및 기타 여러 후크를 제거합니다.mkinitcpio를 사용하여 시작 최적화영감으로도 사용됩니다.
유효한 mkinitcpio후크는 다음과 같습니다.~에 따르면,자동 감지그리고구성 파일 수정.

BTRFS 후크

btrfs 후크가 활성화되지 않았습니다.mkinitcpio후크 문서화btrfs 후크 목록:

단일 장치에서 Btrfs를 사용하는 경우에는 이 후크가 필요하지 않습니다.

반품

  1. udev -> 시작 오류를 제거해 보았습니다.
  2. btrfs 모듈을 추가하려고 합니다 -> 시작 오류
  3. btrfs 후크를 추가했습니다 -> 시작 오류
  4. 루트=PARTUUID=를 루트=UUID= 기호로 변경 -> 시작 오류
  5. 매개변수 rootfstype=btrfs 추가 -> 시작 오류
  6. rootdelay=0 -> 시작 오류
  7. rootdelay=10 -> 시작 오류
  8. 비상 쉘에서 /dev/sda2를 사용하여 마운트 -> 확인

실수

udev 또는 systemd 후크를 삽입한 후에만 시스템 루트가 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"사전 마운트" 호출을 표시합니다.분석 장치함수를 실행하고 빈 검색을 반환합니다.

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

비상 셸의 blkid명령은 올바른(부분) UUID 값을 나열합니다. (PART)UUID가 없기 때문에 설치가 실패합니까 /dev/disk/?

질문

udev 없이 USB 플래시 드라이브에 있는 비 RAID 비 하위 볼륨 단일 드라이브 루트 btrfs 파티션으로 부팅하려면 무엇이 필요합니까?


initramfs/initPS 이 오류는 명령을 실행할 때 UUID/PARTUUID를 아직 사용할 수 없는 RACE 조건으로 인해 발생할 수 있습니다 mount ... UUID=....

답변1

이유

버전 23에서는mkinitcpioresolve_device() 함수한 번만 호출되었습니다. 실행 시 아직 드라이브 라벨을 읽지 않은 경우blkid/dev/...요청한 레이블에 대한 커널 드라이버( ) 이름을 찾을 수 없습니다 .

해결책

"without-udev" 후크(아래 표시됨)를 추가하면solve_device 기능이 변경되지 않은 상태로 유지됩니다. 사용 가능한 표준 mkinitcpio 함수는 mount_handler를 재정의 할 수 있지만 run_hook 추가blkid값이 반환될 때까지 또는 (시간 초과) 10초가 경과할 때까지 폴링하는 데 사용됩니다 . 따라서 mkinitcpio 구성에서 "udev" 후크를 제거할 수 있습니다.

노트

  • 이 솔루션은 다음의 도움으로 만들어졌습니다.팔코닌디.
  • fsck와 관련된 오류 메시지는 초기 부팅 단계에서 나타납니다. 해당 메시지를 제거하기 위해 udev 없이 후크를 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:

관련 정보