如何复制btrfs文件系统


17

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

看起来像是块级副本(例如with dd)不是一个好主意,因为它复制了UUID,并且显然没有办法轻松地对其进行更改

Answers:


4

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

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

使用dd(慢,哑)或partclone.btrfs -b -s /dev/src -o /dev/target

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

数据丢失警告待办事项尝试(自动)安装或者原件或复制,直到UUID已经改变


选项2- btrfs-clone

我没有亲自尝试过btrfs-clone,但是它旨在将现有的BTRFS文件系统克隆到一个新的文件系统,从而依次克隆每个子卷。


1
为了完整起见,
goncalopp

16

截止到今天(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的空间,因此确实避免了数据重复。


写得很好的答案,谢谢。你能解释什么ogen意思吗?
drumfire

@drumfire ogen是子卷的“原始代”。我必须承认,我不完全了解它们之间的差异,也不能完全理解使用(非起源)生成方法是否正确,但是假设某些测试表明这样做效果更好(避免重复)。当基于子卷创建快照时,这一代似乎确实得到了更新,而gen则没有。我想听听一些发现。最好检查IRC或Btrfs邮件列表。
Thomas Luzat

2
我只是采用了@ThomasLuzat的算法,在其周围添加了一些绒毛(检查错误等),并将其放在这里:github.com/jernst/btrfs-copy-filesystem/blob/master/…。它可以解决我从损坏的磁盘中取出磁盘的问题,并且无法保证它可以用于其他任何人。但无论如何,我都会在此处发布此代码,以防有人想要从头开始而不是从头开始编写此代码。当前依赖于新的UBOS方法,但应该易于移植。
约翰内斯·恩斯特

6

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

请考虑以下常见文件系统历史记录:

current ---------------------------------\
             |       |        |          |
           snap4   snap3    snap2      snap1

使用Thomas算法,将首先克隆“ current”,并且所有快照(即“ current”以前状态的快照)都将“ current”用作克隆源/父代。显然,最好将snap3设置在snap4上,将snap2设置在snap3上,等等。

这只是冰山一角。在具有复杂历史记录的btrfs文件系统中查找“最佳”克隆源(就节省空间而言)并非易事。我提出了其他3种策略来解决此问题,这些策略似乎可以更有效地利用空间。实际上导致克隆的大小略小于来源的大小。

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



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.