btrfs send и receive можно использовать для передачи терабайтов данных, но эти команды не дают полезных результатов (даже с -v). Как я могу проверить, удалось ли им это сделать?

Например, если я создаю новый подтом с именем source, записываю в него 1 ГБ случайных данных и делаю его доступным только для чтения, чтобы его можно было отправить:

# btrfs subvolume create source
# head -c 1G < /dev/urandom > source/data
# btrfs property set source ro true

Затем создайте копию нового подтома, используя btrfs send и receive, но прервите процесс до его завершения:

# mkdir destination
# btrfs send source | btrfs receive destination
At subvol source
At subvol source
^C

btrfs subvolume list не будет означать, что что-то пошло не так:

# btrfs subvolume list .
ID 1216 gen 370739 top level 5 path source
ID 1219 gen 371244 top level 5 path destination/source

Новый подобом можно просматривать нормально, хотя очевидно, что его данные повреждены:

# exa -lT
   - ├── destination
   - │  └── source
251M │     └── random_data
   - └── source
1.1G    └── random_data

btrfs subvolume show destination/source не предупреждает нас о том, что подтом неполный. Это показывает, что destination/source имеет разные UUID и source, и похоже, что destination/source Received UUID будет установлено на source 's UUID тогда и только тогда, когда btrfs receive выполняется до завершения.

Гарантирует ли наличие Received UUID, что подтом, созданный btrfs receive, является полной и неизмененной копией подтома с этим UUID в другой файловой системе?

Эта часть man btrfs-send предполагает, что нет, и кажется подразумевая, что использование destination/source в приведенном выше примере в качестве родителя будущего моментального снимка source также не сможет обнаружить и исправить повреждение. Тем не менее, я до сих пор не совсем понимаю цель send -c и применим ли этот совет также к send -p.

В инкрементальном режиме (опции -p и -c) ранее отправленные снимки, доступные как на стороне отправки, так и на стороне получателя, могут использоваться для уменьшения объема информации, которая должна быть отправлена ​​для восстановления отправленного. снимок в другой файловой системе.

Параметр -p <parent> можно опустить, если заданы параметры -c <clone-src>, и в этом случае отправка btrfs определит подходящего родителя из числа источников клонирования.

Вы не должны указывать источники клонирования, если не гарантируете, что эти моментальные снимки находятся в одинаковом состоянии с обеих сторон — как для отправителя, так и для получателя.

Насколько я могу судить, snap-sync, buttersink и другие подобные инструменты решают эту проблему, перенаправляя вывод btrfs send в серию файлов и передавая их используя надежный метод, такой как rsync, а не простой канал. Является ли это правильным подходом, если я хочу разработать собственное решение для инкрементного резервного копирования, не полагаясь на стороннее программное обеспечение, не включенное в мой дистрибутив?

9
Community 11 Июн 2020 в 17:16
Если кто-то еще сталкивается с этим вопросом и смотрит на snap-sync и buttersink, в настоящее время я изучаю btrbk, который кажется более многообещающим вариантом с лучшей документацией.
 – 
sjy
29 Фев 2020 в 16:44

3 ответа

Лучший ответ

TL;DR: Если Received UUID и установлен флаг readonly, то маловероятно, что что-то пошло не так, если только речь не идет о небрежности или злом умысле.

Как уже сказал @timakro в своем ответе, Received UUID не устанавливается до тех пор, пока передача не будет завершена. Также не является флагом readonly. Это, в сочетании с тем фактом, что каждая команда в потоке проверяется контрольной суммой (и что, насколько я понимаю, отправляемые метаданные также включают контрольные суммы), делает маловероятным, что вы получите поврежденный снимок на принимающей стороне с readonly и Received UUID установлены. Если какой-либо из них не установлен, btrfs откажется использовать этот снимок в качестве эталона для будущего btrfs receive.

Повреждение полученного моментального снимка может быть преднамеренным повреждением, если получен специально созданный поток, или если какой-либо процесс или пользователь изменил содержимое полученного моментального снимка во время его получения. На справочной странице btrfs-receive:

ОШИБКИ

Прием btrfs устанавливает для подтома доступ только для чтения после его успешного завершения. Однако во время получения пользователи, имеющие доступ на запись к файлам или каталогам на пути получения, могут добавлять, удалять или изменять файлы, и в этом случае результирующий подтом, доступный только для чтения, не будет точной копией отправленного подтома. .

Если намерение состоит в том, чтобы создать точную копию, путь получения должен быть защищен от доступа пользователей до тех пор, пока операция получения не будет завершена и подтом не будет установлен только для чтения.

Кроме того, в настоящее время метод получения не очень хорошо проверяет, имеет ли смысл добавочный поток отправки, и, таким образом, специально созданный поток отправки может создать подтом с рефссылками на произвольные файлы в той же файловой системе. В связи с этим пользователям рекомендуется не использовать btrfs для получения и отправки потоков из ненадежных источников и защищать доверенные потоки при их отправке по ненадежным сетям.

Также стоит отметить, что можно отключить флаг readonly для подтома, изменить что-то, а затем снова включить его. Если это было сделано с любой стороны, все гарантии выбрасываются в окно.

Обратите внимание, что передача вывода в файл и передача этого файла не обеспечивают какую-либо защиту от вышеуказанного. Лично я не вижу абсолютно никаких причин, по которым было бы небезопасно передавать вывод btrfs send напрямую в ssh. Преимущество промежуточного хранения потока в файлах заключается в том, что это позволяет возобновить прерванную передачу при ненадежном соединении, но не дает никаких гарантий целостности данных.

Хороший (хотя и не надежный) способ проверить соответствие полученного моментального снимка отправленному — использовать rsync -avcn --del path/to/sent/snapshot/ user@remote:path/to/received/snapshot/.

5
mbloms 3 Июн 2021 в 12:15
Таким образом, кажется, что не существует собственного решения для btrfs, но rsync -avcn --del достаточно хорошо справляется со своей задачей, поскольку сравнивает файлы по содержимому (контрольной сумме). Ваше здоровье!
 – 
Greendrake
26 Авг 2021 в 15:14

У меня есть более десяти систем резервного копирования, основанных именно на последней части того, что вы сказали. Прямые каналы никогда не были для меня вариантом, так как я имею дело с резервным копированием по сети размером> 1 ТБ. Не мог рисковать потерять ни единого бита и тратить часы работы.

Моя окончательная установка выглядит следующим образом.

Этап начальной загрузки:

  1. Сделать первый полный снимок
  2. Отправить снимок в локальный файл (опция -f)
  3. Rsync или передача файла моментального снимка на физический носитель на удаленный сайт.
  4. Удаленное получение первого снимка

Пошаговая фаза:

  1. Новый локальный снимок

  2. Локальная генерация и отправка в файл разницы между текущим и последним снимком

  3. Rsync на удаленный сайт

  4. Удаленный импорт переданного файла моментального снимка

  5. Логика очистки (подумайте об удержании, удалите старые снимки...)

Это работает с 3 лет. В худших случаях, когда снимки не совпадают, достаточно удалить последние два (1 локальный, 1 удаленный), чтобы он снова работал при следующей отправке.

Удачи

4
realpclaudio 31 Янв 2020 в 14:12
Большое спасибо за ваш ответ. Кажется, что определенно необходимо использовать другой инструмент (например, rsync) для запуска резервных копий по сети, и мне придется более внимательно изучить, как такие инструменты, как buttersink решают проблему начальной загрузки, не требуя например. 2 ТБ свободного места для переноса подтома объемом 1 ТБ.
 – 
sjy
1 Фев 2020 в 10:31
Я бы сказал, что собственные каналы отправки / получения через ssh возможны только в тихом сегменте локальной сети, ИМХО, как только вы столкнетесь со шлюзом на своем пути, уже достаточно переключиться на передачу на основе файлов;)
 – 
realpclaudio
3 Фев 2020 в 17:24

Гарантирует ли наличие Received UUID, что подтом, созданный btrfs receive, является полной и неизмененной копией подтома с этим UUID в другой файловой системе?

Поле Received UUID устанавливается только после получения подтома. Из исходный код btrfs-progs:

@received_uuid: UUID подтома, из которого этот подтом был получен, или все нули, если этот подтом не был получен. Обратите внимание, что это поле, @stransid, @rtransid, @stime и @rtime устанавливаются вручную пользовательским пространством после получения подтома.

Вы также можете наблюдать это в подробном режиме:

$ btrfs send -v 2020-12-28/ | ssh root@link "btrfs receive -v /mnt/test"
At subvol 2020-12-28/
BTRFS_IOC_SEND returned 0
joining genl thread
At subvol 2020-12-28
receiving subvol 2020-12-28 uuid=778ec7aa-6709-d240-b41d-58d99a6fb9a0, stransid=9
BTRFS_IOC_SET_RECEIVED_SUBVOL uuid=778ec7aa-6709-d240-b41d-58d99a6fb9a0, stransid=9
3
timakro 29 Дек 2020 в 02:22