根本原因是内核中存在未完成I/O或路径状态未收敛,常见于multipath故障恢复后pending request残留或LVM/文件系统持有device-mapper引用。

为什么 dmsetup suspend 会报 “device busy”
根本原因不是设备正在被读写,而是内核中仍有未完成的 I/O 请求或路径状态未收敛。常见于 multipath 设备在路径切换、故障恢复后残留 pending request,或上层(如 LVM、文件系统)持有 device-mapper 表引用。
典型错误信息:device-mapper: suspend ioctl failed: Device or resource busy
- 运行
lsof /dev/mapper/xxx或lsof +D /mnt/point可能查不到真正占用者 —— 占用常来自内核态(如 bio queue、kworker 线程) -
dmsetup info -c查看Open列是否为 0;非 0 表示有活跃用户(如 LVM cache、LV 活跃挂载) - 若使用 LVM,
lvscan --cache或pvs输出中出现active但实际无进程访问,说明 device-mapper target 被缓存引用
执行 dmsetup suspend 前必须检查的三件事
跳过这三步直接强制 suspend,大概率失败,且可能触发路径重映射异常或 I/O hang。
- 确认 multipathd 状态:
systemctl is-active multipathd必须为active;若为inactive,先systemctl start multipathd,否则路径状态不更新,suspend会卡住 - 清空 pending I/O:
echo 1 > /sys/block/dm-XX/device/delete(仅对底层 SCSI 设备有效)不如先运行multipath -r强制重载路径表,再等 2–3 秒让 multipathd 收敛 - 停掉所有依赖该设备的上层服务:比如
umount /dev/mapper/vg-lv、vgchange -an vgname、systemctl stop docker(若容器挂载了该 LV)
dmsetup suspend 和 dmsetup resume 的安全顺序
resume 不是 suspend 的逆操作 —— 它只恢复 device-mapper 的请求转发能力,不恢复路径状态或重连 SCSI 设备。顺序错乱会导致设备不可见或 I/O 错误。
- 正确流程:
multipath -r→ 等待multipath -ll显示所有路径为ready→dmsetup suspend mpatha→ 执行维护(如替换 HBA、拔盘)→multipath -r→dmsetup resume mpatha - 不要在
suspend后直接resume:若底层路径尚未重建(如新磁盘未被 HBA 识别),resume会立即转发 I/O 到无效路径,触发 timeout 或 abort -
dmsetup suspend --noflush不能省略:默认--flush会等待所有 pending I/O 完成,但在 busy 场景下永远等不到;加--noflush是唯一能绕过“busy”的实用方式(但要求你确保上层已静默)
遇到 “device busy” 时最有效的两个应急命令
不是所有场景都能提前卸载或停服务。生产环境常需快速干预,以下命令组合可绕过多数阻塞点。
- 强制释放 device-mapper 引用:
dmsetup remove --force mpatha(慎用!仅当确认无活跃 I/O 且 multipathd 已接管路径管理时) - 配合内核参数临时缓解:
echo 0 > /sys/block/dm-XX/queue/dax(禁用 DAX 可避免某些文件系统层锁争用)+blockdev --flushbufs /dev/mapper/mpatha(清页缓存,减少上层引用) - 终极排查:
cat /proc/dm-0/holders和cat /proc/dm-0/name查看谁持有了这个 dm 设备;若输出为空但仍 busy,基本可判定是 multipathd 内部状态未同步,重启它:systemctl restart multipathd
真正麻烦的从来不是命令本身,而是 multipathd 和内核 block layer 之间那几百毫秒的状态窗口 —— suspend 命令发出时,multipathd 可能刚把一条路径标为 failed,但还没来得及通知 dm 子系统,此时设备就卡在“半悬起”状态。










