精简配置的 LVM 快照成为没有来源的单独卷

精简配置的 LVM 快照成为没有来源的单独卷

我正在使用我的 LVM 精简安装。创建了多个快照,多次将它们与原点合并。在lvs -a命令输出的某个时刻,最旧的快照丢失了其原点。在更详细的命令的输出中,lvs -a -o time,name,origin,lv_role这些快照现在具有lv_rolepublic而快照具有角色public,snapshot,thinsnapshot)。merge现在无法出现错误is not a mergeable logical volume。现在我有多个问题:

  1. 这些孤立快照是正确的卷还是已损坏?
  2. 为什么会发生这种情况?(我正在将一些中间的创建时间快照与其原点合并,然后重新创建它们)
  3. 我可以手动从快照中删除原点以使其成为分离的卷吗?
  4. 有没有办法让这些卷恢复为快照,并将相等的数据块再次链接到原点以节省空间?

更新。测试脚本。

具有应存在的 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 技术,但我不知道有这样的工具。

参考:

相关内容