Вопрос или проблема
Я испытываю очень странную проблему с “send” в Btrfs с файловыми ссылками, и после множества попыток я нашел некоторые детали:
Сначала я создал подтом “1”:
btrfs subvolume create 1
и записал в него файл:
dd if=/dev/urandom of=1/a bs=64 count=3110017
Теперь создаем снимок только для чтения с помощью sudo btrfs subvolume snapshot -r 1 1_ro0
, а затем выполняем cp --reflink=always 1/a 1/b
, снова создаем снимок только для чтения: sudo btrfs subvolume snapshot -r 1 1_ro1
. Теперь подсчитаем размер данных с помощью “btrfs send”:
sudo btrfs send -p 1_ro0 1_ro1 | wc -c
Выводит 64864765
, что примерно равно 61.9MiB. Это так аномально – я просто скопировал его с использованием reflink, не понимаю, почему “btrfs send” выводит так много данных.
Однако, если заменить count
в dd
на 3110016
(3110017-1), и снова выполнить указанные выше операции, с wc -c
на “btrfs send”, вы получите 604 (604 Б), всего 604 байта, и это то, чего я ожидал.
Я также написал bash-скрипт для выполнения этих двух тестов:
#!/bin/bash
btrfs subvolume create 1
rm -rf 1/*
dd if=/dev/urandom of=1/a bs=64 count=3110017
sudo btrfs subvolume snapshot -r 1 1_ro0
cp --reflink=always 1/a 1/b
sudo btrfs subvolume snapshot -r 1 1_ro1
sudo btrfs send -p 1_ro0 1_ro1 | wc -c
sudo btrfs subvolume delete 1_ro0 1_ro1
rm -rf 1/*
dd if=/dev/urandom of=1/a bs=64 count=3110016
sudo btrfs subvolume snapshot -r 1 1_ro0
cp --reflink=always 1/a 1/b
sudo btrfs subvolume snapshot -r 1 1_ro1
sudo btrfs send -p 1_ro0 1_ro1 | wc -c
sudo btrfs subvolume delete 1_ro0 1_ro1
rm -r 1
Если заменить wc -c
на btrfs receive --dump
, чтобы исследовать данные вывода “btrfs send”, то при значении dd 3110016
он выведет несколько записей “clone” такого типа:
clone ./1_ro1/b offset=0 len=134217728 from=./1_ro1/a clone_offset=0
clone ./1_ro1/b offset=134217728 len=64823296 from=./1_ro1/a clone_offset=134217728
...
Но при значении dd 3110017 он выведет:
write ./1_ro1/b offset=197918720 len=49152
write ./1_ro1/b offset=197967872 len=49152
write ./1_ro1/b offset=198017024 len=49152
write ./1_ro1/b offset=198066176 len=49152
write ./1_ro1/b offset=198115328 len=49152
write ./1_ro1/b offset=198164480 len=49152
... (намного больше)
которые содержит множество записей “write”.
Я также искал и заметил этот сайт: https://www.spinics.net/lists/linux-btrfs/msg105951.html, и там, похоже, говорится о “дырах” в файлах, но в моем случае это явно не может быть.
Это так странно, и я не знаю, что я упускаю.
Моя версия btrfs-progs
– 5.18.1-1
а параметры монтирования из /proc/mount
: rw,relatime,space_cache=v2,subvolid=5,subvol=/
Спасибо!
Разработчики заметили это и что-то с этим сделали. https://github.com/kdave/btrfs-progs/issues/572
Ответ или решение
Проблема с объемом данных, получаемым при использовании команды btrfs send
, связана с особенностями работы системы файлов Btrfs, особенно в контексте операций с референциями (reflinks) и тем, как они обрабатываются при создании снимков и отправке данных.
Причины высокой суммы данных при btrfs send
-
Отличия в размере данных: Как вы заметили, различие в количестве записанных байтов (
3110017
против3110016
) приводит к заметной разнице в размере данных, отправляемых черезbtrfs send
. Это связано с тем, что при создании файла с размером, кратным определенному порогу, Btrfs может использовать более эффективные методы копирования, такие какclone
, что позволяет избежать дублирования данных. -
Динамика управления данными: Когда вы используете
cp --reflink=always
, и размер файла не соответствует определенному критерию (например, не является кратным размеру блока), это может привести к тому, что Btrfs будет считывать данные из файла более фрагментированными кусками и записывать их в новом месте как обычные записи (write
), а не как ссылки на существующие блоки. Это, в свою очередь, значительно увеличивает объем передаваемых данных. -
Структура данных Btrfs: В Btrfs данные организованы в формате, который оптимизирует использование пространства на диске через снапшоты и референции. Однако существует вероятность, что при использовании различных комбинаций снимков и референций Btrfs может решить, что данные были изменены, и соответственно, передает их как обычный запись вместо использования ссылок.
-
Фрагментация и пробелы: Хотя вы упомянули, что эта ситуация не может быть связана с пробелами, важно учитывать влияние фрагментации файловой системы и как она обрабатывает свободное место. При наличии многих фрагментов данных размер может увеличиться, особенно если они не выравнены по размеру блока.
Рекомендации
-
Использование одного размера блока: Если есть возможность, старайтесь использовать размеры файлов, которые кратны размеру блока вашей файловой системы. Это может помочь уменьшить количество записей
write
и увеличить количество записейclone
при выполненииbtrfs send
. -
Обновление btrfs-progs: Убедитесь, что у вас установлена последняя версия
btrfs-progs
, так как разработчики могут внедрять исправления и улучшения, которые могут повлиять на производительность и поведение системы с точки зрения управления данными. -
Мониторинг и тестирование: Продолжайте тестировать разные подходы к созданию файлов и снимков. Важно понимать, как системные события влияют на ваши результаты, поскольку каждая операция может интерпретироваться Btrfs по-разному в зависимости от конфигурации и состояния файловой системы.
Заключение
Выводы из вашего тестирования показывают, что Btrfs является сложной системой, и ее поведение может варьироваться в зависимости от мелких изменений в данных и их размещении. Изучение особенностей работы этой файловой системы и экспериментирование с параметрами может привести к более предсказуемым и эффективным результатам.