使用 Qemu(无 initrd)的 NFS /sbin/init

使用 Qemu(无 initrd)的 NFS /sbin/init

TL;DR:我尝试告诉 Qemu 机器上的内核从 NFS 服务器启动 /sbin/init,但出现内核恐慌(未同步:VFS:无法在未知块 (2,0) 上挂载根文件系统)。我为此使用了以下命令:

kvm \
  -netdev tap,id=totou,ifname=tap1 -device e1000,netdev=totou,mac=52:54:00:12:34:57 \
  -kernel /tmp/bzImage \
  -append "root=/dev/nfs rw nfsroot=10.0.2.3:/serverNFS ip=dhcp" \
  -m 6G

更详细的解释:

我编译了一个内核(linux-4.8.6):

make defconfig
make -j8
cp arch/x86/boot/bzImage /tmp

我还有一个mydisk.qcow2由创建的磁盘qemu-img,它有一个 ext4 分区,其中只有 /sbin/init。其中 init 是结果gcc -static -o init init.c,而 init.c 是:

#include <stdio.h>
#include <unistd.h>
int main()
{
  printf("Hello init\n");
  while(1)
    sleep(100);
  return 0;
}

然后我运行 qemu (kvm):

kvm \
  -kernel /tmp/bzImage \
  -append "root=/dev/sda1 rw" \
  -hda mydisk.qcow2 \
  -m 6G

一切按预期工作:内核启动并启动init。



然后我在另一台虚拟机上添加了 dhcp 和 nfs 服务器:

qemu-DHCP-and-NFS-server ------- (tap0)[ 主机桥 (br0) ](tap1) --------- qemu 客户端

  1. 主机桥 br0 包含两个接口:tap0 连接到 qemu 服务器,tap1 连接到客户端。桥接 ip 为 10.0.2.2/24,mac=5e:50:67:79:96:f0 qemu-DHCP-and-NFS-server ip 为 10.0.2.3/24,mac=52:54:00:12:34:56

  2. 在 qemu-DHCP-and-NFS-server 上,init二进制文件位于 /serverNFS/sbin/init 中,且 /etc/export 如下所示:

    /serverNFS      *(rw,no_root_squash,async,insecure)
    

只是为了测试,我在 qemu 客户端上运行了 ubuntu live cd:

  kvm \
  -netdev tap,id=totou,ifname=tap1 -device e1000,netdev=totou,mac=52:54:00:12:34:57 \
  -cdrom ubuntu-16.04-desktop-amd64.iso \
  -m 6G

并尝试挂载 nfs 分区:

# mkdir /tmp/nfs
# mount.nfs 10.0.2.3:/serverNFS /tmp/nfs
# ls /tmp/nfs/sbin
init

好的,DHCP 和 NFS 可以工作了!


现在我停止 qemu 客户端并使用以下命令重新启动它:

kvm \
  -netdev tap,id=totou,ifname=tap1 -device e1000,netdev=totou,mac=52:54:00:12:34:57 \
  -kernel /tmp/bzImage \
  -append "root=/dev/nfs rw nfsroot=10.0.2.3:/serverNFS ip=dhcp" \
  -m 6G

在启动时,内核启动,我可以看到如下内容:

...
Sending DHCP requests ;, OK
IP-Config : Got DHCP answer from 10.0.2.3, my address is 10.0.2.19
IP-Config : Complete:
    device=eth0,hwaddr=52:54:00:12:34:57, ipaddr=10.0.2.19, mask=255.255.255.0, gw=10.0.2.2
    host=10.0.2.19, domain=, nis-domain=(none)
    bootserver=10.0.2.3, rootserver=10.0.2.3, rootpath=/serverNFS

...

但最后我出现了内核恐慌——“未同步:VFS:无法挂载根文件系统

我的 nfs 服务器似乎有问题,但我找不到原因。您有什么想法吗?

再补充一点:我不想添加“-initrd”(或者解释为什么它是绝对必要的)。内核配置中的文件系统 -> 网络文件系统中的所有内容都被选中(不是作为模块)。此外,CONFIG_ROOT_NFS、CONFIG_IP_PNP、CONFIG_IP_PNP_BOOTP、CONFIG_IP_PNP_RARP、CONFIG_IP_PNP_DHCP 都被选中。

如果您需要其他精度,请告诉我。

答案1

这个问题实际上很容易解决,我很惭愧在发帖之前没有想到这一点(很抱歉!)

wireshark 跟踪让我知道内核正在使用 NFSv2(即使内核中编译了 NFSv3 和 NFSv4)。(它使用 NFS 和 RPC over UDP)但我的服务器只接受 nfsv3 或 nfsv4。因此,解决方案是接受 nfsv2:

需要支持使用 NFSv2(例如 U-Boot)的客户端的用户应在 /etc/sysconfig/nfs 中设置 RPCNFSDARGS="-V 2"。(来自https://wiki.archlinux.org/index.php/NFS#NFSv2_compatibility

顺便说一句,如果你知道如何强制使用 NFSv3 或 NFSv4,请告诉我

相关内容