btrfs 卷的 LVM 快照更改已安装的设备

btrfs 卷的 LVM 快照更改已安装的设备

我在 LVM 上有一个 btrf 卷。现在我想在 lvm 级别(而不是 btrfs 级别)上创建快照。但每次我创建 LVM 快照时,btrfs 都会将挂载的块设备更改为快照,就像我使用某种 --bind mount 选项一样。

情况:

# 安装 | grep libvirt
/var/lib/libvirt/images 上的 /dev/dm-4 类型 btrfs (rw、relatime、space_cache)
# ls -l /dev/mapper | grep dm-4
lrwxrwxrwx 1 root root 7 月 17 日 01:18 system-vm_disks -> ../dm-4
# lvcreate -s /dev/system/vm_disks -n vm_backup -L 32G
  逻辑卷“vm_backup”已创建
# 安装 | grep libvirt
/var/lib/libvirt/images 上的 /dev/dm-5 类型 btrfs (rw、relatime、space_cache)
# ls -l /dev/mapper | grep dm-5
lrwxrwxrwx 1 root root 7 月 17 日 01:18 system-vm_backup -> ../dm-5
# 挂载 /dev/system/vm_backup /mnt/test
# 触摸 /mnt/test/touchME
# ls -l /var/lib/libvirt/images/touchME
-rw-r--r-- 1 root root 0 三月 17 01:26 /var/lib/libvirt/images/touchME

当我删除快照时:

# 卸载 /mnt/test
# lvremove /dev/system/vm_backup
您确实要删除活动逻辑卷 vm_backup 吗?[y/n]: y
  逻辑卷“vm_backup”已成功删除
# 安装 | grep libvirt
/var/lib/libvirt/images 上的 /dev/dm-4 类型 btrfs (rw、relatime、space_cache)
# ls -l /dev/mapper | grep dm-4
lrwxrwxrwx 1 root root 7 月 17 日 01:21 system-vm_disks -> ../dm-4
# ls -l /var/lib/libvirt/images/touchME
-rw-r--r-- 1 root root 0 三月 17 01:26 /var/lib/libvirt/images/touchME

我希望我的快照是真正的快照,而不是像 --bind mount 这样的快照。我正在使用 LVM 快照通过 rsync 将一致的系统状态备份到我们的备份服务器。出于各种原因,我不想使用 btrfs 快照:

  • 我想备份 vm_disks LV 中的每个子卷和每个 btrfs 快照(但我不知道有多少以及有哪些快照/子卷)
  • 我的备份策略不应该依赖于文件系统。理想情况下,在更改 /var/lib/libvirt/images 处的文件系统时,不需要更改任何其他内容

我的系统:

# uname -a
Linux 笔记本电脑 3.12-1-amd64 #1 SMP Debian 3.12.9-1 (2014-02-01) x86_64 GNU/Linux
# lvm 版本
  LVM 版本:2.02.104(2)(2013-11-13)
  库版本:1.02.83(2013-11-13)
  驱动程序版本:4.26.0
# btrfs --version
Btrfs v3.12

我必须至少使用内核 3.9 或更新版本,因为我使用 Linux 3.9 或更新版本提供的 IPv6 NAT 功能(是的,我知道您不应该将 NAT 与 IPv6 一起使用,但那是另一回事)。

感谢您的帮助!

编辑:

我使用 dd 和 loop 设备做了一些实验。这种行为并非 LVM 所特有。

测试:

# mkfs.btrfs /dev/loop0
[...]
# 挂载 /dev/loop0 原始
# 触摸原始/原始文件
# ls -l 原始
-rw-r--r-- 1 root root 0 3月28日 21:42 original_file
# dd if=/dev/loop0 of=/dev/loop1
509312+0 条记录
509312+0 条记录
已复制 260767744 字节(261 MB),耗时 1.76431 秒,148 MB/s
# 挂载 /dev/loop1 克隆
# 触摸克隆/预期克隆文件
# ls -l 克隆
-rw-r--r-- 1 root root 0 3月28日 21:44 expected_clone_file
-rw-r--r-- 1 root root 0 3月28日 21:42 original_file
# ls -l 原始
-rw-r--r-- 1 root root 0 3月28日 21:44 expected_clone_file
-rw-r--r-- 1 root root 0 3月28日 21:42 original_file
# 卸载克隆
# 卸载原有
# 挂载 /dev/loop1 克隆
# ls -l 克隆
-rw-r--r-- 1 root root 0 3月28日 21:42 original_file
# 卸载克隆
# 挂载 /dev/loop0 原始
# ls -l 原始
-rw-r--r-- 1 root root 0 3月28日 21:44 expected_clone_file
-rw-r--r-- 1 root root 0 3月28日 21:42 original_file

因此,每当您尝试安装一个包含克隆的 btrfs 文件系统的新设备时,您最终都会使用旧的已安装设备(但 mount 的输出中没有任何内容正确表明这一点,如您在上面的 LVM 实验中看到的那样)。因此,所有请求最终都会使用旧设备。您无法安装克隆的 fs,直到您卸载原始 fs(并且您无法在安装克隆的 fs 时安装原始 fs)。

我现在的问题是:如何将克隆的 btrfs 的 uuid 更改为某个新的未使用的 uuid。我猜想之后我就能将克隆的设备与原始设备一起安装。

答案1

我还没有深入研究过这个问题,但 btrfs 作为文件系统是在磁盘组上运行的,而不是单个设备。

我怀疑 btrfs 在挂载时无法区分挂载的快照和实际挂载的文件系统。事实上,它可能会看到底层子卷的 UUID,假设它是原始卷的镜像,并同时写入两个卷。

如果这个问题能够得到解决我会感到惊讶,因为在大多数情况下,btrfs 快照都取代了 LVM 快照。

答案2

看起来 udev 是导致这种现象的原因。

执行 lvcreate (或 losetup)会导致 udev 在“块”系统上执行“更改”操作:

# udevadm monitor
...
UDEV  [62084.032411] change   /devices/virtual/block/dm-7 (block)
UDEV  [62084.469374] change   /devices/virtual/block/dm-6 (block)
UDEV  [62084.582549] change   /devices/virtual/block/dm-6 (block)
UDEV  [62084.606191] change   /devices/virtual/block/dm-5 (block)
...

这会触发(就我而言)以下规则:

/lib/udev/rules.d/64-btrfs.rules

并调用内置的 udev 命令:

IMPORT{builtin}="btrfs ready $devnode"

通过 src/udev/udev-builtin-btrfs.c:52

err = ioctl(fd, BTRFS_IOC_DEVICES_READY, &args);

进入内核:http://lxr.free-electrons.com/source/fs/btrfs/volumes.c#L848导致出现如下 dmesg:

...
[62030.117248] btrfs: device label label devid 1 transid 13 /dev/dm-6
[62030.141242] btrfs: device label label devid 1 transid 13 /dev/dm-5
...

目前尚不清楚究竟是什么导致了“重新挂载”,也不清楚为什么需要这样做。但有关重复的 UUID 是罪魁祸首的说法似乎并不牵强。

我甚至不确定这种重新挂载(更改现有挂载点的设备)是否是需要的或有用的行为......

如果您想要改变行为,您可以修改或删除 btrfs-udev 规则,但会丧失功能:热插拔 btrfs usb 磁盘后不再自动挂载。

相关内容