症状是这样的。开机默认内核进不去,屏幕报 KERNEL PANIC,提示 VFS: Unable to mount root fs on unknown-block(0,0),逐帧看录屏还能在底部找到 VFS: Cannot open root device "/dev/nvme0n1p5" error -6。旧内核能正常进桌面,新内核和它的 recovery mode 都是同样的 panic。

不用担心数据, 真正的原因不是硬盘坏了,也不是内核本身有问题。根子配置了自动升级, 一个第三方 DKMS 模块在新内核上编译失败,导致新内核的安装脚本中途报错退出,initramfs 没能生成。没有 initramfs,内核启动时加载不了 NVMe 驱动,找不到根分区,于是 panic。我这台机器上编译失败的模块是 evdi,也就是 DisplayLink 外接屏驱动。

快速修复

思路很简单:先用能进的旧内核开机,把默认启动固定到旧内核让电脑立刻恢复可用,再把坏掉的新内核删掉,最后关掉会再次偷装内核的自动升级。全程不需要去救那个坏内核。

第一步,开机在 GRUB 菜单里选能正常启动的旧内核进桌面,打开终端。

第二步,把默认启动项固定到旧内核。编辑配置文件:

sudo vim /etc/default/grub

把 GRUB_DEFAULT=0 那一行改成你的旧内核菜单项,名字要和 grub.cfg 里完全一致:

GRUB_DEFAULT="Advanced options for Ubuntu>Ubuntu, with Linux 6.17.0-40-generic"

保存退出后更新 GRUB:

sudo update-grub

第三步,删掉出问题的新内核。删之前先用 uname -r 确认当前跑的是旧内核,不能删正在运行的内核。

uname -r    # 必须显示旧内核, 比如 6.17.0-40-generic
sudo apt remove --purge 'linux-image-7.0.0-28-generic' 'linux-headers-7.0.0-28-generic'
sudo apt autoremove --purge

如果删除过程仍被 DKMS 模块编译报错卡住,先把那个模块从 dkms 树里移除,再重试删除:

sudo rm -f /var/crash/evdi-dkms.0.crash
sudo dkms remove evdi/1.14.2+dfsg --all

这里的 evdi 和版本号换成你自己 make.log 里报错的那个模块。

第四步,关掉无人值守的自动升级,避免以后又在后台偷装内核。

sudo dpkg-reconfigure unattended-upgrades

弹窗选 No,然后确认 /etc/apt/apt.conf.d/20auto-upgrades 里两行都是 "0"。之后更新改为自己手动执行 sudo apt update 和 sudo apt upgrade,节奏完全由你掌握。

做完这四步,重启就会直接进旧内核,坏内核已经删除,也不会再自动装回来。

怎么快速判断自己是不是同一类问题

进旧内核后跑一条命令,检查出问题内核的 initramfs 里有没有 NVMe 驱动:

lsinitramfs /boot/initrd.img-7.0.0-28-generic | grep -i nvme

如果没有任何输出,说明这个内核的 initramfs 缺 NVMe 驱动或者压根没生成好,基本可以锁定是本文这类问题。再看一眼 sudo apt install -f 是否提示有包没配置完,以及是否伴随 DKMS 编译报错,就能坐实。

完整分析过程

现场:panic 到底在说什么

初始报错只有 VFS: Unable to mount root fs on unknown-block(0,0) 一句,信息不够。把开机过程录下来逐帧看,才在最底部抓到真正有用的两行:

/dev/root: Can't open blockdev
VFS: Cannot open root device "/dev/nvme0n1p5" or unknown-block(0,0): error -6

问题就从"根文件系统坏了"收窄到了"内核启动时打不开 NVMe 设备"。error -6 是 ENXIO,也就是 No such device,意思是内核在这个阶段根本看不见那块 NVMe 盘。典型原因就是 initramfs 里缺 NVMe 驱动,或者 initramfs 本身没生成好。旧内核能进,正好说明它的 initramfs 是完整的,问题只出在新内核身上。

排除低级原因

进旧内核桌面后先确认基本环境:

findmnt /            # 根分区确实是 /dev/nvme0n1p5, ext4
df -h /boot          # /boot 在根分区内, 还有空闲, 排除空间不足
apt list --installed | grep linux-image

内核列表显示新旧两个内核都来自官方源,新内核是通过 HWE 元包 linux-image-generic-hwe-24.04 升上来的,属于正常的官方升级,不是野内核。

关键线索:apt 状态是半完成的

清理时 apt 提示 4 not fully installed or removed,尝试配置新内核时抛出一大段错误,核心是这几行:

dkms: running auto installation service for kernel 7.0.0-28-generic
Building module ... (bad exit status: 2)
dkms autoinstall on 7.0.0-28-generic/x86_64 failed for evdi
dpkg: error processing package linux-image-7.0.0-28-generic (--configure):
 installed ... post-installation script subprocess returned error exit status 11

因果链到这里就清楚了。evdi 这个 DKMS 模块在新内核上编译失败,内核包的安装脚本因此返回非零,内核配置阶段没跑完,生成 initramfs 的那一步根本没执行。这才是 panic 的源头,缺 NVMe 驱动只是表现。

顺带还有个小障碍,上一次崩溃残留的 crash 文件挡着后续操作,需要先删掉:

ERROR: Cannot create report: [Errno 17] File exists: '/var/crash/evdi-dkms.0.crash'

evdi 为什么编不过

查它的构建日志 /var/lib/dkms/evdi/版本/build/make.log,报错很直白:

error: 'struct drm_device' has no member named 'struct_mutex'
error: implicit declaration of function 'DRM_DEBUG_PRIME'

这是内核图形子系统 DRM 的接口在新版本里变了,struct_mutex 这类旧成员和宏被移除,而手头这版 evdi 源码还在用旧接口,在新内核上必然编不过。这类问题很有共性,NVIDIA、VirtualBox、DisplayLink 这些第三方 DKMS 模块在内核大版本升级时都可能踩到。

溯源:确认是自动升级触发的

查 dpkg 日志坐实时间线:

grep -iE "7.0.0-28|evdi|dkms" /var/log/dpkg.log /var/log/dpkg.log.1

可以看到新内核是在清早无人操作的时间点由 HWE 元包自动升级装入的,之后连续几天反复出现 half-configured 却始终到不了干净的 installed,正是每次 apt 想收尾都被 evdi 卡住的痕迹。这解释了那种什么都没干、突然就坏了的感觉。升级在后台发生,evdi 让它没能收尾,直到下一次重启默认进新内核才暴露成 panic。

一句话总结

VFS: Unable to mount root fs 加上 NVMe error -6 这类开机 panic,当旧内核能进、新内核不能进时,优先怀疑第三方 DKMS 模块编译失败导致新内核 initramfs 没生成。用旧内核开机后,把默认启动固定到旧内核,删掉坏内核,再关掉自动升级,问题就解决了。