我在 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 磁盘后不再自动挂载。