Как заставить Btrfs проверить контрольную сумму для одного файла?
Btrfs предлагает эти команды для проверки целостности данных / контрольных сумм:
btrfs scrub start <path>|<device>
btrfs check --check-data-csum
Однако AFAIK всегда проверяет целые файловые системы; path
Аргумент должен идентифицировать файловую систему на устройстве, а не файл / каталог в файловой системе.
Теперь у меня есть файловая система Btrfs объемом 3 ТБ. Очистка занимает несколько часов. Иногда мне нужно убедиться, что bitrot еще не затронул только определенный файл / каталог, например, перед использованием установочного образа *.iso или восстановлением резервной копии. Как мне использовать Btrfs для этого - не прибегая к хранению хеш-файлов вручную для каждого файла?
Мне известно, что Btrfs не хранит контрольные суммы для отдельных файлов - он хранит контрольные суммы для блоков данных. В этом случае я ищу команду / инструмент, который идентифицирует все блоки, используемые для хранения определенных файлов / каталогов, и проверяет только эти блоки.
Я где-то читал, что Btrfs якобы проверяет контрольные суммы на чтение. То есть, если файл был бит-гнилой, чтение его не удастся или что-то в этом роде. Это тот случай?
1 ответ
Ответ: просто попробуйте прочитать весь файл. Если он читается не так, как было проверено, будет ошибка ввода / вывода. Так что да, Btrfs действительно проверяет контрольные суммы на чтение!
Чтобы узнать этот ответ, я собрал следующий тест:
- Выделите файл размером 1 Гб для использования в качестве блочного устройства для тестирования раздела Btrfs, смонтируйте его как устройство петли и отформатируйте на нем Btrfs;
- Создайте фиктивный файл 800 Мб, содержащий известную уникальную последовательность байтов в середине (
token1
); - Запишите файл в Btrfs и запишите его sha256 для дальнейшего использования;
- Размонтируйте и исправьте файл блочного устройства, чтобы изменить один байт. Для этого мы
sed
-replacetoken1
сtoken2
; - Смонтируйте снова и попробуйте получить sha256 из файла 800 Мб на Btrfs. См. Ошибка ввода / вывода;
- Размонтируйте, исправьте, смонтируйте и убедитесь, что файл 800 Мбайт снова доступен для чтения, и sha256 такой же, как на шаге 3;
- Прибыль!
Вот сценарий:
#!/bin/bash
f="btrfstestblockdevicefile"
ft="btrfstestfile"
loop="/dev/loop0"
mount_dir="btrfstestdir"
size="1g"
token1="36bbf48aa6645646fbaa7f25b64224fb3399ad40bc706c79bb8276096e3c9e8f"
token2="36bbf48aa6645646fbaa7f25b64224fb4399ad40bc706c79bb8276096e3c9e8f"
f_mount() {
echo "Mounting..." && \
sudo losetup $loop $f && \
if ! [[ -z $1 ]] ; then
sudo mkfs.btrfs -q $loop
fi
mkdir $mount_dir && \
sudo mount $loop $mount_dir
}
f_umount() {
echo "Unmounting..." && \
sudo umount $loop && \
sudo rmdir $mount_dir && \
sudo losetup -d $loop
}
echo "Allocating file for test block device..." && \
fallocate -l $size $f && \
f_mount 1 && \
echo "Generating test file..." && \
dd if=/dev/urandom of="${ft}1" bs=1M count=400 status=none && \
echo $token1 > "${ft}2" && \
dd if=/dev/urandom of="${ft}3" bs=1M count=400 status=none && \
sudo sh -c "cat ${ft}1 ${ft}2 ${ft}3 > ${mount_dir}/${ft}" && \
rm "${ft}1" "${ft}2" "${ft}3" && \
echo "Calculating original hash of the file..." && \
sha256sum "${mount_dir}/${ft}" && \
f_umount && \
echo "Patching the file in the block device file..." && \
sed -i "s/${token1}/${token2}/g" $f && sync && \
f_mount && \
echo "Trying to read the file..." && \
sha256sum "${mount_dir}/${ft}"
echo "OK, unmount, patch back and try again..." && \
f_umount && \
sed -i "s/${token2}/${token1}/g" $f && sync && \
f_mount && \
sha256sum "${mount_dir}/${ft}" && \
echo "Yay, Btrfs rules! Cleaning up..." && \
f_umount && \
rm $f && \
echo "All clear!"
Как и ожидалось, замена mkfs.btrfs
с созданием файловой системы без контрольной суммы (например, mkfs.ext4
) позволяет читать поврежденный файл. Конечно, его sha256 отличается от не испорченного.