「指定ブロックがどのファイルに属するか調べる」の版間の差分

提供: ArchWiki
ナビゲーションに移動 検索に移動
(カテゴリタグの位置修正、空行の削除)
(内部リンク)
 
(2人の利用者による、間の4版が非表示)
8行目: 8行目:
   
 
==破損ブロックを見つける==
 
==破損ブロックを見つける==
[[badblocks]] コマンドを使います。このコマンドにはいくつかのスキャンモードがあります。リードオンリーモード(デフォルト)は正確さが一番低くなります。破壊的書き込みモード(-w オプション)は最も正確ですが、より時間がかかり、(当然ながら)ディスク上の全データを破壊します。ですのでこれはブロックが属するファイルを見つけるのには使えません。そして最後に非破壊的読み書きモードがあります。これはおそらく破壊的モードと同じくらい正確で、唯一のデメリットはおそらく一番遅いことです。しかし、ディスクが壊れつつあるとわかっているときは、リードオンリーモードが一番安全でしょう。
+
[[badblocks]] コマンドを使います。このコマンドにはいくつかのスキャンモードがあります。リードオンリーモード(デフォルト)は正確さが一番低くなります。破壊的書き込みモード({{ic|-w}} オプション)は最も正確ですが、より時間がかかり、(当然ながら)ディスク上の全データを破壊します。ですのでこれはブロックが属するファイルを見つけるのには使えません。そして最後に非破壊的読み書きモードがあります。これはおそらく破壊的モードと同じくらい正確で、唯一のデメリットはおそらく一番遅いことです。しかし、ディスクが壊れつつあるとわかっているときは、リードオンリーモードが一番安全でしょう。
   
次のいずれかのコマンドを実行し、-v オプション(冗長表示)つきでリードオンリースキャンを実行します(x はディスクを表す文字で、y はパーティション番号です)。
+
次のどちらかのコマンドを実行し、{{ic|-v}} オプション(冗長表示)つきでリードオンリースキャンを実行します({{ic|x}} はディスクを表す文字で、{{ic|y}} はパーティション番号です)。
   
 
ディスク全体をスキャンする:
 
ディスク全体をスキャンする:
badblocks -v /dev/sdx
+
# badblocks -v /dev/sdx
   
 
1個のパーティションをスキャンする:
 
1個のパーティションをスキャンする:
badblocks -v /dev/sdxy
+
# badblocks -v /dev/sdxy
   
  +
ディスク全体をスキャンすると計算が少し面倒になります。各ファイルシステムはパーティションの先頭からブロック番号を数えるため、例えば 2 番目のパーティション上に破損ブロックがあり、そのパーティションがブロック 1000 から始まっていた場合、求めるブロック番号を得るには badblocks が表示するブロック番号から 1000 を引かなければなりません。つまりディスク全体のスキャンでブロック 1005 が破損していると表示された場合、2 番目のパーティションのブロック 5 が求める破損ブロックの番号になります。
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 オプションでブロックサイズを変更してファイルシステムのブロックサイズに一致させるか、後の手順において手計算でブロック番号する必要があります。
+
もう一つ覚えておべきなのは、badblocks はデフォルトでは 1024 バイトを 1 ブロックとすることです。そのため、{{ic|-b}} オプションでブロックサイズを指定してファイルシステムのブロックサイズに一致させるか、後の手順において手計算でブロック番号を変換する必要があります。
   
パーティションの開始・終了位置を調べるには fdisk を使います(古いバージョンではデフォルトでシリンダー単位になるかもしれません。その場合は -u オプションでセクタ単位に変更できます)。fdisk で表示されるブロックサイズをメモしておいて、後でブロック数を変換できるようしておいてください
+
パーティションの開始・終了位置を調べるには [[fdisk]] を使います。
  +
{{Note|古いバージョンではデフォルトでシリンダー単位になるかもしれません。その場合は {{ic|-u}} オプションでセクタ単位に変更できます。}}
  +
fdisk で表示されるブロックサイズをメモしておいて、後でブロック数を変換できるようしておいてください。
   
  +
{{hc|# fdisk -l /dev/sdx|<nowiki>
  +
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</nowiki>}}
   
  +
ここまでで、破損ブロックのブロック番号(そのパーティションの開始位置からの相対位置)が分かりました。
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)==
  +
jfs_debugfs を使うと、[[JFS]] ファイルシステム内の全ての低レベル構造にアクセスできます。EXT など他のファイルシステムでも同じようなツールがあります。これを行う前に全てのファイルシステムをアンマウントしておくとよいでしょう。次を実行します:
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
+
# jfs_debugfs /dev/sdxy
   
  +
このコマンドを実行するとコマンドコンソールに入ります。最初にすべきことは aggregate block size を確認することです。これは(おそらく)ファイルシステムのブロックサイズと同じです。JFSのデフォルトは 4096 バイトのようです。
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.
 
   
 
badblocks を実行したときのブロックサイズがこのファイルシステムのブロックサイズと一致していなかった場合は、ブロック番号を変換する必要があります(パーティションの開始位置からの相対ブロック番号を使うことに注意してください)。
 
badblocks を実行したときのブロックサイズがこのファイルシステムのブロックサイズと一致していなかった場合は、ブロック番号を変換する必要があります(パーティションの開始位置からの相対ブロック番号を使うことに注意してください)。
52行目: 52行目:
 
さて、本来の目的は inode 番号を取得することです。このコマンドを実行してください:
 
さて、本来の目的は inode 番号を取得することです。このコマンドを実行してください:
   
d ''blocknumber'' 0 i
+
d ''ブロック番号'' 0 i
   
 
この構文の意味は、d コマンドはディスプレイ、ブロック番号、オフセット(ここでは 0 にしている)、表示フォーマット i は inode となっています。
 
この構文の意味は、d コマンドはディスプレイ、ブロック番号、オフセット(ここでは 0 にしている)、表示フォーマット i は inode となっています。
   
''注意'': ブロックが使用中でないと表示される場合は、そのブロックが割り当てられておらず、空きスペースになっていることを意味します。これは、何も重要なデータが失われていないということなので良いことです。
+
{{Note|ブロックが使用中でないと表示される場合は、そのブロックが割り当てられておらず、空きスペースになっていることを意味します。これは、何も重要なデータが失われていないということなので良いことです。}}
   
  +
di_number にセットされている 10 進数が私達の求めるものです。ここで x とタイプしてディスプレイモードから抜けます。全ての破損ブロックに対してこのディスプレイコマンドを繰り返し、それらの inode 番号を記録しておきます。inode に関するパーミッションやファイルタイプなど他の情報を得るには、次のようにタイプします:
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''
+
i ''inode番号''
   
  +
inode 番号が分かったら q とタイプして終了します。
When you have all the inode numbers type q to quit.
 
   
 
==破損ファイルを見つける (JFS/Universal)==
 
==破損ファイルを見つける (JFS/Universal)==
68行目: 68行目:
 
これでようやく破損ファイルを見つけられます。GNU find ユーティリティを使います。ファイルシステムをマウントして次を実行します:
 
これでようやく破損ファイルを見つけられます。GNU find ユーティリティを使います。ファイルシステムをマウントして次を実行します:
   
find / -inum ''inodenumber''
+
# find / -inum ''inode番号''
   
"/" はその inode が属するファイルシステムのマウントポイントで置き換えてください。
+
"/" はその inode が属するファイルシステムのマウントポイントで置き換えてください。{{ic|/}} を検索して 2 個以上のファイルシステムがマウントされていたら(普通はそうなっているでしょう)、異なるファイルシステム上で同じ inode 番号のファイルが複数見つかるでしょう。そしてその場合は明らかに時間が長くかかります。inode はファイルシステムの中でだけユニークなことに注意してください。
/ を検索して 2 個以上のファイルシステムがマウントされていたら(普通はそうなっているでしょう)、異なるファイルシステム上で同じ inode 番号のファイルが複数見つかるでしょう。そしてその場合は明らかに時間が長くかかります。inode はファイルシステムの中でだけユニークなことに注意してください。
 
   
==ファイルシステムをデバッグする (EXT(2/3/4))==
+
==ファイルシステムをデバッグする (Ext2/3/4)==
 
tune2fs を使うと、各種 EXT ファイルシステム内の全ての低レベル構造にアクセスできます。これを行う前に全てのファイルシステムをアンマウントしておくとよいでしょう。
 
tune2fs を使うと、各種 EXT ファイルシステム内の全ての低レベル構造にアクセスできます。これを行う前に全てのファイルシステムをアンマウントしておくとよいでしょう。
   
最初にやることは、ファイルシステムのブロックサイズを取得することです。これを実行します:
+
最初にやることは、ファイルシステムのブロックサイズを取得することです。以下のコマンドを実行します:
   
tune2fs -l /dev/sdxy | grep Block
+
{{hc|<nowiki># tune2fs -l /dev/sdxy | grep Block</nowiki>|2=
Block count: 29119820
+
Block count: 29119820
'''Block size: 4096'''
+
'''Block size: 4096'''}}
   
 
この場合は 4096 がブロックサイズです(これがデフォルトのようです)。
 
この場合は 4096 がブロックサイズです(これがデフォルトのようです)。
90行目: 89行目:
 
(original block number) / ((filesystem block size) / (badblocks block size))
 
(original block number) / ((filesystem block size) / (badblocks block size))
   
さて、本来の目的は inode 番号を取得することです。のコマンドを実行してください:
+
さて、本来の目的は inode 番号を取得することです。以下のコマンドを実行してください:
   
debugfs
+
# debugfs
   
そして debugfs のコンソールにおいて、破損セクタを含んでいる EXT のパーティションを引数に open コマンドを実行します:
+
そして debugfs のコンソールにおいて、破損セクタを含んでいる EXT のパーティションを引数に {{ic|open}} コマンドを実行します:
   
 
debugfs: open /dev/sdxy
 
debugfs: open /dev/sdxy
102行目: 101行目:
 
debugfs: testb ''ブロック番号''
 
debugfs: testb ''ブロック番号''
   
  +
{{Note|ブロックが使用中でないと表示される場合は、そのブロックが割り当てられておらず、空きスペースになっていることを意味します。これは、何も重要なデータが失われていないということなので良いことです。}}
 
''注意'': ブロックが使用中でないと表示される場合は、そのブロックが割り当てられておらず、空きスペースになっていることを意味します。これは、何も重要なデータが失われていないということなので良いことです。
 
   
 
ブロックが使用中なら、このコマンドで inode 番号を取得できます:
 
ブロックが使用中なら、このコマンドで inode 番号を取得できます:
111行目: 109行目:
 
これは 2 個の数字を表示します。ブロック番号と inode 番号です。
 
これは 2 個の数字を表示します。ブロック番号と inode 番号です。
   
==破損ファイルを見つける (EXT(2/3/4))==
+
==破損ファイルを見つける (Ext2/3/4)==
inode 番号(icheck コマンドで表示される 2 番目の番号を引数に ncheck コマンドを実行します:
+
inode 番号 (icheck コマンドで表示される 2 番目の番号) を引数に {{ic|ncheck}} コマンドを実行します:
   
ncheck ''inodenumber''
+
ncheck ''inode番号''
   
 
この破損ブロックを使っているファイルのフルパスが表示されます。これで実際に何が破損したのかがわかります。
 
この破損ブロックを使っているファイルのフルパスが表示されます。これで実際に何が破損したのかがわかります。
   
もし inode 番号が非常に小さくて ncheck がパス表示に失敗する場合は、おそらくジャーナル自体が壊れています。ジャーナルを削除するには、このコマンドをパーティションに対して実行します:
+
もし inode 番号が非常に小さくて {{ic|ncheck}} がパス表示に失敗する場合は、おそらくジャーナル自体が壊れています。ジャーナルを削除するには、このコマンドをパーティションに対して実行します:
   
tune2fs -O ^has_journal /dev/sdxy
+
# tune2fs -O ^has_journal /dev/sdxy
   
もう一度 debugfs コンソールでtestb コマンドを使ってそのブロックを調べると、もし本当にジャーナルに使われていたのであれば、今度は使われていると表示されないはずです。
+
もう一度 debugfs コンソールで {{ic|testb}} コマンドを使ってそのブロックを調べると、もし本当にジャーナルに使われていたのであれば、今度は使われていると表示されないはずです。
 
次のコマンドで新しいジャーナルを構築します:
 
次のコマンドで新しいジャーナルを構築します:
   
tune2fs -j /dev/sdxy
+
# 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'''
 
   
  +
==強制的に破損ブロックを代替処理させる==
  +
まず、smartctl コマンドでハードディスク上にいくつの破損ブロックが認識されているかを調べられます:
   
  +
# smartctl -t long /dev/sdx
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:
 
  +
テストが完了するまで待ってから以下のコマンドを実行してください:
  +
{{hc|# smartctl -l selftest /dev/sdx|<nowiki>
  +
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'''</nowiki>}}
   
  +
透過的に破損ブロックをスペアの予備セクタへ代替させるには、単に root で dd コマンドを使って破損ブロックにゼロを書き込むだけです。注意すべきなのは、このコマンドを実行するとき、ファイルシステムと同じブロックサイズを使うことと、ブロックの位置をディスク全体でなくファイルシステムがあるパーティションからの相対位置で指定することです:
dd if=/dev/zero of=/dev/sdxy bs=4096 count=1 seek=2269012
 
sync
 
   
  +
# dd if=/dev/zero of=/dev/sdxy bs=4096 count=1 seek=2269012
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:
 
  +
# sync
   
  +
本当に破損セクタが代替処理されたかどうかを確認するには、smartctl コマンドを使って Reallocated_Sector_Ct か Reallocated_Event_Count の値が増えているかを確認します。
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'''
 
   
  +
{{hc|# smartctl -A /dev/sdx|<nowiki>
To get Offline_Uncorrectable to go back to 0 you need to run a SMART long test and a selftest:
 
  +
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'''</nowiki>}}
   
  +
{{ic|Offline_Uncorrectable}} を 0 に戻すには、SMART のロングテストとセルフテストを実行する必要があります:
smartctl -t long /dev/sdx [wait until test completes, then]
 
smartctl -l selftest /dev/sdx
+
# smartctl -t long /dev/sdx
  +
テストが完了するまで待ってから以下を実行してください:
  +
# smartctl -l selftest /dev/sdx
   
 
==参考==
 
==参考==
   
[http://smartmontools.sourceforge.net/badblockhowto.html EXT2/3 badblocks howto]
+
* [http://smartmontools.sourceforge.net/badblockhowto.html EXT2/3 badblocks howto]

2017年1月27日 (金) 23:05時点における最新版

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

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

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

破損ブロックを見つける

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

次のどちらかのコマンドを実行し、-v オプション(冗長表示)つきでリードオンリースキャンを実行します(x はディスクを表す文字で、y はパーティション番号です)。

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

# badblocks -v /dev/sdx

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

# badblocks -v /dev/sdxy

ディスク全体をスキャンすると計算が少し面倒になります。各ファイルシステムはパーティションの先頭からブロック番号を数えるため、例えば 2 番目のパーティション上に破損ブロックがあり、そのパーティションがブロック 1000 から始まっていた場合、求めるブロック番号を得るには badblocks が表示するブロック番号から 1000 を引かなければなりません。つまりディスク全体のスキャンでブロック 1005 が破損していると表示された場合、2 番目のパーティションのブロック 5 が求める破損ブロックの番号になります。

あるいは、ディスク全体をスキャンして破損ブロックが見つかった場合、それがどのパーティションにあるかを計算して、そのパーティションに対して再度スキャンすることでもブロック番号が得られます。

もう一つ覚えておくべきなのは、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 を使うと、JFS ファイルシステム内の全ての低レベル構造にアクセスできます。EXT など他のファイルシステムでも同じようなツールがあります。これを行う前に全てのファイルシステムをアンマウントしておくとよいでしょう。次を実行します:

# jfs_debugfs /dev/sdxy

このコマンドを実行するとコマンドコンソールに入ります。最初にすべきことは aggregate block size を確認することです。これは(おそらく)ファイルシステムのブロックサイズと同じです。JFSのデフォルトは 4096 バイトのようです。

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

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

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

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

d ブロック番号 0 i

この構文の意味は、d コマンドはディスプレイ、ブロック番号、オフセット(ここでは 0 にしている)、表示フォーマット i は inode となっています。

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

di_number にセットされている 10 進数が私達の求めるものです。ここで x とタイプしてディスプレイモードから抜けます。全ての破損ブロックに対してこのディスプレイコマンドを繰り返し、それらの inode 番号を記録しておきます。inode に関するパーミッションやファイルタイプなど他の情報を得るには、次のようにタイプします:

i inode番号

inode 番号が分かったら q とタイプして終了します。

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

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

# find / -inum inode番号

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

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

tune2fs を使うと、各種 EXT ファイルシステム内の全ての低レベル構造にアクセスできます。これを行う前に全てのファイルシステムをアンマウントしておくとよいでしょう。

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

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

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

icheck ブロック番号

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

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

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

ncheck inode番号

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

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

# tune2fs -O ^has_journal /dev/sdxy

もう一度 debugfs コンソールで testb コマンドを使ってそのブロックを調べると、もし本当にジャーナルに使われていたのであれば、今度は使われていると表示されないはずです。 次のコマンドで新しいジャーナルを構築します:

# tune2fs -j /dev/sdxy

強制的に破損ブロックを代替処理させる

まず、smartctl コマンドでハードディスク上にいくつの破損ブロックが認識されているかを調べられます:

# smartctl -t long /dev/sdx

テストが完了するまで待ってから以下のコマンドを実行してください:

# 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'''

透過的に破損ブロックをスペアの予備セクタへ代替させるには、単に root で dd コマンドを使って破損ブロックにゼロを書き込むだけです。注意すべきなのは、このコマンドを実行するとき、ファイルシステムと同じブロックサイズを使うことと、ブロックの位置をディスク全体でなくファイルシステムがあるパーティションからの相対位置で指定することです:

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

本当に破損セクタが代替処理されたかどうかを確認するには、smartctl コマンドを使って Reallocated_Sector_Ct か Reallocated_Event_Count の値が増えているかを確認します。

# 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'''

Offline_Uncorrectable を 0 に戻すには、SMART のロングテストとセルフテストを実行する必要があります:

# smartctl -t long /dev/sdx

テストが完了するまで待ってから以下を実行してください:

# smartctl -l selftest /dev/sdx

参考