如何复制 btrfs 文件系统

loo*_*bee 18 backup btrfs

如何制作btrfs 文件系统内容的完整副本?通过完全复制我的意思不仅是当前的数据,而且不同的子体积与他们的快照,保存最好母牛结构(即:不与相同内容重复的块。

似乎块级副本(例如 with dd)不是一个好主意,因为它复制了 UUID,并且显然没有办法轻松更改它

Tho*_*zat 18

截至今天(2016-05-06),我还没有找到任何现成的解决方案,但是为了我的目的解决了这个问题,包括写时复制处理。“克隆”/source到的步骤/target是:

  1. 获取按ogen以下顺序排序的子卷列表: btrfs subvolume list -qu --sort ogen /source。排序可能足以保证首先处理依赖于先前快照或子卷的快照或子卷。这对于处理写时复制很重要,因为我们需要先传输基本卷。

  2. 使所有子卷只读使用 btrfs property set -ts /source/some-volume ro true

  3. 现在,对于上面列表中的每个子卷,从顶部开始,执行以下操作:

    1. 如果卷没有父 UUID(显示为-)或父 UUID 不再存在于列表中,请运行:btrfs send /source/some/volume | btrfs receive /target/some/

    2. 如果卷确实有一个仍然存在的父 UUID,我们应该已经转移它,因为--sort ogen我们可以使用它作为基础来避免数据重复。因此,在列表中找到父 UUID 的路径并运行:btrfs send -p /source/parent/volume/ -c /source/parent/volume/ /source/some/volume/ | btrfs receive /target/some/(btrfs 可能会-p自动猜测参数,但我更愿意明确表示)。

    3. 运行上述命令之一后,再次使目标和源读写:btrfs property set -ts /source/some/volume ro false; btrfs property set -ts /target/some/volume ro false. 如果源以前是只读的,则可以跳过此步骤。

这应该可以处理很多情况。注意事项:

  1. 在嵌套子卷/快照时,排序可能会有些复杂。

  2. 整个过程在脚本化后显然更有趣。

  3. btrfs send接受多个克隆源 ( -c) 参数。不仅指定父卷路径,而且指定任何祖先的卷路径或简单地任何先前发送的卷的路径可能是有利的。它在这里没有任何区别,但它可能 - 只是一个猜测 - 在某些情况下有助于避免数据重复。

  4. 我不确定快照或子卷上的任何元信息是否会在此过程中丢失,但对于大多数用例来说,几乎所有其他有趣的东西都应该保留。

整个过程帮助我将使用 3.8 GB 的 800 GB 文件系统(根据df)传输到使用 3.8 GB 的 10 GB 图像。没有传输-p并且-c会使用大约 190 GB,因此确实避免了数据重复。

  • 我只是采用了 @ThomasLuzat 的算法,在它周围添加了一些绒毛(错误检查等)并将其放在这里:https://github.com/jernst/btrfs-copy-filesystem/blob/master/btrfs-copy-filesystem。它解决了我从损坏的磁盘中获取的问题,并且不能保证它对其他人有效。但无论如何我都会在这里发布这个,以防有人想从头开始以外的地方开始编写代码。目前依赖于新的 UBOS 方法,但应该很容易移植。 (2认同)

小智 9

我创建了一个可以做到这一点的python 工具。我这样做是因为我在我自己的和 @Johannes Ernst 的实现中都尝试了 @Thomas Luzat 的方法,并且在克隆过程中使用的空间从 20GB 翻了一番到 40GB。我认为需要一些更有效的东西。

考虑这个常见的文件系统历史:

current ---------------------------------\
             |       |        |          |
           snap4   snap3    snap2      snap1
Run Code Online (Sandbox Code Playgroud)

使用 Thomas 的算法,“当前”将首先被克隆,所有快照(即“当前”以前状态的快照)将使用“当前”作为克隆源/父项。显然,将 snap3 基于 snap4,将 snap2 基于 snap3 等会更好。

而这只是冰山一角;在具有复杂历史的 btrfs 文件系统中找到“最佳”克隆源(就空间节省而言)是一个不平凡的问题。我提出了 3 种其他策略来解决这个问题,它们似乎更有效地利用空间。一个实际上导致克隆的大小略低于源的大小。

如果您有兴趣,可以在github 页面上阅读详细信息。


Tom*_*ale 6

选项 1 - 哑数据复制然后更改 UUID

确保源分区已卸载且不会自动挂载。

使用dd(缓慢、愚蠢)或partclone.btrfs -b -s /dev/src -o /dev/target

用于btrfstune -u在复制之后和安装之前更改 UUID。

数据丢失警告在 UUID 更改之前,请勿尝试(自动)安装原始文件或副本


选项 2 -btrfs-clone

我个人没有尝试过btrfs-clone,但它旨在将现有的 BTRFS 文件系统克隆到新的文件系统,并按顺序克隆每个子卷。