飞牛 NAS 看电影死机排查实录:VFIO 直通 + md 阵列冲突根治指南
一台飞牛 NAS,用飞牛影视看了半小时电影后整机卡死——ping 不通但机器还在转。本文记录从现象到根治的完整排查过程,供遇到同类问题的朋友参考。
一、问题现象
飞牛 NAS 正常运行,用飞牛影视看电影约 30 分钟后整机卡死
网络不通(ping 不通),但机器电源、风扇仍在转(假死)
强制长按电源 10-15 秒关机后重启才能恢复
反复出现,每次都是看影视持续一段时间后触发
典型特征:不是开机即死,也不是随机死,而是"持续 IO 一段时间后才死"。这种模式高度指向 IO 死锁,而非硬件损坏。
二、排查思路
1. 先排除内存爆掉(OOM)
Plain Text
free -h结果:内存 15G,可用 8.5G,Swap 未使用。排除 OOM。
2. 查 RAID 状态
Plain Text
cat /proc/mdstat发现关键异常:多个阵列标记为 broken,其中 md0/md1 显示 26/1 的诡异槽位数(RAID1 本应只有 2 个槽位),且盘符缺失。
3. 查所有盘的 SMART
Plain Text
lsblk -o NAME,SIZE,MODEL,SERIAL,ROTA
for d in /dev/sd? /dev/nvme?n1; do
smartctl -a "$d" | grep -E "Reallocated|Pending|Uncorrectable|Power_On|Health|Critical"
done结果:sda 和 sdb 两块盘从 lsblk 里彻底消失,但 mdstat 里还挂着它们的阵列。剩下三块盘(sdc 8TB 希捷 + 两块 NVMe)SMART 全部正常。
三、根因定位
关键线索
通过 virsh list --all 发现飞牛里跑着一个群晖 VM ossgyte7,且 /sys/bus/pci/drivers/vfio-pci/ 下有 0000:02:00.0,说明 SATA 控制器通过 VFIO 直通给了群晖 VM。
用户确认:消失的 sda/sdb 正是直通给群晖的那两块盘。
死锁链条
启动时序冲突:
宿主机开机,initramfs 加载 md_mod,先于 VFIO 抢占 SATA 控制器
mdadm 自动扫描,发现 sda/sdb 上有群晖的 RAID superblock,组装成 md0/md1/md3/md127
VFIO 随后绑定控制器,宿主机失去对 sda/sdb 的访问
已组装的 md 阵列变成 broken,但内核仍持有 IO 请求
看影视持续读 IO → 碰到 broken 阵列 → md 重试超时 → D 状态进程堆积 → 整机挂起
为什么是"看半小时才死":平时空闲能撑着,一旦持续高 IO,到临界点就触发死锁。这是 IO 死锁的典型表现,跟"硬件坏盘立即掉线"完全不同。
四、根治方案
需要堵两层:mdadm 启动组装 + udev 热插拔增量组装。只堵一层不够。
第一层:mdadm 启动配置
1. 停掉所有 broken 阵列
Plain Text
mdadm --stop /dev/md0
mdadm --stop /dev/md1
mdadm --stop /dev/md3
mdadm --stop /dev/md1272. 备份原配置
Plain Text
cp /etc/mdadm/mdadm.conf /etc/mdadm/mdadm.conf.bak3. 只保留宿主机自己的阵列
Plain Text
mdadm --detail --brief /dev/md2 /dev/md4 /dev/md6 > /tmp/mdadm.host.conf
cat /tmp/mdadm.host.conf4. 写入新配置,禁止自动组装
Plain Text
echo "AUTO -all" > /etc/mdadm/mdadm.conf
cat /tmp/mdadm.host.conf >> /etc/mdadm/mdadm.conf
echo "MAILADDR root" >> /etc/mdadm/mdadm.confAUTO -all 含义:默认不自动组装任何阵列,只组装下面显式列出的。
5. 更新 initramfs
Plain Text
update-initramfs -u第二层:禁用 udev 增量组装
AUTO -all 管的是 mdadm 启动脚本,管不住 udev 热插拔。VM 关机后盘归还宿主机时,udev 会绕过 mdadm.conf 自动增量组装阵列。必须再堵这一层。
Plain Text
# 1. 停掉当前被组装回来的阵列
mdadm --stop /dev/md0
# 2. 屏蔽 mdadm 的 udev 规则
mkdir -p /etc/udev/rules.d
cp /dev/null /etc/udev/rules.d/85-mdadm.rules
# 3. 重载 udev
udevadm control --reload-rules验证根治效果
Plain Text
# 确认阵列没了
cat /proc/mdstat | grep md0
# 模拟热插拔,看会不会被重新组装
for h in /sys/class/scsi_host/host*/scan; do echo "- - -" > "$h"; done
sleep 3
cat /proc/mdstat | grep md0两次 grep 都无输出 = udev 不再自动组装,根治成功。
五、最终状态
Plain Text
md4 : active raid1 sdb1[0] [U] # 宿主机 8TB 数据盘
md2 : active raid1 nvme1n1p3 [U] # 宿主机 1T NVMe
md6 : active raid1 nvme0n1p1 [U] # 宿主机 512G NVMe启动群晖 VM 后,VFIO 抢走 SATA 控制器,sda/sdc 从宿主机消失,broken 阵列连出现的土壤都没了。看影视 30 分钟以上不再死机,根因 100% 确认。
六、防御层总结
双层防御,彻底根治。
七、附带建议:开启持久化日志
飞牛默认不保留重启后的日志,死机重启后查不到现场。排查时 journalctl -b -1 会报 no persistent journal was found。建议立即开启:
Plain Text
mkdir -p /var/log/journal
systemd-tmpfiles --create --prefix /var/log/journal
systemctl restart systemd-journald下次再死,重启后就能用 journalctl -b -1 -p err 抓到死机当时的错误日志。
八、经验总结
"ping 不通但机器还转"几乎都是 IO 死锁,不是硬件坏。硬件坏通常是某块盘直接掉,不会有"用半小时才死"的特征。
飞牛直通盘给群晖 VM 是常见组合,但默认配置会抢盘。宿主机开机时 mdadm 会抢先扫描到直通盘上的群晖 RAID superblock 并组装,等 VFIO 抢回控制器后阵列就变 broken,埋下 IO 死锁雷。
只改 mdadm.conf 不够,还要堵 udev 热插拔。
AUTO -all管启动脚本,管不住 udev 增量组装。持续 IO 才触发死锁是关键特征。空闲能撑很久,一看影视/转码就死,指向 IO 路径问题而非内存/CPU 问题。
持久化日志默认不开,排查前先开,否则重启后无现场可查。
九、适用范围
飞牛 NAS(fnOS)直通 SATA 盘给群晖/其他 VM 的场景
任何用 KVM/QEMU + VFIO 直通 + mdadm 的 Debian 系宿主机
症状为"持续 IO 后整机卡死、ping 不通但机器还转"
排查日期:2026-09-12 环境:飞牛 fnOS,内核 6.18.18,群晖 VM via VFIO 直通 SATA 控制器
评论交流
欢迎留下你的想法