如何找到 debootstrap 映像的根设备名称

How to find the root device name of a debootstrap image

我正在使用 debootstrap (debootstrap --arch amd64 focal .) 创建一个 ubuntu 20.04 QEMU 映像。但是,当我尝试使用已编译的 Linux 内核启动它时,它无法启动:

[    0.678611] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
[    0.681639] Call Trace:
...
[    0.685135]  ret_from_fork+0x35/0x40
[    0.685712] Kernel Offset: disabled
[    0.686182] ---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0) ]---

我正在使用以下命令:

sudo qemu-system-x86_64 \
    -enable-kvm -cpu host -smp 2 -m 4096 -no-reboot -nographic \
    -drive id=root,media=disk,file=ubuntu2004.img \
    -net nic,macaddr=00:da:bc:de:00:13 -net tap,ifname=tap0,script=no \
    -kernel kernel/arch/x86/boot/bzImage \
    -append "root=/dev/sda1 console=ttyS0"

所以我猜测错误来自错误的根设备名称(/dev/sda1 在我的例子中)。有没有办法找到正确的根设备名称?


根据@Peter Maydell 的评论更新:

[    0.302200] VFS: Cannot open root device "sda1" or unknown-block(0,0): error -6
[    0.302413] Please append a correct "root=" boot option; here are the available partitions:
[    0.302824] fe00         4194304 vda 
[    0.302856]  driver: virtio_blk
[    0.303152] Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

其中 vda 应该是根设备名称。

这种“无法在未知块上挂载根文件系统”错误有几种可能的原因:

  • 你要求内核使用错误的设备作为rootfs(或者你没有指定,内置默认是错误的)
  • 您要求内核使用正确的设备作为 rootfs,但内核没有为其编译的设备驱动程序。(这可能包括更复杂的情况,例如“该设备是 PCI 设备并且内核没有编译 PCI 控制器驱动程序。")
  • 您要求内核使用正确的设备作为 rootfs,内核确实有它的驱动程序,但找不到硬件,可能是因为 QEMU 命令行不正确

找出问题所在的一个重要线索是查看内核日志中“内核崩溃”部分之前的部分。内核应该打印一个“可用分区”列表,这些分区是它有驱动程序的设备,并且存在。如果该列表包含一个看似合理的设备名称,如您的情况(其中“vda”列为“virtio_blk”驱动程序提供的)那么您现在知道根设备名称应该是什么,以及您需要的所有内容要做的是修复内核命令行,例如“root=vda”。请注意,此列表是可用分区的列表,因此如果您的磁盘映像有多个分区,它们应该在列表中显示为“vda1”、“vda2”等(在这种情况下,您的映像看起来像是一个文件系统,而不是具有多个分区的磁盘映像,因此列表中只有“vda”。)

如果内核的可用分区列表不包括任何看起来像您期望的磁盘的东西,那么要么是内核缺少驱动程序,要么是 QEMU 命令行没有提供该设备的选项.这有点难调试,但在内核启动日志的早期可能有有用的信息,内核在其中探测硬件——例如,当探测到 PCI 控制器时应该有日志记录。当然,您也可以仔细检查内核的配置文件,看看是否设置了正确的 CONFIG 选项。

如果您使用的是标准发行版内核,那么它​​们通常内置了所有常用设备,您的第一个检查应该是您的 QEMU 命令行。如果您从源代码构建了自己的内核,请检查您的配置,尤其是当您试图获得仅包含所需驱动程序的“最小”内核时。