☰
NVMe Surprise 掉链、控制器实例漂移与残留 I/O
2026/10/10 6:08:35 网站建设 项目流程

目录

0. 文档用途与口径

1. 现网拓扑(可定死)

1.1 槽位 ↔ Root Port ↔ Endpoint ↔ 控制器实例

1.2 双口为何被排除

2. 失败链(建议按此顺序对外讲述)

3. pciehp 在干什么(物理层入口)

3.1 典型片段(Slot 40 / 32 / 42 形态相同)

3.2 与 -ENODEV 的关系

3.3 现场需一并核对

4. 两类 I/O:必须拆开,禁止写成「盘坏了」

4.1 僵尸 gendisk 被 udev / blkid 戳(容量已废)

4.2 活着或半活路径上的介质 / PI 完成错

4.3 最危险的时序:新实例已活,旧 n1 无人释放

5. 与 CLR / CSTS=0x1 如何衔接(改口径,不推翻旧事实)

6. 证据分级(对外时不要把推断写成事实)

7. 立即处置(只读 + 止血)

7.1 止血

7.2 链路 / 槽位 / AER(只读)

7.3 盘侧只读(禁止 reset / NSSR / FLR)

8. 对外话术(可直接转发)

8.1 平台 / 现场

8.2 盘厂 / 固件

9. 后续决策树(避免现场即兴)

10. 一句话结论


0. 文档用途与口径

本文把现网日志、PCI 拓扑、Identify 信息和块层错误压成一条可对外、可复盘的因果链。结论用于:

  • 现场止血(停旧节点、禁 reset、禁槽位 power cycle)
  • 平台侧查 U.2 / 背板 / 供电 / 带外
  • 盘厂侧查 CC 状态机、未开 PI 时报 Guard Check、残留 NS 完成路径

口径必须同时写两头,缺一不可:

责任面已坐实的现象不能单独解释的部分
平台 / 物理链路pciehpSurprise:Card present + No link,约 30s 后再 Link Up;槽位反复重新枚举掉链之前盘已对 4K Read 回0x281;CLR 后CSTS.RDY不落
盘固件 / NVMe 状态机Controller Reset 后 RDY 卡在0x1→-ENODEV;IdentifyCMIC=0槽位 Presence 仍在、链路自己掉;pciehp风暴先于多数-19

只骂固件或只骂槽位,都会漏掉一半证据。

明确排除:

  • 不是「双端口对端」故事。全机 NVMe 均为xx:00.0单功能,无.1第二 PF。
  • 不只是「CC.EN清不掉RDY」单点。那是失败链中段,入口在链路 Surprise,出口在残留 gendisk 仍被 udev / 巡检打 I/O。

硬禁令(已在现网验证会恶化):

  • nvme reset/ FLR / 写 NSSR
  • echo 0 > /sys/bus/pci/slots/*/power

Slot(40)/(42) 已在断电级循环。在循环上再 reset,会把「链路不稳」升级为「CLR 卡死、CSTS=0x1、最终-ENODEV」。


1. 现网拓扑(可定死)

1.1 槽位 ↔ Root Port ↔ Endpoint ↔ 控制器实例

热插拔槽Root PortEndpoint现 ctrl旧 ctrl本次是否进 surprise 风暴
Slot(40)e0:03.1e1:00.0nvme0nvme3是,反复enabling device
Slot(42)e0:03.3e3:00.0nvme8nvme5是,至少两次完整回来并建队列
Slot(32)80:01.1很大概率81:00.0nvme7—抖动最密;本段 grep未见配套81:00.0增删
其他槽—含另一厂商一块、以及同系列另外两颗若干—未进入同一套风暴

readlink即使未贴全也不影响:内核已把Slot(40)→e1:00.0→nvme0、Slot(42)→e3:00.0→nvme8打进 dmesg。

1.2 双口为何被排除

  • lspci -d ::0108(NVM Express 类代码)全部是xx:00.0,无第二功能。
  • 对0000:e1:00.0/0000:e1:00.*的列举路径本身错误:那是找「该设备下的子设备」,不是找同槽第二 PF。
  • 故障后再枚举的 ctrl Identify:CMIC=0、CNTLID=0,与单控制器一致。

实例号从nvme3→nvme0、nvme5→nvme8,是PCI remove/add 后 nvme 核心按空闲最小号重分配,不是对端口换身份。


2. 失败链(建议按此顺序对外讲述)

U.2 / 背板 / 供电 / 线序 / 带外 power │ ▼ pciehp: Card present, No link (~3s PD 断言, LTSSM 未起来) │ ~30s 等链路 ▼ Card present + Link Up → pci enabling device │ 上电过程中再次 Surprise ▼ Endpoint 从 PCI 消失 / 再出现 │ ├─ 用户可见:ctrl 号漂移(nvme3→0, nvme5→8) ├─ 驱动可见:旧 gendisk 未释放(nvme3n1 / nvme5n1 仍在) └─ 若此时再 nvme reset / FLR │ ▼ CC.EN 置位或 CLR,CSTS.RDY 不落(保持 0x1) │ ▼ 超时 → -ENODEV (-19) ← 链路已没设备时也会直接 -19

并行、独立的一条盘侧错误(发生在部分 Link Down 之前):

周期性 4K Read(opcode 0x2, 8 blocks, ~2s, LBA 散落) │ ▼ 完成状态 SCT=2 SC=81 (0x281 Guard Check) + MORE + DNR │ ▼ (随后才) Slot Link Down → 未完成命令被 host abort → SCT=3 SC=71 (0x371)

因此:0x281不是掉链的结果,是掉链前盘已经在报 PI/介质类错误;0x371才是掉链瞬间的 host 侧取消。


3.pciehp在干什么(物理层入口)

3.1 典型片段(Slot 40 / 32 / 42 形态相同)

Card present No link ← Presence Detect 仍断言,链路未训练 … ~30s(热插拔驱动等 Link Up)… Card present + Link Up pci … enabling device Already in powering on state ← 上电未完成又来一次 surprise

叠加:

日志含义
Already disabled槽位已被软件关掉(pciehp自己,或有人写了slots/*/power)
Slot(40) 反复enabling device同一 BDFe1:00.0被拆掉再枚举成同一个名字nvme0,是循环不是一次 hang
Slot(42) 建队列成功Shutdown timeout 15s、128/0/0 default/read/poll queues、rescanning namespaces→ 新实例曾经 Ready 且有 NS
Slot(32) 最密但缺81:00.0增删更像LTSSM 抖、尚未完整 remove,或 remove/add 打在别的 BDF。必须单独确认下游

3.2 与-ENODEV的关系

-19/-ENODEV在这条链上有两种充分条件,不必互斥:

  1. PCI 设备已从总线消失(Surprise remove)→ 任何后续 admin/io 都是-ENODEV。
  2. 设备还在,但 CLR 后CSTS.RDY不置位,驱动放弃 → 同样-ENODEV。

现网两种都出现过。实例号空洞大量可用 Surprise 直接解释,不必先假设双口。

3.3 现场需一并核对

  • MPS 被抬到 512:是否符合 Root Port / 交换机 / 盘的协商设计,避免当成「无关配置」。
  • BMC / 带外是否对 slot 做 power cycle(会与pciehp抢状态,出现Already disabled/Already in powering on state)。

4. 两类 I/O:必须拆开,禁止写成「盘坏了」

4.1 僵尸 gendisk 被 udev / blkid 戳(容量已废)

I/O error, dev nvme3n1, sector 0 unable to read RDB block 0 unable to read partition table partition table beyond EOD, truncated
项说明
谁在打systemd-udevd/blkid/ 监控扫残节点
打什么sector 0、RDB、分区表
块层状态gendisk还在,容量已是 EOD 或队列已死
是不是业务不是

4.2 活着或半活路径上的介质 / PI 完成错

nvmeXn1: I/O Cmd(0x2) @ LBA …, 8 blocks, I/O Error (sct 0x2 / sc 0x81) MORE DNR critical medium error
字段规格含义现场解读
Opcode0x2Read读路径
8 blocks典型 512B×8 =4KB对齐一次页面/一次 scrub 单元
LBA 散落 + 间隔 ~2s—scrub / 巡检 / 用户态扫盘,不是随机业务
SCT=2 SC=810x281End-to-end Guard Check(PI/DIF CRC)厂商也可能把0x81当通用 media error;必须以 Identify 的dps/ms核对是否真开了 PI
MORE后续还有错不要当单点 ECC
DNRDo Not Retry固件禁止 host 重试;再打也是同一条错

对照样本:

Slot(40): Link Down nvme3n1: … (sct 0x3 / sc 0x71) ← 0x371 HOST_ABORTED_CMD

时序:先0x281完成,后 Link Down,再0x371。
掉链不能用来「洗掉」掉链前的 Guard Check。

4.3 最危险的时序:新实例已活,旧n1无人释放

Endpoint新绑定旧节点仍在 completion
e1:00.0已是nvme0nvme3n1仍出 I/O 完成
e3:00.0已是nvme8,128 队列nvme5n1仍报0x281

内核 nvme 驱动在 Surprise remove 时:

  • PCI 功能没了 → 分配新的nvmeX次序号;
  • 若用户态 / udev / multipath仍持有旧/dev/nvmeXn1的打开文件或 gendisk 引用,旧节点不会消失,I/O 会继续下到已经无效或半死的请求队列。

谁还握着/dev/nvme3n1、/dev/nvme5n1(OSD、qemu、multipath、监控、厂商工具),谁就在给死路径喂 I/O,并把固件从「偶发 PI 错」推向「再 reset / 再掉链」。

数据面只认现实例:nvme0n1/nvme8n1(且list-ns非空)。
旧节点只许停、不许修、不许再blkid。


5. 与 CLR /CSTS=0x1如何衔接(改口径,不推翻旧事实)

仍成立:

  • 两颗问题盘都经历过 Controller Reset 后 RDY 不落 →-ENODEV。
  • 现网没有第二 PF。
  • nvme8是故障后再枚举、「看起来 Ready」的实例(曾建 128 队列并 rescan NS)。

必须改的口径:

  • -19与实例空洞,优先用 Slot(40)/Slot(42) Surprise 解释,CLR 卡死是叠加动作的结果。
  • Slot(40) 两日内反复enabling device= 链路/热插拔循环,不是单次固件 hang。
  • 在循环上打nvme reset:链路窗口内 admin 超时 → 驱动见CSTS停在0x1→ 放弃设备。

规格对照(便于盘厂对接,无需厂商名):

寄存器/状态期望现网
CC.EN0→1 或 Controller ResetCSTS.RDY在 CAP.TO 内置 1保持0x1或不可读
设备从 PCI 消失驱动应 teardown 并释放旧 NS旧n1残留
Identify CMIC双口应有多控制器/多口标志CMIC=0

6. 证据分级(对外时不要把推断写成事实)

级别内容
已坐实三槽pciehpSurprise;e1:00.0↔nvme0↔旧 nvme3;e3:00.0↔nvme8↔旧 nvme5;无第二 PF;0x281出现在部分 Link Down 之前;旧n1在新 ctrl 存活后仍 completion;CLR 后 RDY 不落曾导致-ENODEV
高置信推断Slot(32) 下游为81:00.0;4K/~2s 为 scrub/巡检;僵尸 sector 0 为 udev/blkid
待取证Slot(32) 下游 BDF 实锤;AER/Uncorrectable 是否伴随;BMC 是否 cycle power;id-ns的dps/ms(PI 是否真开);谁持有旧 fd;数据现在在nvme0n1/nvme8n1还是空 ctrl

7. 立即处置(只读 + 止血)

原则:先切断旧节点 I/O,再采集只读信息,全程禁止 reset 与槽位下电。

7.1 止血

lsof /dev/nvme3n1 /dev/nvme5n1 /dev/nvme3 /dev/nvme5 2>/dev/null lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,PKNAME | grep -E 'nvme[0358]' multipath -ll 2>/dev/null | grep -A2 -E 'nvme[0358]' # 若 OSD/文件系统/qemu 仍挂在 nvme3n1、nvme5n1 → 先停业务再卸设备 ls -l /dev/nvme{0,3,5,8}* 2>/dev/null nvme list nvme list-ns /dev/nvme0 nvme list-ns /dev/nvme8

判定:

  • list-ns对 nvme0/nvme8有 NS且存在nvme0n1/nvme8n1→ 数据面在新节点,旧节点一律停。
  • 只有空 ctrl、无n1→ 不要对旧n1做任何「修复」;先固定链路再谈数据。

7.2 链路 / 槽位 / AER(只读)

ls -l /sys/bus/pci/devices/0000:80:01.1/ find /sys/bus/pci/devices/0000:80:01.1 -name address -o -name devicetype 2>/dev/null | head ls /sys/bus/pci/slots for s in /sys/bus/pci/slots/*; do echo "== $s"; cat $s/address $s/power 2>/dev/null; done for d in 0000:e1:00.0 0000:e3:00.0; do echo "== $d" cat /sys/bus/pci/devices/$d/current_link_speed cat /sys/bus/pci/devices/$d/current_link_width done dmesg -T | grep -iE 'AER|PCIe Bus Error|Uncorrectable|e1:00|e3:00|81:00' 核对待外/BMC 是否对上述 slot 做 cycle;不要在此时手动写 slots/*/power

7.3 盘侧只读(禁止 reset / NSSR / FLR)

nvme smart-log /dev/nvme0 nvme smart-log /dev/nvme8 nvme error-log /dev/nvme0 -e 16 nvme error-log /dev/nvme8 -e 16 nvme id-ns /dev/nvme0n1 2>/dev/null | egrep 'nsze|ncap|dps|lbaf|ms ' nvme id-ns /dev/nvme8n1 2>/dev/null | egrep 'nsze|ncap|dps|lbaf|ms '

若dps/ms显示PI 未开却大量0x281:固件乱报或内部映射/RAID 损坏,直接作为盘厂缺陷单,而不是「开 PI 后的 CRC」。

禁止:nvme reset、FLR、写 NSSR、echo 0 > slots/*/power。

建议回收给分析侧:nvme list、旧n1的lsof、nvme0/8 的list-ns、Slot(32) 下游 BDF、id-ns的 PI 字段、当前 link speed/width。


8. 对外话术(可直接转发)

8.1 平台 / 现场

80:01.1Slot(32)、e0:03.1Slot(40)、e0:03.3Slot(42) 发生 PCIe 热插拔 Surprise:Presence 仍在(Card present),链路未训练(No link),约 30s 后再 Link Up。Slot(40)/(42) 伴随 NVMe Endpoint 反复重新枚举;Slot(40) 在两日内多次enabling device。请检查:

  1. U.2 连接器、背板、线序、槽位供电;
  2. 带外/BMC 是否对上述 slot 做 power 操作(日志中有Already disabled/Already in powering on state);
  3. MPS 被协商到 512,是否符合该槽位设计。

在链路未稳定前,不要对槽位软件下电,不要对盘做 Controller Reset / FLR。

8.2 盘厂 / 固件

  • 盘 A(现nvme0@e1:00.0,Slot 40;内核旧名nvme3):掉链前 Read 返回SCT=2 SC=81(Guard Check)DNR,随后 Link Down,host 侧SCT=3 SC=71(HOST_ABORTED_CMD)。历史 CLR 时CSTS保持0x1,随后-ENODEV。
  • 盘 B(现nvme8@e3:00.0,Slot 42;内核旧名nvme5):IdentifyCMIC=0。同样出现过 CLR 后 RDY 不落;再枚举后能建 128 队列并 rescan NS,但旧nvme5n1仍报0x281。

请书面回复:

  1. 链路 Surprise(PD 仍在、LTSSM 掉)后CC.EN/CSTS.RDY的状态机与超时;
  2. Namespace未启用 PI时为何完成0x281Guard Check(或确认内部是否误用该 status);
  3. PCI remove 后残留 NS / 旧块设备上 I/O 的完成与 abort 路径,以及为何 DNR。

9. 后续决策树(避免现场即兴)

链路是否仍在 Surprise 循环? ├─ 是 → 只做物理排查;禁 reset / 禁 slot power;停旧 n1 I/O └─ 否 → nvme0 / nvme8 是否仍在且 list-ns 非空? ├─ 有 n1 → 业务切到新节点;销毁旧 udev 规则/残留 dm;再观察 smart/error-log └─ 无 n1 → 不要扫描旧 n1;保留现场,提交盘厂(RDY/NS 残留)+ 平台(槽位) PI 未开却 0x281? └─ 是 → 固件缺陷单,不要用「开 PI」去圆 谁还在打开 nvme3n1/nvme5n1? └─ 有 → 先杀/停该进程,再谈任何「修复」

10. 一句话结论

三条线同时成立:槽位 Surprise 掉链、PCI 重枚举导致 ctrl 号漂移、旧 gendisk 被 udev/巡检继续打 4K 读。
掉链前已有0x281,CLR 后曾RDY不落;双口不成立。
止血是停旧节点、禁 reset、禁槽位下电;根因由平台链路与盘侧 CC/PI 完成路径共同承担。

你在现网遇到过类似的pciehpSurprise 掉链 + 旧 gendisk 残留的组合吗?当时是怎么定位和止血的?欢迎在评论区分享你的排查思路,一起把这条失败链补得更完整。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询