指定ブロックがどのファイルに属するか調べる

提供: ArchWiki
2016年1月13日 (水) 23:32時点におけるAosho235 (トーク | 投稿記録)による版 (英語版よりコピペ。一部翻訳)
(差分) ← 古い版 | 最新版 (差分) | 新しい版 → (差分)
ナビゲーションに移動 検索に移動


この記事では、ディスク上の指定のブロックがどのファイルに属するか調べる方法を説明します。主な目的は、ストレージに破損ブロックが生じたときに、どのファイルが破損したかを調べることです(そして重要なデータが失われたかどうかを確認できます)。

この記事の中のほとんどのコマンドを実行するには、root か、ディスクに直接読み込みアクセスができるユーザーになる必要があります(disk グループのメンバーであれば十分です)。いつもの通り、現在のバックアップを取っておくとよいでしょう。もうすぐディスクが壊れそうな場合は特にそうです。壊れそうかどうかを調べるには S.M.A.R.T. が役に立ちます。

今のところ、この記事は JFS と EXT ファイルシステムだけに向けて書かれています。

破損ブロックを見つける

badblocks コマンドを使います。このコマンドにはいくつかのスキャンモードがあります。リードオンリーモード(デフォルト)は正確さが一番低くなります。破壊的書き込みモード(-w オプション)は最も正確ですが、より時間がかかり、(当然ながら)ディスク上の全データを破壊します。ですのでこれはブロックが属するファイルを見つけるのには使えません。そして最後に非破壊的読み書きモードがあります。これはおそらく破壊的モードと同じくらい正確で、唯一のデメリットはおそらく一番遅いことです。しかし、ディスクが壊れつつあるとわかっているときは、リードオンリーモードが一番安全でしょう。

To do a verbose (-v option), read-only scan, run one of these commands (with x being the drive letter and y being partition number you want to scan):

ディスク全体をスキャンする:

badblocks -v /dev/sdx

1個のパーティションをスキャンする:

badblocks -v /dev/sdxy

The downside to scanning the drive as a whole is that each filesystem is going to start its block count relative to the partition it's on. This means that if you have a bad block that happens to be on, let's say, the second partition, and that partition starts on block 1000, then you will have to subtract 1000 from your block number in order to get the number you want. So if a scan from the beginning of the disk results in block number 1005 being bad, then block 5 of the second partition is what you'll actually be using.

Otherwise, if you've found bad blocks after doing a full scan, you can simply figure out which partitions they're on, and rescan those in order to get the block number, rather than do any block math.

もう一つ覚えておきべきなのは、badblocks はデフォルトでは 1024 バイトを 1 ブロックとすることです。そのため、-b オプションでブロックサイズを変更してファイルシステムのブロックサイズに一致させるか、後の手順において手計算でブロック番号する必要があります。

パーティションの開始・終了位置を調べるには fdisk を使います(古いバージョンではデフォルトでシリンダー単位になるかもしれません。その場合は -u オプションでセクタ単位に変更できます)。fdisk で表示されるブロックサイズをメモしておいて、後でブロック数を変換できるようしておいてください。


fdisk -l /dev/sdx
255 heads, 63 sectors/track, 19457 cylinders, total 312581808 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00000000

これによって、破損ブロックのブロック番号(そのパーティションの開始位置からの相対位置)が分かりました。

ファイルシステムをデバッグする (JFS)

jfs_debugfs will give you access to all the low level structures within any JFS filesystem. Other filesystems such as the EXT filesystems have similar tools. It is probably a good idea to umount any filesystem before you run this on them. To use it just run:

jfs_debugfs /dev/sdxy

This puts you into a command console. The first thing you should note is your aggregate block size. This is (presumably) the block size the filesystem is using. JFS seems to default to 4096 bytes.

If you did not run badblocks using the block size that your filesystem is using then you will need to convert your block number(s) to match it (remember to use the block number(s) relative to the partition they're on).

i.e. block number 100 with a block size of 1024 bytes becomes block number 25 at 4096 bytes. The formula is:

(original block number) / ((filesystem block size) / (badblocks block size))

Now the entire point of running this program (for the purpose of this article) is to get the inode number. To do this run the command:

d blocknumber 0 i

The syntax is the d command for display, the block number, the offset (just set it to 0), and the display format i for inode.

Note: If you get an error then that means the block is not allocated and is being used as free space. In that case this is a good thing as it means nothing important was damaged.

The decimal number that di_number is set to is the one we want. From here you type x to exit out of the display mode. Repeat the display command for each bad block that you have and note all of their inode numbers. For more info on the inode such as permissions and filetype type:

i inodenumber

When you have all the inode numbers type q to quit.

破損ファイルを見つける (JFS/Universal)

これでようやく破損ファイルを見つけられます。GNU find ユーティリティを使います。ファイルシステムをマウントして次を実行します:

find / -inum inodenumber

"/" はその inode が属するファイルシステムのマウントポイントで置き換えてください。 / を検索して 2 個以上のファイルシステムがマウントされていたら(普通はそうなっているでしょう)、異なるファイルシステム上で同じ inode 番号のファイルが複数見つかるでしょう。そしてその場合は明らかに時間が長くかかります。inode はファイルシステムの中でだけユニークなことに注意してください。

ファイルシステムをデバッグする (EXT(2/3/4))

tune2fs will give you access to all the low level structures within any EXT filesystem. It is probably a good idea to umount any filesystem before you run this on them.

最初にやることは、ファイルシステムのブロックサイズを取得することです。これを実行します:

tune2fs -l /dev/sdxy | grep Block
Block count:              29119820
Block size:               4096

この場合は 4096 がブロックサイズです(これがデフォルトのようです)。

badblocks を実行したときのブロックサイズがこのファイルシステムのブロックサイズと一致していなかった場合は、ブロック番号を変換する必要があります(パーティションの開始位置からの相対ブロック番号を使うことに注意してください)。

つまり、ブロックサイズが 1024 バイトの場合のブロック番号 100 は、ブロックサイズが 4096 バイトの場合のブロック番号 25 になります。変換公式は:

(original block number) / ((filesystem block size) / (badblocks block size))

さて、本来の目的は inode 番号を取得することです。このコマンドを実行してください:

debugfs

そして debugfs のコンソールにおいて、破損セクタを含んでいる EXT のパーティションを引数に open コマンドを実行します:

debugfs:  open /dev/sdxy

最後に testb コマンドを実行してそのブロックに関する情報を取得します(この例ではブロック 1000 番):

debugfs:  testb ブロック番号


Note: ブロックが使用中でないと表示される場合は、そのブロックが割り当てられておらず、空きスペースになっていることを意味します。これは、何も重要なデータが失われていないということなので良いことです。

ブロックが使用中なら、このコマンドで inode 番号を取得できます:

icheck ブロック番号

これは 2 個の数字を表示します。ブロック番号と inode 番号です。

破損ファイルを見つける (EXT(2/3/4))

inode 番号(icheck コマンドで表示される 2 番目の番号)を引数に ncheck コマンドを実行します:

ncheck inodenumber

この破損ブロックを使っているファイルのフルパスが表示されます。これで実際に何が破損したのかがわかります。

もし inode 番号が非常に小さくて ncheck がパス表示に失敗する場合は、おそらくジャーナル自体が壊れています。ジャーナルを削除するには、このコマンドをパーティションに対して実行します:

tune2fs -O ^has_journal /dev/sdxy

Run the testb command again from the debugfs console on the bad block and it should be no longer marked as used if it was indeed used by the journal. To build a new journal run:

tune2fs -j /dev/sdxy

強制的に破損ブロックを再配置させる

First you'll want to see how many badblocks the harddrive is aware of through the smartctl command:

smartctl -t long /dev/sdx  [wait until test completes, then]
smartctl -l selftest /dev/sdx
 ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
5 Reallocated_Sector_Ct     0x0033   100   100   005    Pre-fail  Always       -       0
196 Reallocated_Event_Count 0x0032   100   100   000    Old_age   Always       -       0
197 Current_Pending_Sector  0x0022   100   100   000    Old_age   Always       -       0
198 Offline_Uncorrectable   0x0008   100   100   000    Old_age   Offline      -       0


To make the harddrive transparently map out the badblock with a spare good sector you will have to simply write zeros to the bad block using the dd command as root. Remember that with this command you have to work with the same block size as your filesystem and the block as to be relative to the partition the filesystem is on and NOT the harddrive as a whole:

dd if=/dev/zero of=/dev/sdxy bs=4096 count=1 seek=2269012
sync

You can see if the harddrive did indeed map out an additional bad sector by checking with the smartctl command and seeing if the reallocated sector or event count went up:

smartctl -A /dev/sdx
ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
5 Reallocated_Sector_Ct     0x0033   100   100   005    Pre-fail  Always       -       1
196 Reallocated_Event_Count 0x0032   100   100   000    Old_age   Always       -       1
197 Current_Pending_Sector  0x0022   100   100   000    Old_age   Always       -       0
198 Offline_Uncorrectable   0x0008   100   100   000    Old_age   Offline      -       1

To get Offline_Uncorrectable to go back to 0 you need to run a SMART long test and a selftest:

smartctl -t long /dev/sdx  [wait until test completes, then]
smartctl -l selftest /dev/sdx

参考

EXT2/3 badblocks howto