Rocky 10:LVM 快照与 merge 回滚(真机实测)
在 Rocky Linux 10.2 虚拟机(内核 6.12.0-211.16.1.el10_2,LVM 2.03.36)中实测:loop 盘建 PV/VG/LV、XFS、fsfreeze + lvcreate -s、mount -o ro,nouuid 读快照、lvconvert --merge 回滚、重新挂载校验。日志:plans/content-expansion/evidence/logs/rocky-lvm-snapshot.log。
这是真实 EL10 内核的虚拟机,不是共享宿主内核的容器;快照相关的内核行为(dm-snapshot)在此可信。
为什么先 fsfreeze
Section titled “为什么先 fsfreeze”sudo fsfreeze -f /mnt/datasudo lvcreate -y -s -L 300M -n snap /dev/vglab/datasudo fsfreeze -u /mnt/dataXFS 是写时一致性文件系统:挂载状态下直接打快照,可能把「元数据已改、数据未落盘」的中间态拍进去,快照里的文件系统就不一致。fsfreeze -f 把挂起写操作、刷盘,-u 再解冻。
不加 fsfreeze 的后果不是必然失败,而是「快照可能不可用」——比报错更危险。
只读挂载快照要加 nouuid
Section titled “只读挂载快照要加 nouuid”sudo mount -o ro,nouuid /dev/vglab/snap /mnt/snapls /mnt/snapcat /mnt/snap/a.txta.txtbefore-snapshot快照与源卷的 XFS UUID 相同,内核默认拒绝同时挂载两个同 UUID 的文件系统;nouuid 跳过这个检查。只读挂载还避免快照被写入。
改数据:验证「快照冻结在那一刻」
Section titled “改数据:验证「快照冻结在那一刻」”echo "after-snapshot-change" > /mnt/data/b.txtrm -f /mnt/data/a.txtls /mnt/datab.txt源卷变成只有 b.txt;而快照里仍是 a.txt 且内容是 before-snapshot——两边是不同时间点。
merge 回滚与 EBUSY 坑
Section titled “merge 回滚与 EBUSY 坑”sudo umount /mnt/datasudo lvconvert --merge /dev/vglab/snapsudo lvchange -an vglab/datasudo lvchange -ay vglab/dataMerging of volume vglab/snap started.vglab/data: Merged: 100.00%merge 报 100% 不代表能立刻挂载。实测只做 lvchange -ay 直接 mount 会得到:
mount: /mnt/data: /dev/mapper/vglab-data already mounted or mount point busy.先 lvchange -an 再 -ay(完整去激活/再激活)之后挂载才成功。这是本页最有价值的一条——Merged: 100.00% 会让人误以为已经好了。

回滚后的校验
Section titled “回滚后的校验”sudo mount /dev/vglab/data /mnt/datals /mnt/datacat /mnt/data/a.txtls /mnt/data/b.txta.txtbefore-snapshotls: cannot access '/mnt/data/b.txt': No such file or directorya.txt 回来了、b.txt 消失了——快照时间点之后的所有写入都被回滚。必须做这一步,只看 merge 百分比不算验证。
可播放的完整时序
Section titled “可播放的完整时序”下面这段终端录制把「建卷 → freeze → 打快照 → 改数据 → 读快照 → merge → 重新激活 → 校验」一次放完(.cast 只有 871 字节,默认不自动播放):
文字版(命令与输出) / Text transcript
# 1. build a loop-backed LV for the labtruncate -s 1G /var/tmp/cast.imgpvcreate -y "$L"; vgcreate vglab "$L"; lvcreate -y -L 800M -n data vglabmkfs.xfs -q /dev/vglab/data; mount /dev/vglab/data /mnt/dataecho before > /mnt/data/a.txt
# 2. freeze, snapshot, unfreezefsfreeze -f /mnt/datalvcreate -y -s -L 200M -n snap /dev/vglab/datafsfreeze -u /mnt/dataLV LSize Attrdata 800.00m owi-aos---snap 200.00m swi-a-s---
# 3. change the origin, then read the snapshotecho after > /mnt/data/b.txt; rm -f /mnt/data/a.txtmount -o ro,nouuid /dev/vglab/snap /mnt/snapcat /mnt/snap/a.txt # before
# 4. merge back and reactivatelvconvert --merge /dev/vglab/snapvglab/data: Merged: 100.00%lvchange -an vglab/data; lvchange -ay vglab/data
# 5. verify the rollbackcat /mnt/data/a.txt # before- 不 fsfreeze:快照可能不一致,恢复时才发现;
- 挂快照不加
nouuid:报 UUID 冲突; - merge 后直接 mount:EBUSY,先
lvchange -an && -ay; - merge 前没卸载:
lvconvert --merge要求源卷未挂载。
练习:完整走一遍快照与回滚
Section titled “练习:完整走一遍快照与回滚”sudo dnf install -y lvm2 xfsprogstruncate -s 2G /var/tmp/snap.imgL=$(sudo losetup -f --show /var/tmp/snap.img)sudo pvcreate -y "$L" && sudo vgcreate vglab "$L"sudo lvcreate -y -L 1G -n data vglabsudo mkfs.xfs -q /dev/vglab/datasudo mkdir -p /mnt/data /mnt/snap && sudo mount /dev/vglab/data /mnt/dataecho before | sudo tee /mnt/data/a.txt >/dev/null && syncsudo fsfreeze -f /mnt/datasudo lvcreate -y -s -L 300M -n snap /dev/vglab/datasudo fsfreeze -u /mnt/datasudo rm /mnt/data/a.txtsudo umount /mnt/data && sudo lvconvert --merge /dev/vglab/snapsudo lvchange -an vglab/data && sudo lvchange -ay vglab/datasudo mount /dev/vglab/data /mnt/data && cat /mnt/data/a.txt检查:
lvs -o lv_attr里快照属性以s开头mount -o ro,nouuid能读到before- merge 输出
Merged: 100.00% - 回滚后
cat /mnt/data/a.txt输出before
常见问题
快照一定要 fsfreeze 吗?
对 XFS/ext4 这类日志文件系统,挂载状态下打快照必须冻结才能保证一致;不冻结的快照可能能挂载但数据不一致,恢复时才暴露问题。
为什么挂快照要加 nouuid?
快照复制了源文件系统的 UUID,内核默认不允许两个同 UUID 的 XFS 同时挂载;nouuid 跳过该检查,配合 ro 只读使用。
merge 报 100% 后挂载 EBUSY 怎么办?
做一次完整去激活/再激活:lvchange -an vglab/data && lvchange -ay vglab/data,再 mount;只 -ay 不够(实测)。
- LVM 扩容:LVM 扩容
- XFS 修复:XFS 修复
- rsync 增量备份:rsync 增量备份