发布于 ,更新于 

PVE 踩坑:ext4_journal_check_start:84 报错排查

PVE 踩坑:ext4_journal_check_start:84: Detected aborted journal

这事儿前后折腾了快两天。

表面上看,是 EXT4 崩了,NVMe 好像也坏了。但最后发现,硬盘啥事没有,锅全在 PCIe 直通配置上。

简单说就是:PCIe 地址变了,但虚拟机配置没改,结果 PVE 启动 VM 时把设备指错了,顺手把宿主机的系统盘给干趴下了。


一开始,还以为是硬盘坏了

PVE 启动没多久就开始报:

1
2
EXT4-fs error (device dm-1): ext4_journal_check_start:84: Detected aborted journal
EXT4-fs (dm-1): Remounting filesystem read-only

第一反应就是系统盘文件系统坏了。

于是进 SystemRescue,激活 LVM:

1
vgchange -ay

e2fsck

1
e2fsck -f -y /dev/pve/root

确实扫出点东西:

1
2
Free blocks count wrong
Free inodes count wrong

修完以后顺手把 journal 也重建了:

1
2
3
4
tune2fs -O ^has_journal /dev/pve/root
e2fsck -f -y /dev/pve/root
tune2fs -j /dev/pve/root
e2fsck -f -y /dev/pve/root

这时候一切正常,重启,以为搞定了。

结果 PVE 起来大概 30 秒,又炸了,这次是:

1
2
EXT4-fs error (device dm-1) in ext4_reserve_inode_write: IO failure
EXT4-fs (dm-1): Remounting filesystem read-only

不是 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
2
3
for d in /sys/kernel/iommu_groups/*/devices/*; do
echo "IOMMU Group $(basename $(dirname $(dirname "$d"))): $(lspci -nns ${d##*/})"
done

发现这个 USB 控制器和系统 NVMe 处在同一个 IOMMU Group 里,或者至少存在某种 PCIe 拓扑上的互相影响关系。

VFIO 在准备直通的时候,会把整个 group 里的设备都从宿主机驱动解绑。结果就是:

1
2
3
4
5
6
7
8
9
10
11
VM autostart

PVE 执行 hostpci 直通

操作了 ASM1042A 所在的 IOMMU Group

宿主机 NVMe 被波及

系统盘 I/O 直接挂掉

EXT4 触发 journal aborted,自动切 read-only

所以整个链条其实是:

地址变了 → 直通错了设备 → 影响了系统盘的 PCIe 通路 → NVMe I/O 中断 → EXT4 崩溃


为什么绕了这么大一圈?

因为所有报错都太像硬盘故障了:

  • EXT4-fs error
  • Detected aborted journal
  • IO failure
  • Remounting 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 这种组合下,硬件地址变化带来的影响,远比想象中隐蔽。