Linux共享存储报错“存储正忙”?dmsetup remove_all教你快速定位与清理 简介Linux 存储管理中同一存储设备挂载到两台服务器后常出现一台已挂载、另一台却无法挂载或提示“存储正忙”的故障。这份资源面向系统运维、存储管理员及需要处理共享存储的工程师提供了一套完整的问题分析与解决参考。文档从 Linux 设备文件与 Device-Mapper 映射机制切入清晰解释多服务器同时访问同一存储时产生冲突的底层原因在此基础上详细讲解 dmsetup 命令的用法包括使用 dmsetup remove_all 清除全部设备映射后重新挂载的排错流程并延伸介绍快照、clone、镜像等存储管理技巧兼顾原理理解与实操落地。资源为单个 docx 格式技术文档压缩包内共 1 个文件大小仅 11KB内容紧凑便于快速阅读和查阅。目前已有 1648 人学习下载适合需要排查存储冲突、学习 dmsetup 命令或提升 Linux 存储管理能力的运维人员文档虽短但覆盖了从故障现象、原理分析到解决命令的关键链路实用性强。1. 同一个存储挂两台服务器报错“存储正忙”到底卡在哪两台服务器共享同一个存储LUNA节点因为断电、内核panic或者强制重启挂了B节点接管业务准备挂载这个共享存储却得到了“存储正忙”或者“device is busy”的报错。这个场景在双机热备、数据库主备切换以及SAN多路径组网里非常普遍尤其是故障节点不是优雅下电而是被硬生生拉闸的时候几乎每次都能撞上。很多人遇到这种报错第一反应是存储阵列坏了然后换线、换HBA卡、甚至重启存储控制器绕了一大圈回来报错还是原样。实际上根子通常不在硬件端而在Linux的Device-Mapper映射残留——系统里还留着旧节点对应路径的设备映射新节点的挂载请求就被内核挡在了块设备层。下面要讲的就是这一类“共享存储挂不上、提示正忙”的定位思路、处置命令和事后预防核心操作就一条dmsetup remove_all。2. 根因分析Device-Mapper 残留映射是如何挡住第二条挂载路径的2.1 先分清“存储正忙”和“无法挂载”两个报错指向不同层级在双机共享存储的环境里B节点报错通常有两种形态一种是在系统日志里看到“device-mapper”相关告警随后mount命令返回“device is busy”另一种是挂载时直接提示“存储正忙”或者“资源暂时不可用”。这两类现象看起来差不多其实指向的层级完全不一样。“存储正忙”更接近SCSI层面的预留冲突比如故障节点在存储阵列上留下了持久预留Persistent Reservation而“无法挂载、设备忙”则是操作系统块设备层的状态问题——Device-Mapper映射还挂在某个dm设备上内核认为该设备正处于被占用状态于是拒绝新的open操作。我一般收到这类工单时会让现场工程师先抓三样东西报错原文、dmesg -T的尾部日志、以及dmsetup ls的输出。这三样基本能决定走哪条排查路线。如果是SCSI层的预留冲突光在操作系统里删映射是没用的还要配合存储端释放预留如果是DM映射残留才轮到dmsetup命令登场。不少踩坑的人就是把这两类问题混在一起处理结果在该清理映射的时候去折腾存储在该释放预留的时候反复删映射白白浪费几个小时。2.2 根因拆解故障节点没有“善后”映射状态留在了内核里Device-Mapper是Linux内核的块设备映射框架LVM、多路径软件device-mapper-multipath、dm-crypt这些上层模块都建立在它之上。当两台服务器通过光纤或iSCSI共享同一个LUN时每台服务器上的多路径软件会基于这个LUN的物理路径多块HBA卡、多个控制器端口创建一条逻辑映射最终呈现为一个类似/dev/mapper/mpathX的设备。正常情况下A节点优雅关机时会依次停止多路径服务、清理DM映射、把SCSI层上下文复位。但如果A节点是断电、内核panic或者被强制重启这些清理动作全部没有执行。问题在于共享存储的连接不一定立刻断开A节点留下的DM映射表项、SCSI指令上下文会继续被存储端目标器记录。B节点此刻去挂载内核在发起路径发现、去重、绑定新映射的过程中发现设备状态与已有上下文冲突于是直接拒绝最终表现为“设备忙”或“存储正忙”。还有一个容易被忽略的细节如果B节点之前也挂载过这个LUN并且因为A节点故障触发了多路径切换那么B节点自己的DM映射表里也可能残留着指向旧路径的表项。这种情况下即便在B节点上直接执行mount内核也会因为映射表项冲突而拒绝。所以dmsetup remove_all要清理的不只是对端留下的脏映射还包括本机历史运行留下的残留状态。2.3 dmsetup remove_all 的执行逻辑为什么它能解开这个死结dmsetup是Device-Mapper框架的用户态管理工具负责创建、查询、移除内核中的DM映射设备。dmsetup remove_all的作用是遍历当前系统中所有由Device-Mapper管理的映射设备逐个尝试删除。它的执行逻辑并不复杂向内核发送移除指令内核遍历设备表只要设备没有处于打开状态没有被文件系统挂载、没有被进程占用就移除映射并释放设备号。这条命令之所以能解决“存储正忙”本质上是把本机残留的、处于休眠状态的DM映射全部清干净。映射清掉之后内核里那个“设备已被占用”的状态位随之消失之后无论是用multipath重新加载路径还是直接用新映射挂载都不会再撞上旧上下文。这里有一个关键点需要强调dmsetup remove_all默认遇到仍在使用的设备会跳过并报“Device or resource busy”所以安全做法是先卸载文件系统、停止多路径守护进程再执行清理这个顺序问题会在第5章详细展开。# 查看系统当前的 DM 映射设备清单判断是否有残留 dmsetup ls执行后如果看到很多以mpath开头、或与目标LUN不对应的设备名就说明存在残留映射。还可以用dmsetup table /dev/mapper/xxx查看某条映射的底层物理设备信息确认它是否指向你正在排障的那个LUN。这一步多看两分钟能避免后面误删本地盘映射。3. 标准处置流程确认映射、dmsetup remove_all、重新挂载三步走3.1 挂载前体检lsblk、dmsetup ls、multipath -ll 三件套收到“存储正忙”报错后不要急着删映射。先在B节点上做一轮体检把设备状态摸清楚。我习惯按顺序执行下面三条命令lsblk dmsetup ls multipath -ll这三条命令各有侧重。lsblk负责看块设备树重点确认目标LUN是否已被操作系统识别识别出来的设备名是什么dmsetup ls列出所有DM映射设备排查是否存在和目标LUN同源的残留映射multipath -ll则查看多路径软件对这条LUN的路径聚合情况确认哪几条物理路径在线、哪几条已经掉线。体检结果分两种情况。如果multipath -ll里还能看到完整的路径组说明存储链路本身没断问题大概率在DM映射冲突如果multipath里根本看不到目标LUN或者显示“no path”那就要先解决链路问题包括光模块、交换机zone、存储端口的状态再回来处理映射残留。我遇到过不少案例工程师上来就跑dmsetup remove_all但实际是链路down了清理映射完全不解决问题反而把正常的LVM映射也一并删掉了平白扩大了故障面。3.2 执行 dmsetup remove_all确认环境后一次清理确认是DM映射残留之后才轮到清理动作。执行前必须确认两件事这台服务器上是否有正在使用的本地LVM卷、是否有其他业务挂载点直接走了DM设备。因为remove_all会删除所有DM映射包括本地LVM创建的系统卷映射和业务盘映射。正确做法是先把能卸载的文件系统都卸载掉停掉多路径守护进程如果有再执行# 停掉多路径守护进程避免边清理边重建映射 systemctl stop multipathd # 清理所有 DM 映射设备 dmsetup remove_all # 查看清理结果此时应该没有残留输出 dmsetup ls这段命令的逻辑是先停掉multipathd防止它在我们清理的过程中自动重建映射dmsetup remove_all此时遍历所有DM设备并移除最后的dmsetup ls用来确认列表已经空了。注意我这里故意没有加--force参数。如果执行过程中有设备被进程占用命令会报“Device or resource busy”并跳过那个设备这是内核的保护机制宁可让它跳过也不要强行删除正在使用的映射。注意如果确实有设备报busy需要回到第5章的操作先用lsof/fuser找到占用者卸载干净后再重新执行remove_all。我在生产环境见过太多事故是工程师图省事直接dmsetup remove_all --force结果正在写入的文件系统数据瞬间损坏连恢复的机会都没有。3.3 重新加载路径并挂载partprobe、multipath 刷新与新挂载清理完成后不要以为直接mount就一定成功。还要让系统重新发现路径并生成新的映射。这一步根据环境不同有两种选择如果这台服务器不做多路径聚合直接重新扫描分区# 重新读取分区表让内核重新识别 LUN 上的分区 partprobe /dev/sdX # 挂载文件系统 mount /dev/sdXp1 /data如果使用多路径软件则重新加载多路径映射# 重新加载多路径映射 systemctl start multipathd multipath -r # 确认新映射设备已经生成 multipath -ll这里的逻辑是上一步我们把multipathd停了现在要显式启动它再通过multipath -r触发内核重新扫描该LUN的所有在线路径并根据多路径配置文件生成新的dm设备通常是/dev/mapper/mpathX。之所以先systemctl start multipathd再跑multipath -r是因为如果顺序颠倒守护进程可能在刷新过程中自动重建一份不一致的映射。新映射生成后挂载时优先使用映射名而不是裸设备名因为多路径场景下裸设备名会随路径变化漂移而映射名是稳定的。3.4 挂载后的验证不只是能mount还要能写挂载成功不等于万事大吉。我一般会做三次验证第一dmesg -T | tail看有没有新的I/O报错第二用dd写一个测试文件再读回来确认读写链路通第三stat -f /挂载点看文件系统容量和可用空间是否正确。# 写入 100MB 测试文件并强制落盘验证写链路 dd if/dev/zero of/data/test.bin bs1M count100 convfsync # 读回测试文件验证读链路 dd if/data/test.bin of/dev/null bs1M count100这三步都过了才敢对业务说“存储恢复了”。很多人在这一步翻过车mount成功了但一写大文件就报错回头看dmesg才发现路径组里只剩一条脏路径读没问题写就失败。所以验证一定要包含实际写入不能只停在“能看到文件系统”这一层。4. 共享存储挂载避坑四条最容易翻车的操作记录4.1 现象dmsetup remove_all 报 “Device or resource busy”删不掉原因DM映射设备正被文件系统或进程占用remove_all的保护机制让它跳过正在使用的设备结果命令执行完了一看目标映射还在。很多人在这一步反复执行命令甚至重启系统但问题依旧。解决先umount /挂载点把文件系统卸掉再用lsof/fuser找出占用进程停掉业务后再重新执行dmsetup remove_all。如果文件系统挂在根分区上没法卸载例如LVM卷承载了系统盘那就不能直接清理要把系统引导参数里的该LVM移除或者从救援系统处理。这里最容易踩的坑是把本地系统盘的LVM映射当成“残留”去清理一旦删掉根分区映射系统直接挂起。4.2 现象删除映射后LVM 卷组和逻辑卷全部消失了原因dmsetup remove_all把系统里所有DM映射都删了包括LVM卷组创建的映射。卷组的元数据仍然存在磁盘上但/dev/mapper/vg-lv这个设备节点没有了系统看起来就像“丢盘”。如果不清楚LVM的恢复机制这时候很容易误判为数据丢失。解决执行vgscan重新扫描卷组元数据再执行vgchange -ay激活卷组系统会重新创建逻辑卷的DM映射。如果环境里开了lvmetad缓存还要先重启lvm2-lvmetad服务。这个操作本身不丢数据但容易让人慌一慌就容易做出更危险的动作比如对磁盘重新分区。4.3 现象remove_all 和重新挂载都做了还是提示存储正忙原因这是SCSI持久预留Persistent Reservation在存储端锁着操作系统层面清理映射不解决根本问题。共享存储一般会配置SCSI-3 PR故障节点持有预留key不释放的话其他节点访问该LUN时会被存储端拒绝。解决使用sg3_utils工具包里的sg_persist命令查看预留信息先确认预留key归属再在故障节点已被隔离的前提下用sg_persist --out --release释放预留。释放后重新挂载即可。这里有一条硬性前提必须确保故障节点不会重新启动并抢占存储否则会有双写风险那比报错本身危险得多。4.4 现象两台服务器同时挂载同一个共享盘文件系统几分钟后损坏原因ext4、xfs这类普通文件系统不支持多节点并发读写。块设备层可以同时挂载但文件系统层没有锁协调机制两边的元数据缓存互相覆盖很快就会出现目录结构损坏、文件不可见之类的症状。解决共享存储只能使用集群文件系统如GFS2或者严格的主备模式同一时刻只有一台服务器挂载。不要靠dmsetup来解决并发写的问题这不是映射层能管的。遇到“两台都想同时用一块存储盘”的需求先问架构到底是需要并发读写还是只做主备切换并发读写就该上集群文件系统主备切换则要保证故障节点被彻底隔离。5. 高级场景设备占用、多路径与清理顺序的联动处置5.1 umount 不掉时如何找到真正的占用者清理映射的最大障碍是“设备正在使用”。出现这种情况时不要反复执行umount先定位占用人。命令顺序如下# 查看哪些进程持有该挂载点或设备文件的句柄 lsof /data fuser -v /datalsof会列出进程名和PIDfuser -v会直接显示持有该文件系统的进程。找到进程后优先正常停止业务进程而不是kill -9尤其是数据库类服务强杀进程可能留下需要回滚的事务恢复起来比清理映射更麻烦。业务进程实在停不下来时再考虑fuser -km /data这个命令会终止所有访问该目录的进程副作用大必须确认当前没有关键写操作才能用。这一步做完umount才能顺利通过之后再执行dmsetup remove_all就不会再撞到busy。5.2 多路径环境stop multipathd 与 dmsetup remove_all 为什么必须成对出现在多路径场景中dmsetup remove_all执行到一半时如果multipathd还活着它会立刻检测到映射被删除又重新创建一份新映射导致remove_all永远删不完看起来就像命令失效。这就是为什么第3章的处置流程要先停multipathd。但停掉multipathd之后系统的路径状态又没人维护如果多路径配置文件里写了自动路径分组重新启动multipathd后生成的映射可能和清理前不一致需要再一次multipath -r来稳定映射结构。这套顺序先停服务、再清理、再启动服务、再刷新路径一步都不能跳。我见过有人在生产环境只做了dmsetup remove_all没有停multipathd结果命令跑完映射又被守护进程重建业务挂载依然失败还以为是命令无效。5.3 生产环境操作顺序不可逆的教训——先停应用而不是先碰映射在生产双机系统上做这类操作我强制要求操作顺序是停上层应用、卸载文件系统、停多路径服务、清理映射、重新加载路径、挂载文件系统、启动应用。这个顺序不能颠倒理由很直接任何一步倒过来都可能让数据处于不一致状态。特别是“先清映射再停应用”这种操作应用进程还在读写的时候底层设备突然消失文件系统直接进入异常状态轻则要fsck重则业务数据损坏。备份和回滚能力也要提前准备好如果清理过程中出现意外至少知道如何从备用节点切回。操作前把当前的dmsetup ls输出保存到文件这就是天然的“后悔药”——出了问题能对照着看哪些映射该在、哪些不该在。6. 快速定位共享存储故障三步排查顺序与验证方法遇到“存储正忙/无法挂载”这类报错时我建议按固定顺序排查不要东一榔头西一棒子。第一步收集报错现场。抓取dmesg -T | tail -50、mount命令的完整报错原文、以及systemctl status multipathd的输出。这三个信息能区分问题在SCSI层、DM层还是多路径服务本身。第二步查映射与路径状态。依次执行lsblk、dmsetup ls、multipath -ll把三份输出并排比对。如果dmsetup ls存在与目标LUN相同的映射但multipath -ll不完整走“清理-重建”路径如果multipath正常但挂载仍报busy优先怀疑SCSI持久预留用sg_persist验证。第三步按照下表的对应关系确定处置方向。报错现象优先检查处理方向挂载提示 device is busydmsetup ls、lsof清理DM映射残留multipath -ll 无路径链路、光模块、zone配置先解决物理链路挂载成功但写入异常dmesg、路径组状态刷新路径或更换故障链路报错提示存储正忙sg_persist查询预留确认并释放持久预留验证方法上我自己的习惯是任何涉及共享存储的节点在重启或关机前强制要求先看一遍dmsetup ls和multipath -ll的状态并留档在部署时就提前准备好清理脚本和回滚脚本放到根目录下而不是出了故障再临时翻手册。这样做的原因是我在这类问题上翻过几次车最惨的一次是收到业务方电话说存储正忙我没做任何体检就执行了dmsetup remove_all结果把另一台正常节点的LVM映射也清了导致逻辑卷全部失效业务中断了比直接故障更长的时间。从那以后我每次都强制按“先体检、再定性、后清理”的顺序来再也没有犯过同样的错。希望这篇笔记能帮你少走一次这个弯路。本文还有配套的精品资源点击获取