PVE 踩坑:ext4_journal_check_start:84 报错排查
PVE 踩坑:ext4_journal_check_start:84: Detected aborted journal
这事儿前后折腾了快两天。
表面上看,是 EXT4 崩了,NVMe 好像也坏了。但最后发现,硬盘啥事没有,锅全在 PCIe 直通配置上。
简单说就是:PCIe 地址变了,但虚拟机配置没改,结果 PVE 启动 VM 时把设备指错了,顺手把宿主机的系统盘给干趴下了。
一开始,还以为是硬盘坏了
PVE 启动没多久就开始报:
1 | EXT4-fs error (device dm-1): ext4_journal_check_start:84: Detected aborted journal |
第一反应就是系统盘文件系统坏了。
于是进 SystemRescue,激活 LVM:
1 | vgchange -ay |
跑 e2fsck:
1 | e2fsck -f -y /dev/pve/root |
确实扫出点东西:
1 | Free blocks count wrong |
修完以后顺手把 journal 也重建了:
1 | tune2fs -O ^has_journal /dev/pve/root |
这时候一切正常,重启,以为搞定了。
结果 PVE 起来大概 30 秒,又炸了,这次是:
1 | EXT4-fs error (device dm-1) in ext4_reserve_inode_write: IO failure |
不是 journal 的问题了,是 I/O 直接报错。
开始怀疑是不是 NVMe 真出了物理毛病。
但最懵的是:Live 系统里一点事没有
再次进 SystemRescue,e2fsck 能正常跑完,手动写 1GB 文件也完全没问题,一点卡顿都没有。
但只要一启动 PVE,稳定 30 秒左右,系统盘就掉。
这时候其实已经有个很明显的信号了:
如果硬盘真坏了,为什么 Live 系统里随便写都没事,偏偏只有 PVE 跑起来才出事?
而且这个时间点非常固定,像是某个任务触发的,不是随机故障。
真正让人警觉的是:连 /usr/bin/mount 都读不出来了
又一次进入 read-only 状态后,想手动 remount:
1 | mount -o remount,rw / |
结果返回的不是”权限不够”或者”无法 remount”,而是:
1 | -bash: /usr/bin/mount: Input/output error |
这就不是文件系统层的问题了,这是 块设备层已经读不出数据了。
连 mount 这个二进制文件都加载不出来,说明系统盘在 I/O 层面已经没法正常工作了。
这时候才意识到,EXT4 报的那些 journal aborted、read-only,全是被牵连的,不是根因。
最后查出来的东西,谁都没想到
翻了一下 PVE 的虚拟机配置:
1 | grep -R "hostpci" /etc/pve/qemu-server/ |
发现有一台 VM 的配置里有:
1 | hostpci0: 0000:xx:xx.x |
拿着这个地址去对了一下当前设备:
1 | lspci -Dnn |
结果发现,这个 BDF 地址已经不是当年直通的那块设备了。
硬件动过之后,PCIe 枚举重新分配了地址。原来那个地址,现在指向的是:
ASM1042A USB 3.0 控制器
而 VM 还保留着旧的配置,PVE 不知道”想直通的是原来的那块卡”,它只知道”把 xx:xx.x 这个地址交给虚拟机”。
于是每次 VM 一启动,PVE 就把这个 USB 控制器从宿主机剥离,交给 VFIO。
但为啥直通个 USB 会搞死 NVMe?
这个最反直觉。
ASM1042A 本身跟 NVMe 八竿子打不着。但问题不在设备类型,而在 IOMMU Group 的隔离关系。
查了一下当时的 IOMMU Group:
1 | for d in /sys/kernel/iommu_groups/*/devices/*; do |
发现这个 USB 控制器和系统 NVMe 处在同一个 IOMMU Group 里,或者至少存在某种 PCIe 拓扑上的互相影响关系。
VFIO 在准备直通的时候,会把整个 group 里的设备都从宿主机驱动解绑。结果就是:
1 | VM autostart |
所以整个链条其实是:
地址变了 → 直通错了设备 → 影响了系统盘的 PCIe 通路 → NVMe I/O 中断 → EXT4 崩溃
为什么绕了这么大一圈?
因为所有报错都太像硬盘故障了:
EXT4-fs errorDetected aborted journalIO failureRemounting filesystem read-only/usr/bin/mount: Input/output error
换谁第一反应都是”盘坏了”。
真正能跳出这个思维定势的,其实是三个现象:
① Live 系统里完全正常
说明硬件本身大概率没坏。
② 故障时间非常固定,大约 30 秒
像是某个服务启动后触发的,不是随机崩溃。
③ 故障附近能看到 PVE 的 task 日志
说明是人为操作触发的,不是硬盘自己坏的。
如果一开始就做这个最简单的测试:
1 | systemctl disable --now 所有 VM 的 autostart |
然后重启,如果系统盘不再炸,那基本就能锁定是 VM 启动导致的。
修完之后,改了这几个习惯
硬件变动后,必对 PCI 地址
只要动过 PCIe 插槽、BIOS 设置、增减设备,一定跑一遍:
1 | lspci -Dnn |
然后和所有 VM 配置里的 hostpci 核对一遍。
不要觉得”以前是 03:00.0 以后还是”。
改用 PVE 的 PCI Resource Mapping
在 Datacenter → Resource Mappings → PCI 里给设备建立映射,比直接写死 BDF 安全得多。
系统盘所在的 IOMMU Group,绝不碰
如果发现要直通的设备和系统 NVMe 在同一个 IOMMU Group,会慎重考虑,甚至直接放弃这个直通方案。
最后
这次故障最深刻的体会是:
EXT4-fs error很多时候不是在说”EXT4 坏了”,而是在说”脚底下那块盘没了”。
不要只盯着文件系统修,先问问自己:这个时间点,系统对硬件做了什么?
尤其是在 PVE + PCIe Passthrough + VM autostart 这种组合下,硬件地址变化带来的影响,远比想象中隐蔽。