已挂载文件系统的LVM快照

lio*_*ori 5 linux filesystems backup snapshot

我想以编程方式在Linux中制作实时文件系统的快照,最好使用LVM.我不想卸载它,因为我已经打开了很多文件(我最常见的情况是我有一个繁忙的桌面有很多程序).

我理解,由于内核缓冲区和一般文件系统活动,磁盘上的数据可能处于某种或多或少的未定义状态.

有没有办法"原子地"卸载FS,制作LVM快照并将其挂载?如果操作系统将阻止所有活动几秒钟来执行此任务,那就没问题.或者也许某种原子"同步+快照"?内核通话?

我不知道是否有可能......

Omn*_*ous 11

您不应该为大多数Linux文件系统做任何事情.它应该在你没有任何努力的情况下工作.快照命令本身使用正在快照的卷搜寻已挂载的文件系统,并调用一个特殊的挂钩,以一致的可挂载状态检查它们并以原子方式执行快照.

较旧版本的LVM带有一组VFS锁定补丁,可以修补各种文件系统,以便可以为快照检查点.但是新内核应该已经内置到大多数Linux文件系统中.

这个快照简介声称同样多.

还有一点研究表明,对于2.6系列中的内核,ext系列文件系统应该都支持这一点.ReiserFS也可能.如果我知道btrfs的人,那个人可能也会这样做.


Vla*_*eev 6

有什么方法可以“自动”卸载 FS、制作 LVM 快照并将其重新安装吗?

即使文件系统不在 LVM 卷上,也可以对已安装的文件系统进行快照。如果文件系统位于 LVM 上,或者它具有内置快照设施(例如 btrfs 或 ZFS),则改用它们。

以下说明相当低级,但如果您希望能够对不在 LVM 卷上的文件系统进行快照,并且无法将其移动到新的 LVM 卷,那么它们可能会很有用。尽管如此,它们并不适合胆小的人:如果你犯了一个错误,你可能会损坏你的文件系统。请务必查阅官方文档dmsetup手册页,三重检查您正在运行的命令,并进行备份

Linux 内核有一个很棒的工具,称为设备映射器,它可以做一些不错的事情,例如创建作为其他块设备“视图”的块设备,当然还有快照。这也是 LVM 在幕后用来完成繁重工作的方法。

在下面的示例中,我假设您想要快照/home,它是位于 上的 ext4 文件系统/dev/sda2

首先,找到分区挂载的设备映射器设备的名称:

# mount | grep home
/dev/mapper/home on /home type ext4 (rw,relatime,data=ordered)
Run Code Online (Sandbox Code Playgroud)

这里,设备映射器设备名称是home。如果块设备的路径不以 开头/dev/mapper/,那么您将需要创建一个设备映射器设备,并重新挂载文件系统以使用该设备而不是 HDD 分区。您只需执行一次此操作。

# dmsetup create home --table "0 $(blockdev --getsz /dev/sda2) linear /dev/sda2 0"
# umount /home
# mount -t ext4 /dev/mapper/home /home
Run Code Online (Sandbox Code Playgroud)

接下来,获取块设备的设备映射表:

# dmsetup table home
home: 0 3864024960 linear 9:2 0
Run Code Online (Sandbox Code Playgroud)

您的数字可能会有所不同。设备目标应该是linear;如果您的不是,您可能需要特别考虑。如果最后一个数字(起始偏移量)不为 0,则需要创建一个中间块设备(与当前块设备具有相同的表)并使用它作为基础而不是/dev/sda2.

在上面的示例中,home使用带有linear目标的单条目表。您需要将此表替换为使用snapshot目标的新表。

设备映射器提供三个快照目标:

  • 目标snapshot,将写入保存到指定的 COW 设备。(请注意,尽管它被称为快照,但该术语具有误导性,因为快照将是可写的,但底层设备将保持不变。)

  • 目标snapshot-origin将写入发送到底层设备,同时还将写入覆盖的旧数据发送到指定的 COW 设备。

通常,您会创建home一个目标,然后在其之上snapshot-origin创建一些目标。snapshot这就是 LVM 的作用。然而,更简单的方法是直接创建一个snapshot目标,这就是我将在下面展示的内容。

无论您选择哪种方法,都不能写入底层设备 ( /dev/sda2),否则快照将看到文件系统的损坏视图。因此,作为预防措施,您应该将底层块设备标记为只读:

# blockdev --setro /dev/sda2
Run Code Online (Sandbox Code Playgroud)

这不会影响它支持的设备映射器设备,因此如果您已经重新安装/home在 上/dev/mapper/home,它应该不会产生明显的影响。

接下来,您需要准备 COW 设备,该设备将存储自创建快照以来的更改。这必须是块设备,但可以由稀疏文件支持。如果您想使用例如 32GB 的稀疏文件:

# dd if=/dev/zero bs=1M count=0 seek=32768 of=/home_cow
# losetup --find --show /home_cow
/dev/loop0
Run Code Online (Sandbox Code Playgroud)

显然,稀疏文件不应该位于您正在快照的文件系统上:)

现在您可以重新加载设备的表并将其变成快照设备:

# dmsetup suspend home && \
  dmsetup reload home --table \
    "0 $(blockdev --getsz /dev/sda2) snapshot /dev/sda2 /dev/loop0 PO 8" && \
  dmsetup resume home
Run Code Online (Sandbox Code Playgroud)

如果成功,新的写入/home现在应该记录在/home_cow文件中,而不是写入/dev/sda2. 确保监视 COW 文件的大小以及其所在文件系统上的可用空间,以避免耗尽 COW 空间。

一旦不再需要快照,您可以合并它(将 COW 文件中的更改永久提交到底层设备),或者丢弃它。

  • 合并它:

    1. 将表替换为snapshot-merge目标而不是目标snapshot

      # dmsetup suspend home && \
        dmsetup reload home --table \
          "0 $(blockdev --getsz /dev/sda2) snapshot-merge /dev/sda2 /dev/loop0 P 8" && \
        dmsetup resume home
      
      Run Code Online (Sandbox Code Playgroud)
    2. 接下来,监视合并的状态,直到所有非元数据块都合并:

      # watch dmsetup status home
      ...
      0 3864024960 snapshot-merge 281688/2097152 1104
      
      Run Code Online (Sandbox Code Playgroud)

      请注意末尾的 3 个数字 (X/YZ)。当 X = Z 时合并完成。

    3. 接下来,再次用线性目标替换表格:

      # dmsetup suspend home && \
        dmsetup reload home --table \
          "0 $(blockdev --getsz /dev/sda2) linear /dev/sda2 0" && \
        dmsetup resume home
      
      Run Code Online (Sandbox Code Playgroud)
    4. 现在你可以拆除循环设备了:

      # losetup -d /dev/loop0
      
      Run Code Online (Sandbox Code Playgroud)
    5. 最后,您可以删除COW文件。

      # rm /home_cow
      
      Run Code Online (Sandbox Code Playgroud)
  • 要放弃快照,请 unmount /home,按照上面的步骤 3-5 操作,然后重新 mount /home。尽管设备映射器将允许您在不卸载的情况下执行此操作/home,但它没有意义(因为内存中正在运行的程序的状态将不再对应于文件系统状态),并且它可能会损坏您的文件系统。


Zan*_*ynx 5

我知道 RedHat Enterprise、Fedora 和 CentOS 中的 ext3 和 ext4 在创建 LVM 快照时会自动设置检查点。这意味着安装快照永远不会出现任何问题,因为它始终是干净的。

相信XFS也有同样的支持。我不确定其他文件系统。