Como inicializar no sistema de arquivos root btrfs com o mínimo de initramfs sem o gancho udev?

4

O Arch Linux é carregado pela UEFI a partir de uma unidade flash USB com GPT e três partições:

  1. EFI (sistema de arquivos vfat)
  2. root (o sistema de arquivos btrfs foi convertido do ext4)
  3. home (o sistema de arquivos btrfs foi convertido do ext4)

As partições btrfs não têm sub-volumes e estão em um único disco (a unidade de memória flash USB).

Tarefa

Tentando criar um mínimo de initramfs removendo o udev e muitos outros ganchos. O Otimizando o Bootup com o mkinitcpio também foi usado como inspiração.
Os ganchos mkinitcpio efetivos são: base , autodetectar e modconf .

Gancho do Btrf

O gancho btrfs não está ativado porque as listas mkinitcpio hooks documentation para o gancho btrfs:

This hook is not required for using Btrfs on a single device.

Regressão

  1. Eu tentei remover o udev - > erro de inicialização
  2. Eu tentei adicionar o módulo btrfs - > erro de inicialização
  3. Eu adicionei o gancho btrfs - > erro de inicialização
  4. Raiz alterada = PARTUUID = para root = UUID = notação - > erro de inicialização
  5. adicionando parâmetros rootfstype = btrfs - > erro de inicialização
  6. rootdelay = 0 - > erro de inicialização
  7. rootdelay = 10 - > erro de inicialização
  8. Montagem usando / dev / sda2 a partir do shell de emergência - > ok

Erro

Somente depois de inserir os ganchos udev ou systemd, o sistema entrará na partição raiz btrfs, caso contrário, este erro será exibido:

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.

Tempo de execução debug / log output

Ativar os parâmetros de inicialização rd.debug e rd.log mostra que "premount" chama o resolve_device função e que retorna uma pesquisa vazia.

resolve_device PARTUUID=c2...c13
local major minor dev tag device=PARTUUID=c2...c13
blkid -lt PARTUUID=c2...c13 -o device
dev=

O último dev vazio está causando o erro do dispositivo não encontrado.

comando de montagem initramfs

mount_handler=default_mount_handler
...
# Mount root at /new_root
"$mount_handler" /new_root

fonte: link

default_mount_handler() {
    msg ":: mounting '$root' on real root"
    mount ${rootfstype:+-t $rootfstype} -o ${rwopt:-ro}${rootflags:+,$rootflags} "$root" "$1"

fonte: link

versão de montagem do initramfs

[rootfs ]# mount -V
mount from util-linux 2.29.2 (libmount 2.29.2: btrfs, assert, debug)

conteúdos 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

O shell de emergência, seu comando blkid , lista o valor UUID correto (PART). A montagem usando o UUID (PART) poderia falhar porque não há /dev/disk/ ?

Pergunta

O que é necessário para inicializar em uma partição btrfs raiz de unidade única que não seja um subvolume localizada em uma unidade flash USB sem o udev?

PS Este erro pode ser causado por uma condição RACE, UUID / PARTUUID ainda não disponível quando initramfs/init executa o comando mount ... UUID=... .

    
por Pro Backup 19.03.2017 / 01:16

1 resposta

2

Causa

Na versão 23, a função mkinitcpio resolve_device () é chamada apenas uma vez. Quando, no momento da execução, os rótulos da unidade ainda não foram lidos, blkid não pode pesquisar nome da unidade do kernel ( /dev/... ) para o rótulo solicitado.

Solução

Adicionando o gancho "sem-udev", conforme listado abaixo, a função resolve_dispositivo é deixada intacta. Embora a funcionalidade padrão do mkinitcpio disponível para substituir o mount_handler adicione um run_hook é usada para pesquisar até que blkid retorne um valor ou (um tempo limite de) 10 segundos tenham passado. Assim, o gancho "udev" pode ser removido da configuração do mkinitcpio.

Notas

  • Esta solução foi criada com a ajuda de falconindy .
  • Houve uma mensagem de erro na fase inicial de inicialização envolvendo fsck. Para remover essa mensagem, o gancho sem udev foi reescrito para usar um run_hook em vez de um mount_handler . O código mais novo é ainda mais curto.
$ 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:
    
por 21.03.2017 / 21:00