設定

設定

重要な要約、DRの要約:mdセクタ番号をデバイス内のオフセットに変換して/dev/mdX調査する方法xfs_dbsh->sectorのセクター番号linux/drivers/md/raid5.c:handle_parity_checks5()

printkMD内部を理解していないので、追加したロギングの出力をどのように処理するのかわかりません。

コンポーネントデバイス(dd16進エディタ/ビューア用)のオフセットも興味深いです。

私はLinux-raidメーリングリストにこの質問を投稿する必要があると思いました。購読者専用ですか、それとも購読しなくても投稿できますか?


私のxfsは、デスクトップ(LVMなし)の4つのディスクのMD RAID 5のすぐ上にあります。最近のクリーンアップでは、ゼロ以外の値mismatch_cnt(mdは一度に4kiBページで実行されるため、実際には8)を検出しました。

RAID1/RAID10ではなくRAID5です。ここでmismatch_cnt!= 0 は通常動作中に発生する可能性があります。。 (追加リンクは下部にありますこのWikiページ一部の人には便利かもしれません。 )

盲目的にこれを行うことはできますが、repair再構築する方法を選択する機会を失うことに加えて、どのファイルが破損しているかを確認する必要があるかどうかはわかりません。 同様の質問に対するFrostschutzの答えこれがファイルシステムの違いを追跡するために私が見つけた唯一の提案です。面倒で遅いので、むしろより良いものを使用して最初にいくつかのファイルに絞り込むことをお勧めします。


カーネルパッチにロギングが追加されました。

奇妙なことは、mdの確認機能は、エラーが見つかった場所を報告しません。printkmd/raid5.c にsh->sector増分ロギングのためのif分岐を追加しました。mddev->resync_mismatcheshandle_parity_checks5()(小さなパッチgithubに投稿、元のkernel.orgの4.5-rc4に基づいています。 )一般的な目的で使用できるようにするには、修正で大きな不一致が原因でログがあふれないようにする必要があります(おそらく新しいresync_mismatches値が<1000の場合にのみログを記録しますか?)。check代わりにforを記録することも可能ですrepair

同じ関数がセクタ番号を印刷するので、有用な情報を記録していると確信しています(MDの内部がわからない場合でも!)。エラー処理の場合switch

修正されたカーネルをコンパイルして起動し、チェックをやり直しました。

[  399.957203] md: data-check of RAID array md125
...
[  399.957215] md: using 128k window, over a total of 2441757696k.
...
[21369.258985] md/raid:md125: check found mismatch at sector 4294708224    <-- custom log message
[25667.351869] md: md125: data-check done.

今、そのセクター番号で何をすべきかわかりません。そこにsh->sector * 512線形アドレス/dev/md/t-r5(別名)がありますか?/dev/md125各構成デバイス内のセクタ番号ですか(したがって、3つのデータセクタと1つのパリティセクタを表します)?私の推測は後者です。 RAID5 のパリティの不一致は、md デバイスの N-1 セクタがストライプ単位で互いにオフセットされ、危険にさらされていることを意味するためです。セクタ 0 はコンポーネントデバイスの先頭、それともスーパーブロックの後のセクタですか、それとも別のセクタですか?handle_parity_checks5()より多くの情報を計算/記録する必要がありますか?

一致しないチャンクだけを取得したい場合、これは正しいですか?

dd if=/dev/sda6 of=mmblock.0 bs=512 count=8 skip=4294708224
dd if=/dev/sdb6 of=mmblock.1 bs=512 count=8 skip=4294708224
dd if=/dev/sda6 of=mmblock.2 bs=512 count=8 skip=4294708224
dd if=/dev/sdd  of=mmblock.3 bs=512 count=8 skip=4294708224  ## not a typo: my 4th component is a smaller full-disk

# i.e.
sec_block() { for dev in {a,b,c}6 d; do dd if=/dev/sd"$dev" of="sec$1.$dev"  skip="$1"  bs=512 count=8;done; }; sec_block 123456

4つのレイドコンポーネントすべてで4,000個のゼロを取得したため、そうではありません0^0 == 0。これは正しいパリティでなければなりません。そうですか?

sync_minmdでセクタアドレスを使用することは、他の場所で言及したものを見sync_maxました(sysfsで)。Neil Brownはlinux-raidのリストにあります。、セクタ番号のソースである故障したドライブについての質問では、hdrecoverニールはディスク全体のセクタ番号をMDセクタ番号として使用しました。これは合っていませんか? mdセクタ番号は、パーティションが属するデバイス全体ではなく、コンポーネントデバイス(この場合はパーティション)に基づいていませんか?


線形セクタをXFSファイル名として:

mdセクタ番号がおそらくRAIDデバイスではなくコンポーネントのものであることに気づく前に、読み取り専用モードで試してみましたxfs_db

Dave Chinnerの非常に簡単なアドバイスXFSが特定のブロックをどのように使用するかを理解する方法については、私にはまったく機能しないようです。 (一部のセクタでは確実な結果を期待しています。不一致セクタでなくても、数字がデバイスの端を越えてはならないからです。)

# xfs_db -r /dev/md/t-r5 
xfs_db> convert daddr 4294708224 fsblock
0x29ad5e00 (699227648)
xfs_db> blockget -nv -b 699227648
xfs_db> blockuse -n       # with or without -c 8
must run blockget first

まあ?私がここで何を間違っているのか?これは別の質問になるはずです。このセクションの回答を他の場所で尋ねるか見つけた場合は、リンクに置き換えます。

私のRAID5は、デフォルトでは書き込みアクティビティがなく、読み取りが最小化されたアイドル状態です(noatimeしたがって、読み取りは書き込みを生成しません)。


私の設定に関する追加情報、ここでは重要ではありません。

私のファイルの多くはビデオまたは他の圧縮データであり、データが正しいかどうか(ファイル形式の内部チェックサムまたはデコードにエラーがないか)知るための効率的な方法を提供します。それからこの読み取り専用ループバック方法確認する必要があるファイルがわかったら動作します。ただし、カーネルが確認して簡単に記録するために必要な情報がある場合に不一致を見つけるために、ファイルシステム内のすべてのファイルに対して最初に4方向diffを実行したくありません。


私の/proc/mdstat一括データ配列:

md125 : active raid5 sdd[3] sda6[0] sdb6[1] sdc6[4]
      7325273088 blocks super 1.2 level 5, 512k chunk, algorithm 2 [4/4] [UUUU]
      bitmap: 0/19 pages [0KB], 65536KB chunk

東芝3TBドライブの3つのパーティションにあり、未パーティションのWD25EZRS環境に優しい電源(低速)ドライブを別の東芝ドライブと交換しました。 (使用mdadm --replace重複した空白なしでオンラインで完了します。コピーした後、問題を探す前後にRAIDの状態を確認する必要があることに気づきました。それから私は矛盾を見つけました。約1年前にクラッシュが発生しましたが、古いログがなく、mdadmはデフォルトでこれに電子メールを送信しないようです(Ubuntu 15.10)。

私の他のファイルシステムは、3つの大きなHD(/ var / tmpのRAID0と一緒に)の古いパーティションで構成されたRAID10f2デバイスにあります。 RAID5は、/homeORではなく大容量記憶域にのみ使用されます/

私のドライブでは、すべてが正常です。すべての不良ブロックカウンタは、すべてのドライブでSMARTエラー数が0で、短期+長期SMARTセルフテストに合格しました。


この質問はほとんど重複していますが、答えはありません。

ベストアンサー1

長い話を短くsh->セクタは、データセグメントの開始後の物理ディスクのセクタ数です。


設定

説明するための簡単なテスト設定は次のとおりです。

  • /dev/raidme/rd[0-3], 2GB デバイス
  • / dev / md127はこの5つでraid5として生成され、xfsで初期化され、任意のデータで埋められます。

始めるには、ゼロ以外のブロックをインポートして上書きします。

# dd if=/dev/raidme/rd0 bs=1k count=1 skip=10240 | hexdump -C | head
...
# dd if=/dev/zero of=/dev/raidme/rd0 bs=1k count=1 seek=10240
...
# dd if=/dev/raidme/rd2 bs=1k count=1 skip=10240 | hexdump  -C | head
1024 bytes (1.0 kB, 1.0 KiB) copied, 8.6021e-05 s, 11.9 MB/s
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000400

アレイを停止/再構成してdm / mdキャッシュをフラッシュし、次の点を確認します。

# mdadm --stop /dev/md127
# mdadm --assemble /dev/md127 /dev/raidme/rd*
# echo check > /sys/class/block/md127/md/sync_action
# dmesg | tail
...
[ 1188.057900] md/raid:md127: check found mismatch at sector 16384

ディスクのブロック

さて、まず16384が私たちが書いたものと一致することを確認してみましょう。私の攻撃には512kストライプがあるので、簡単に一致させるためにいくつかのソート項目を作成したことを確認し1024*10240ました0xa00000

パッチは情報を提供します16384。 1つの注目すべき点は、データがゼロから始まらないことです。

# mdadm -E /dev/raidme/rd0 | grep "Data Offset"
    Data Offset : 4096 sectors

それだけprintf "%x\n" $(((4096+16384)*512))です0xa00000。いいね


mdのブロック

今md側の位置を取得するのは実際には簡単です。セクタ時間で指定された位置にすぎませんnumber_of_stripes。たとえば、私の場合は4つのディスク(3 + 1)があるため、3つのストライプがあります。

ここでは16384*3*512次のことを0x1800000意味します。ディスクがうまくいったので、ディスクを読んで1,000個のゼロを見つけるだけで簡単に確認できます。

# dd if=/dev/md127 bs=1M | hexdump -C | grep -C 3 '00 00 00 00 00 00'
... some false positives...
01800000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
01800400  6b a8 9e e0 ad 88 a8 de  dd 2e 68 00 d8 7a a3 52  |k.........h..z.R|

xfsのブロック

クール。それでは、xfsの位置を見てみましょう。16384*3はい49152(daddrはセクタ番号を使用しています):

# xfs_db -r /dev/md127
xfs_db> blockget -n
xfs_db> daddr 49152
xfs_db> blockuse -n
block 6144 (0/6144) type data inode 2052 d.1/f.1

ファイルに0があることは間違いありません。

# dd if=/mnt/d.1/f.1 bs=1M | hexdump -C | grep -C 3 '00 00 00 00 00'
...
03680000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
03680400  6b a8 9e e0 ad 88 a8 de  dd 2e 68 00 d8 7a a3 52  |k.........h..z.R|

そのファイルを上書きすると、/dev/raidme/rd0の正しいオフセットのゼロも消えます(他のファイルに追加するだけです)。 /dev/raidme/rd0に書き換えると(配列を再び停止/開始する必要があります)、0が再び表示されます。よさそうだね

しかし、1つの問題は、ストライプサイズが私のもの(512k)ほど大きい場合、処理する単一のブロックがなく、可能なデータの1.5MBだけが破損することです。通常、これは単一のファイルに表示されますが、確認するにはxfs_dbに戻る必要があります。以前のinodeは2052だったことを覚えておいてください。

xfs_db> inode 2052
xfs_db> bmap
data offset 0 startblock 256 (0/256) count 17536 flag 0
data offset 17536 startblock 122880 (0/122880) count 4992 flag 0
data offset 22528 startblock 91136 (0/91136) count 3072 flag 0

ここでブロックサイズは4096バイト(参考資料参照xfs_info)なので、1.5MBは384ブロックです。破損したセグメントは、ファイルの最初のセグメント内のブロック6144〜6528です。

注目すべき他の点は、手動でチャンクを抽出し、チェックサムが一致しない場所を正確にチェックすることです。これで、3つの小さなチャンクを見ることができます。


最後に、パッチに関しては私はmd開発者ではありませんが、古いmdadm raid5ユーザーとして非常に興味があります。確かに努力する価値があると言いたいです。あなたが言及したクリーンアップは役に立つかもしれません。パッチを提出すると、開発者はいくつかのコメントを提示することを確信しています。しかし、MDはこれらのバグについてより詳細に説明する必要があります!

おすすめ記事