web-dev-qa-db-ja.com

Btrfsに1つのファイルのチェックサムを検証させる方法は?

Btrfsは、データの整合性/チェックサムを検証するために次のコマンドを提供します。

btrfs scrub start <path>|<device>
btrfs check --check-data-csum

ただし、AFAIKは常に検証しますwhole filesystems; path引数は、ファイルシステム内のファイル/ディレクトリではなく、デバイス上のファイルシステムを識別するためのものです。

これで、3TBのBtrfsファイルシステムができました。スクラブには数時間かかります。 * .isoインストールイメージを使用したり、バックアップを復元したりする前に、特定のファイル/ディレクトリのみがまだビットロットの影響を受けていないことを確認する必要がある場合があります。 これにBtrfsを使用するにはどうすればよいですか —各ファイルごとに手動ハッシュファイルを保持することにフォールバックせずに?

Btrfsは個々のファイルのチェックサムを保存しないことを知っています—データのブロックのチェックサムを保存します。この場合、私が探しているのは、特定のファイル/ディレクトリの保存に使用されるすべてのブロックを識別し、それらのブロックのみを検証するコマンド/ツールです。

Btrfsがチェックサムを検証していると言われているところをどこかで読みました読み取り時。つまり、ファイルがビット腐敗している場合、そのファイルの読み取りは失敗するか、そのようなものになります。これは本当ですか?

5
Greendrake

答えは次のとおりです。単純にファイル全体を読み取ってみてください。チェックサムされたものと異なって読み取られる場合、入力/出力エラーが発生します。そうです、Btrfsは確かに読み取り時にチェックサムを検証します!

この答えを見つけるために、私は次のテストをまとめました。

  1. Btrfsパーティションをテストするためのブロックデバイスとして使用する1Gbファイルを割り当て、ループデバイスとしてマウントし、Btrfsをフォーマットします。
  2. 真ん中に既知の一意のバイトシーケンスを含むダミーの800Mbファイルを作成します(token1);
  3. ファイルをBtrfsに書き込み、後で参照できるようにそのsha256を記録します。
  4. ブロックデバイスファイルをアンマウントしてパッチを適用し、1バイトが変更されるようにします。このために、sed-token1token2に置き換えます。
  5. 再度マウントして、Btrfsで800Mbファイルのsha256を取得してみてください。入出力エラーを参照してください。
  6. アンマウント、パッチバック、マウントして、800 Mbファイルが再び読み取り可能であり、sha256がステップ3と同じであることを確認します。
  7. 利益!

スクリプトは次のとおりです。

#!/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は破損していないものとは異なります。

6
Greendrake