我正在使用我的 LVM 精简安装。创建了多个快照,多次将它们与原点合并。在lvs -a
命令输出的某个时刻,最旧的快照丢失了其原点。在更详细的命令的输出中,lvs -a -o time,name,origin,lv_role
这些快照现在具有lv_role
(public
而快照具有角色public,snapshot,thinsnapshot
)。merge
现在无法出现错误is not a mergeable logical volume
。现在我有多个问题:
- 这些孤立快照是正确的卷还是已损坏?
- 为什么会发生这种情况?(我正在将一些中间的创建时间快照与其原点合并,然后重新创建它们)
- 我可以手动从快照中删除原点以使其成为分离的卷吗?
- 有没有办法让这些卷恢复为快照,并将相等的数据块再次链接到原点以节省空间?
更新。测试脚本。
具有应存在的 VG 和池名称的初始配置:
VG=vg
Pool="${VG}"/pool0
Test_volume="test"
创建测试 LV 并使其随机
lvcreate -V10M -T "${Pool}" -n "${Test_volume}"
lvchange -ay -Ky "${VG}"/"${Test_volume}"
dd if=/dev/urandom of="/dev/${VG}/${Test_volume}"
lvcreate -n "${Test_volume}_snap_0" --snapshot "${VG}"/"${Test_volume}"
lvchange -ay -Ky "${VG}"/"${Test_volume}_snap_0"
dd if=/dev/urandom of="/dev/${VG}/${Test_volume}"
lvcreate -n "${Test_volume}_snap_1" --snapshot "${VG}"/"${Test_volume}"
lvchange -ay -Ky "${VG}"/"${Test_volume}_snap_1"
dd if=/dev/urandom of="/dev/${VG}/${Test_volume}"
lvcreate -n "${Test_volume}_snap_2" --snapshot "${VG}"/"${Test_volume}"
lvchange -ay -Ky "${VG}"/"${Test_volume}_snap_2"
dd if=/dev/urandom of="/dev/${VG}/${Test_volume}"
lvcreate -n "${Test_volume}_snap_3" --snapshot "${VG}"/"${Test_volume}"
lvchange -ay -Ky "${VG}"/"${Test_volume}_snap_3"
sha256sum "/dev/${VG}/${Test_volume}_snap"*
lvs -a -o name,origin,lv_role| grep "${Test_volume}"
lvs
输出:
test public,origin,thinorigin,multithinorigin
test_snap_0 test public,snapshot,thinsnapshot
test_snap_1 test public,snapshot,thinsnapshot
test_snap_2 test public,snapshot,thinsnapshot
test_snap_3 test public,snapshot,thinsnapshot
现在合并一个快照:
lvconvert --merge "${VG}/${Test_volume}_snap_2"
lvs -a -o name,origin,lv_role| grep "${Test_volume}"
输出:
test public
test_snap_0 public
test_snap_1 public
test_snap_3 public
这些快照现在只是卷,它们可能彼此共享一些块,sha256sum
表明数据是完整的,覆盖一个不会影响其他。
很奇怪为什么他们失去了起源但仍然有共同的数据块。
答案1
当两个精简配置卷具有共享数据块时,并不意味着一个卷必须是另一个卷的来源,或者它们两个必须具有相同的来源(目前;它们过去很可能具有相同的来源)。
为了证明这一点,我将创建一个像你这样的设置:
LV Origin Role
test public,origin,thinorigin,multithinorigin
test_snap_0 test public,snapshot,thinsnapshot
test_snap_1 test public,snapshot,thinsnapshot
95e39bac4333499ebb1cacd8c6aed894c6dddcc2d36505791f9edc81527604be /dev/vg/test
13b4464ba0c3d5c56bcaaa0b600a1118cb391e390457f5d29db6228e403bac9a /dev/vg/test_snap_0
40354ff7b2ac521485bf3ff5dd012cd4919221e5fc4e32369281c784f4b9304c /dev/vg/test_snap_1
除了我让 test 和 test_snap_1 共享前 4M:
# dd if=/dev/vg/test bs=4M count=1 2>/dev/null| sha256sum -
c1f080af2d79f17866522cc5105e248d0ab54d6032a4ff6c384b243d1c1f9837 -
# dd if=/dev/vg/test_snap_0 bs=4M count=1 2>/dev/null | sha256sum -
f4d6a9846b45cfab26a20b3cf56317bf4588f837d423002022f92ca605784622 -
# dd if=/dev/vg/test_snap_1 bs=4M count=1 2>/dev/null | sha256sum -
c1f080af2d79f17866522cc5105e248d0ab54d6032a4ff6c384b243d1c1f9837 -
并让 test_snap_0 和 test_snap_1 共享第二个 4M:
root@test-lvm:~# dd if=/dev/vg/test bs=4M count=1 skip=1 2>/dev/null | sha256sum -
9bf134a0e8727ed6d7087c529f3ce5136a1b10cd31286b5ffda10d0d6708b876 -
root@test-lvm:~# dd if=/dev/vg/test_snap_0 bs=4M count=1 skip=1 2>/dev/null | sha256sum -
01b7a2edcc06a1181db0e77d94c2379df658e240a61f6d1d5e5bce087448212d -
root@test-lvm:~# dd if=/dev/vg/test_snap_1 bs=4M count=1 skip=1 2>/dev/null | sha256sum -
01b7a2edcc06a1181db0e77d94c2379df658e240a61f6d1d5e5bce087448212d -
第三个 4 MiB 区域由这三个区域共享。
现在,合并test_snap_0
:
root@test-lvm:~# lvconvert --merge /dev/vg/test_snap_0
Volume vg/test_snap_0 replaced origin vg/test.
root@test-lvm:~# lvs -o name,origin,lv_role
LV Origin Role
pool0 private
test public
test_snap_1 public
是test_snap_1
基于之前的test
,后者已被移除并被其他卷替换,因此现在test_snap_1
没有任何依据。但其数据仍然正确:
root@test-lvm:~# dd if=/dev/vg/test bs=4M count=1 skip=1 2>/dev/null | sha256sum -
01b7a2edcc06a1181db0e77d94c2379df658e240a61f6d1d5e5bce087448212d -
root@test-lvm:~# dd if=/dev/vg/test_snap_1 bs=4M count=1 skip=1 2>/dev/null | sha256sum -
01b7a2edcc06a1181db0e77d94c2379df658e240a61f6d1d5e5bce087448212d -
为了验证这些块仍然共享,我们将转储精简池元数据:
# dmsetup message /dev/mapper/vg-pool0-tpool 0 reserve_metadata_snap
# thin_dump --format xml -m /dev/mapper/vg-pool0_tmeta > /tmp/dump.xml
# dmsetup message /dev/mapper/vg-pool0-tpool 0 release_metadata_snap
<superblock uuid="" time="5" transaction="10" flags="0" version="2" data_block_size="128" nr_data_blocks="0">
<device dev_id="4" mapped_blocks="192" transaction="7" creation_time="4" snap_time="4">
<range_mapping origin_begin="0" data_begin="0" length="192" time="0"/>
</device>
<device dev_id="5" mapped_blocks="192" transaction="8" creation_time="5" snap_time="5">
<range_mapping origin_begin="0" data_begin="768" length="64" time="4"/>
<range_mapping origin_begin="64" data_begin="64" length="128" time="0"/>
</device>
</superblock>
这里dev_id="4"
是test
,并且dev_id="5"
是test_snap_1
(可以使用 来识别/etc/lvm/backup/vg
)。dev 4 将前一个原点所在的位置映射到pool0_tdata
从 0 到 192 的“物理”块(存储在 中)。而 dev 5 的前 64 个块映射到此范围之后的某个空间。但是 dev 5 从 64 开始的 128 个块实际上指向与 dev 4 中相同的位置,例如这些块是共享的。请注意,这些是“精简 lvm”块,每个大小为 64KiB(这是默认值,可以在创建精简池时设置并使用 进行查询lvs -o name,chunksize
);128 * 64KiB 得出 8MiB — 这是实际共享区域的大小(记住,第三个 4MiB 在所有三个卷上都是相同的)。
如果我重写一个卷的第二个 4MiB 区域,区域将不再共享,另一个卷上的数据将不会被触及,从而正确实现了 CoW 语义。但是如果我稍后再次使它们相同,它们不会神奇地合并回共享区域。原则上,应该可以为精简 LVM 创建一个重复数据删除工具,它将相同的块合并到共享中,从而节省一些空间,即使没有新的 VDO 技术,但我不知道有这样的工具。
参考: