BTRFS. Чексумминг
Транскрипт видео
Файлы для теста
Файловые системы – это то, о чём обычно не задумываешься. Работают себе и пусть. Но, время от времени, хочется понять. Данные, вообще-то в целости? Резко вырубили свет? Нестабильная оперативка? Кашляет жёсткий диск? Всё это может повредить данные. Как убедиться, что битики в файлах действительно верные?
В этом видео проведём небольшой эксперимент, где сравним, как ведёт себя ext4 и btrfs в случае, когда по каким-то причинам данные на диске “испортились”. Ext4 и btrfs я взял как пример двух типов файловых систем – более традиционной и более прогрессивной. Будем смотреть только на чистые ФС без дополнительных инструментов и настроек. В самой простой конфигурации по умолчанию.
Сразу оговорюсь – читать btrfs можно по-разному. Butterfs, Betterfs, BTRFS, это не играет большого значения. Я буду говорить ButterFS.
Для примера возьму вот эту фотографию моего кота, которую сделал сам много лет назад. Она имеет для меня сентиментальную ценность и я очень не хотел бы потерять её.
Итак, у нас есть файл. Как можно в будущем понять, что он цел, а не побит и не испорчен? Один из методов, который можно применить – это традиционный чексумминг.
Для начала, откроем терминал и освежим память по базовым командам. Будем пользоваться MD5 чексуммами. Для получения такой чексуммы вводим команду md5sum photo.jpg и выводим результат в файл photo.md5sum. Полученный результат посмотрим с помощью cat. Вот он, чексумма и файл, для которого она была получена. Для проверки целостность файла в будущем, пользуемся md5sum с флагом -c, т.е. check. Ну вот, получаем OK, значит файл в порядке.
Вносим ошибки
Теперь, внесём ошибку в файл. Для этого копируем photo.jpg в photo-bad.jpg. Затем, открываем photo-bad в hexedit. Мы будем намеренно повреждать ТЕСТОВЫЙ файл. Не делайте этого с важными данными. Прокручиваем файл где-то до 50%. Заменяем первые попавшиеся значения на FF. Сохраняем на F2 и выходим на CTRL+C.
Для полноты картины сделаем md5sum для “повреждённого” файла. И, теперь, посредством cat, сравниваем чексуммы. Обратите внимание, значения разные. Именно так в будущем и можно понять – файл повреждён.
Некоторые программы, даже при повреждениях, могут всё-равно обрабатывать файл. Вот как это выглядит для нашей повреждённой фотографии. Серая часть снизу не была обработана Gwenview.
Делаем раздел с ext4
С чексуммами разобрались. Теперь к ФС. Сделаем раздел с ext4. Создавать настоящие разделы нет никакого смысла, достаточно будет смонтировать файлы как блочные устройства. Проще говоря, заставим систему воспринимать файлы как диски.
Делаем truncate с размером в 128 мегабайт. Так выделим пустой файл ext4.img с известным размером. Вот, файл появился. Примонтируем его как устройство в систему с помощью udisksctl loop-setup -f. Проверяем дополнительно с помощью lsblk, да, устройство появилось.
Хорошая практика: на диске разметить хотя бы один раздел. Для этого пользуемся cfdisk для loop0. Оставляем разметку gpt, выбираем New, оставляем размер по-умолчанию, 127M, это максимальный. Выбираем Write для записи изменений, подтверждая словом yes и выбираем Quit для выхода.
lsblk с флагом -f покажет нам разделы с информацией об ФС. Новый раздел loop0p1 появился, но его нужно отформатировать. Для ext4 форматируем с помощью mkfs.ext4, опция -L нужна для названия. Проверяем ещё раз ФС. Вот, всё точно отформатировано.
Осталось только смонтировать раздел ext4. udisksctl mount с опцией -b справится с этим. Копируем на диск исходное, исправное фото и файл md5sum для него. Переходим в точку монтирования и проверяем чексумму. Да, всё в порядке. Для пущей уверенности, посмотрим визуально на фото. Милых котэ много не бывает.
Внедряем битый файл
Теперь к интересной части, подмене файла на устройстве. У команды filefrag из пакета e2fsprogs есть флаг -v, он покажет детальные данные о расположении файла. Зная параметры размера блока и физического смещения, мы можем на место photo.jpg записать “повреждённый” файл photo-bad.jpg с помощью dd.
Особо отмечу, что dd может привести к потере данных, если ему передать неверные параметры, БУДЬТЕ ВНИМАТЕЛЬНЫ. Проверим параметры. if – это photo-bad.jpg, of – это /dev/loop0p1, bs – размер блока, 1024, seek устанавливаем как значение физического смещения, 114817.
Файл photo.jpg на разделе ext4 уже открывался и может находиться в кэше системы. Команда sync синхронизирует изменения на дисках, а echo 1 в /proc/sys/vm/drop_caches сбросит кэши.
Проверяем результат
Открываем файл photo.jpg. Ну вот, он битый. Вернёмся в терминал и попробуем проверить MD5. Ммм… Ошибка. md5sum пишет, что чексумма не сошлась. А есть ли что-то в системных логах по поводу ошибки? journalctl же должен показать что-то с уровнем выше warning за последние, скажем, 3 минуты? Нет! Пусто!
Собственно, в этом и заключается проблема более традиционных ФС типа ext4. Они просто не знают, какие данные должны быть в файле и не смогут подсказать, битый он или нет.
Ответственность за обработку проблемных ситуаций ложится на программу, которая работает с файлом. Именно программа должна выбирать, что делать в случае ошибки. Как мы уже видели, Gwenview просто покажет то, что можно… Половину фото.
Делаем раздел с btrfs
Теперь сделаем раздел с btrfs. Процесс будет практически такой же, что использовали для ext4. Разница только в именах и том, что вместо mkfs.ext4 будем использовать mkfs.btrfs.
Делаем те же шаги. truncate, loop-setup, cfdisk, mkfs.btrfs, mount, копируем файлы photo.jpg и MD5-сумму на новый раздел, проверяем чексумму, она в порядке. Делаем визуальную проверку. Всё окей.
Внедряем битый файл
Достаём данные из filefrag и подменяем файл с помощью dd. Перепроверяем параметры для dd! if – photo-bad.jpg, of – /dev/loop1p1, размер блока и смещение другое, ведь ФС другая и хранит данные иначе. bs – 4096 seek – 3328. После подмены не забываем сбросить кэши.
Проверяем результат
Проверяем визуально файл. Хоть немножко по-другому, но он всё же битый.
Проверяем чексумму. И вот… Уже видна разница. Система вернула ошибку ввода-вывода, а md5sum говорит, что не смог считать файл. Очень интересно. А что в логах? Мда, вот и ошибка. В отличие от ext4, который просто отдал данные как есть, btrfs обнаружил повреждение и зарегистрировал ошибку. Главное, что мы не просто видим ошибку, но и сможем потом найти её в системных журналах
Таким образом, btrfs снимает с пользователя необходимость ручной проверки целостности файлов. Эта файловая система самостоятельно хранит чексуммы для кусочков данных и нам заниматься этим уже не нужно. При считывании файла, в случае несоответствия чексумм, ФС явно сигналирует об ошибке, как мы и увидели.
Скраббинг и статистика
Тут появляется логичный вопрос – мы получили эту ошибку только при доступе к файлу. Как удостоверится, что ВСЕ файлы в порядке? Нам что, открывать каждый?
К счастью, у btrfs есть набор утилит командной строки в пакете btrfs-progs. Одна из утилит там – btrfs scrub. Она умеет делать т.н. “скраббинг”. Процесс проверки, насколько данные в ФС в порядке, ну, или… Подскажет, какие конкретно есть проблемы.
Чтобы начать скраббинг, пользуемся btrfs scrub start и даём путь до точки монтирования. Да, инструменты btrfs оперируют именно путями, а не устройствами. В данном случае точка монтирования находится в example-btrfs.
Раздел очень маленький, всего на 2 файла, можем сразу посмотреть результат с помощью btrfs scrub status. Здесь есть полезная информация, как: время начала процедуры, статус, сколько всего времени занял скраббинг, общий объём данных, скорость обработки… И, конечно, ошибки. Здесь, например, видим одну ошибку чексуммы, которую невозможно восстановить, это тот самый кусочек файла photo.jpg, который мы повредили.
Иногда скраббинг может быть долгим, а Вы просто хотите удостоверится, что в последнее время никаких ошибок не было. Для этого используем команду btrfs device stats. Эта команда показывает количество ошибок записи, чтения, ошибок сброса данных на диск, повреждения данных и ошибок с порядком записи. И вот, тут уже не одна ошибка.
scrub status показывает результаты только для последнего запуска btrfs scrub. Битый кусок данных один, поэтому и ошибка одна. device stats показывает общий счётчик ошибок, аккумулятор, сколько раз ошибка замечена с течением времени, столько и отображается.
Пока записывал видео, неоднократно открывал битое фото и пару раз запускал scrub, вот и набежало 11 ошибок.
Ещё одна интересная особенность: если заглянуть в логи, то scrub оставляет несколько иные записи. Там есть указание пути к файлу, что значительно удобнее, чем только информация об inode.
Ищем путь по inode
Но, найти имя файла можно и по значению inode. Для этого используем btrfs inspect-internal inode-resolve, номер inode и путь к точке монтирования. Вот, так путь понятнее, чем просто цифры.
Резюмируя, мы посмотрели на то, как ведут себя ext4 и btrfs при работе с битыми файлами. Ext4 в стандартной конфигурации просто отдаёт файлы клиентским программам как есть. Btrfs же следит за целостностью, и если заметит проблему, то возвращает ошибку ввода-вывода. Кроме этого, мы посмотрели на доступные инструменты btrfs для проверки целостности данных, аналогов которым в чистой ext4 просто нет.
На мой взгляд, все эти особенности делают btrfs более подходящим выбором для хранения важных данных. Как, например, моего фото котэ.
Ну что, на этом всё. Спасибо вам за внимание!
Журнал изменений
13 июня 2025 г.: добавил транскрипт видео.