13

Как сделать полную копию содержимого файловой системы btrfs? Под полной копией я подразумеваю не только текущие данные, но также различные подобъемы с их моментальными снимками, в идеале сохраняя их структуры CoW (т.е. не дублируя блоки с одинаковым содержимым.

Кажется, что копирование на уровне блоков (например, с помощью dd) не очень хорошая идея, поскольку оно дублирует UUID, и, по-видимому, нет способа легко его изменить .

5 ответов5

12

На сегодняшний день я не нашел ни одного готового решения (2016-05-06), но решил эту проблему для своих целей, включая обработку копирования при записи. Шаги для "клонирования" /source к /target :

  1. Получить список подобъемов, упорядоченных по ogen: btrfs subvolume list -qu --sort ogen /source . Сортировки, вероятно, достаточно, чтобы гарантировать, что снимки или подобъемы, которые зависят от предыдущих, обрабатываются первыми. Это важно для работы с Copy-on-Write, потому что сначала нам нужно перенести базовые тома.

  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. Я не уверен, что какая-либо метаинформация о снимках или подобъемах будет потеряна в процессе, но почти все, что интересно для большинства случаев использования, должно быть сохранено.

Весь процесс помог мне перенести файловую систему объемом 800 ГБ с 3,8 ГБ (в соответствии с df) в образ 10 ГБ с 3,8 ГБ. Передача без -p и -c бы около 190 ГБ, поэтому дублирования данных действительно удалось избежать.

3

Я создал инструмент Python, который может сделать это. Я сделал это потому, что попробовал подход @Thomas Luzat как в своей собственной, так и в реализации @Johannes Ernst, а используемое пространство удвоилось с 20GB до 40GB в процедуре клонирования. Я думал, что нужно что-то более эффективное.

Рассмотрим эту общую историю файловой системы:

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

С помощью алгоритма Томаса "текущий" будет клонирован первым, и все снимки (являющиеся снимками предыдущих состояний "текущего") будут использовать "текущий" в качестве источника / родителя клона. Очевидно, что было бы лучше основать snap3 на snap4, snap2 на snap3 и т.д.

И это только верхушка айсберга; Найти "лучшие" источники клонов (с точки зрения экономии места) в файловой системе btrfs со сложной историей - нетривиальная проблема. Я предложил 3 другие стратегии для решения этой проблемы, которые, кажется, используют пространство намного эффективнее. Один из них на самом деле привел к размеру клонов чуть ниже исходного.

Вы можете прочитать подробности на странице GitHub, если вам интересно.

2

Используйте btrfstune -u чтобы изменить UUID после dd и перед монтированием.

Предупреждение о потере данных: НЕ пытайтесь смонтировать ни оригинал, ни копию, пока UUID не изменился

1

На unix.stackexchange.com есть похожий вопрос, который указывает на partclone.btrfs, но я не знаю каких-либо подробностей по этому поводу.

Существует также обсуждение в списке рассылки ядра, не очень многообещающе ...

1

С btrfs-send , который я видел в последний раз, все еще были экспериментальные патчи, плавающие в списке рассылки btrfs.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .