HDD のバッドセクタ異常を解消させる方法(smartctl/badblocks/e2fsck/hdparm)
先日、家庭内サーバーとして使っていたPCが壊れたため、パーツ買い替え等をしていたのですが、接続していたHDDに不良セクタが出ていたため、修復を行っていました。
本記事は、その修復の手順のメモです。修復の流れは以下の通りです
- smartctl で状況確認
- smartctl でセルフテストを実行
- 破損したセクタ上にあったファイルの修復と、ファイルシステムの不整合の修復
- 不良なセクタを HDD ドライブレベルで使用不可にする
- badblocks 指定の解除
- おまけ: munin の smart plugin の警告を消す
以下、それぞれの詳細です。
smartctl で状況確認
私は普段は munin で smart を監視させているのですが、そこで異常が検知されました。
まずは何が起こっているかを、smartctl で全情報を表示して確認。
$ sudo smartctl -a /dev/sda; echo "exit code: $?"
主なエラー要因は exit code で表現されています。詳しくは、manpage に書かれていますが、exit code はビットフラグになっていて、64 ならエラーログ有り、128 ならセルフテストでのエラー検知を表しています。(両方なら 192になります。)
exit code が 64 (のビットを含んでいる)なら、以下のようなログが表示されているかと思います。下記の例は 34869129 番セクターの READ でエラーが起きているようです。
$ sudo smartctl -l error /dev/sda smartctl 6.6 2016-05-31 r4324 [x86_64-linux-4.15.0-175-generic] (local build) Copyright (C) 2002-16, Bruce Allen, Christian Franke, www.smartmontools.org === START OF READ SMART DATA SECTION === SMART Error Log Version: 1 Warning: ATA error count 863 inconsistent with error log pointer 5 ATA Error Count: 863 (device log contains only the most recent five errors) CR = Command Register [HEX] FR = Features Register [HEX] SC = Sector Count Register [HEX] SN = Sector Number Register [HEX] CL = Cylinder Low Register [HEX] CH = Cylinder High Register [HEX] DH = Device/Head Register [HEX] DC = Device Command Register [HEX] ER = Error register [HEX] ST = Status register [HEX] Powered_Up_Time is measured from power on, and printed as DDd+hh:mm:SS.sss where DD=days, hh=hours, mm=minutes, SS=sec, and sss=millisec. It "wraps" after 49.710 days. Error 863 occurred at disk power-on lifetime: 32098 hours (1337 days + 10 hours) When the command that caused the error occurred, the device was active or idle. After command completion occurred, registers were: ER ST SC SN CL CH DH -- -- -- -- -- -- -- 40 51 01 89 0f 14 e2 Error: UNC at LBA = 0x02140f89 = 34869129 Commands leading to the command that caused the error were: CR FR SC SN CL CH DH DC Powered_Up_Time Command/Feature_Name -- -- -- -- -- -- -- -- ---------------- -------------------- 20 00 01 89 0f 14 e2 08 06:31:15.851 READ SECTOR(S) b0 d5 01 09 4f c2 00 08 06:30:46.223 SMART READ LOG b0 d5 01 06 4f c2 00 08 06:30:46.222 SMART READ LOG b0 d5 01 01 4f c2 00 08 06:30:46.221 SMART READ LOG b0 d5 01 00 4f c2 00 08 06:30:46.221 SMART READ LOG (以下略)
smartctl でセルフテストを実行
smartに対応した多くの HDD は、通常使用中でも実行可能なセルフテスト機能を持っていたりします。このセルフテストは
$ sudo smartctl -t short /dev/sda
で実行を指示することができます。セルフテストは short の他に long なども指定可能です。
longのほうがより多くのエラーを検知できますが、実行にかかる時間が長くなります。(手元の個体だと short で 2 分、long で 4時間ほどでした。サポートしているテストの種類や実行にかかる予定時間は -a
で表示される属性に含まれています。)
上記のコマンドでセルフテストの実行を初めたら、その時に表示された終了予定時刻になるぐらいまで待ったうえで、
$ sudo smartctl -l selftest /dev/sda
とすると、実行結果を見ることができます。
例えば、以下のような出力だった場合、「(先頭からテストして) 34869129 番のセクタで読み込み不可のセクタが見つかった」という意味になります。
SMART Self-test log structure revision number 1 Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error # 1 Short offline Completed: read failure 90% 32095 34869129
破損したセクタ上にあったファイルの修復と、ファイルシステムの不整合の修復
参考ページには、セクタ番号をもとに、そこに書かれていたのがどのファイルかを特定する方法が書かれていますので、必要であればそちらをご参照ください。
今回私はファイルシステム上の修復だけで良かったので、fsck と badblocks だけで手抜きをしました。
badblocks を使う場合、まずは badblocks を使って不良なブロックを検出したうえで、e2fsck で書き込む、という2段階の手順を紹介されていることが多いようですが、e2fsck の -c
オプションを使えば、裏で badblocks を自動で使って一発でやってくれるので楽です。-c
で読み込みのみのテスト、-cc
とすると非破壊の読み書きテストを行い、不良ブロックを検出することができます。
$ sudo e2fsck -vcck /dev/sda1
読み書きテストを行うとかなり時間がかかるので、-y
オプション(「フリーブロック数が間違っているようなので修復するか?」などの質問に自動で yes と答える)をつけるかどうかは好みでどうぞ。
不良なセクタを HDD ドライブレベルで使用不可にする
ファイルシステム側で不良セクタを避けて使ってくれていれば、基本的には問題は無いはずですが、HDD側でも不良セクタは修復しておいたほうが無難なので、そちらも対応しました。
エラーログやセルフテストの結果から、不良セクタの場所はわかっています。(下記は、いろいろいじったあとなのでテスト回数が2回増えてますが気にしないでください。)
SMART Self-test log structure revision number 1 Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error # 1 Extended offline Completed: read failure 90% 32098 34869129 # 2 Short offline Completed without error 00% 32097 - # 3 Short offline Completed: read failure 90% 32095 34869129
まず、確認のため、該当セクタを直接読んでみます。
$ sudo hdparm --read-sector 34869129 /dev/sda /dev/sda: reading sector 34869129: SG_IO: bad/missing sense data, sb[]: 70 00 03 00 00 00 00 0a 40 51 e2 01 11 04 00 00 00 89 00 00 00 00 00 00 00 00 00 00 00 00 00 00 succeeded 0000 0000 0000 0000 0000 0000 0000 0000 (以下略)
たしかにエラーが出ているようです。(succeeded と出ているのがミスリーディングではありますが。)
そこで、hdparmでここに書き込みを行います。なお、これは危険な操作で、もしこのセクタをまだファイルシステムが使用していた場合、ファイルシステムが破壊されるかもしれません。(以下のコマンドライン例からは、最終確認のためのオプションを削っています。実行したときに出る説明をよく読んでからオプションを追加して再実行してください。)
$ sudo hdparm --write-sector 34869129 /dev/sda /dev/sda: re-writing sector 34869129: succeeded
この書き込みによって、この不良セクタに予備のセクタが割り当て直されることになります。うまく修復されていれば、このセクタを再度読み込みしてもエラーがでなくなります。
$ sudo hdparm --read-sector 34869129 /dev/sda /dev/sda: reading sector 34869129: succeeded 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 (以下略)
ここで、再度セルフテストして、他のセクタに異常が無いかを確認します。
$ sudo smartctl -t short /dev/sda (略) (数分待ってから) $ sudo smartctl -l selftest /dev/sda smartctl 6.6 2016-05-31 r4324 [x86_64-linux-4.15.0-175-generic] (local build) Copyright (C) 2002-16, Bruce Allen, Christian Franke, www.smartmontools.org === START OF READ SMART DATA SECTION === SMART Self-test log structure revision number 1 Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error # 1 Short offline Completed without error 00% 32098 - # 2 Extended offline Completed: read failure 90% 32098 34869129 # 3 Short offline Completed without error 00% 32097 - # 4 Short offline Completed: read failure 90% 32095 34869129 $ sudo smartctl -t long /dev/sda (略) (数時間待ってから) $ sudo smartctl -l selftest /dev/sda smartctl 6.6 2016-05-31 r4324 [x86_64-linux-4.15.0-175-generic] (local build) Copyright (C) 2002-16, Bruce Allen, Christian Franke, www.smartmontools.org === START OF READ SMART DATA SECTION === SMART Self-test log structure revision number 1 Num Test_Description Status Remaining LifeTime(hours) LBA_of_first_error # 1 Extended offline Completed without error 00% 32102 - # 2 Short offline Completed without error 00% 32098 - # 3 Extended offline Completed: read failure 90% 32098 34869129 # 4 Short offline Completed without error 00% 32097 - # 5 Short offline Completed: read failure 90% 32095 34869129 2 of 2 failed self-tests are outdated by newer successful extended offline self-test # 1
今回の場合、short, long ともにエラー無しになりました。もし他のセクタでエラーが出た場合は hdparm による書き込みで一つ一つ潰していくことになります。
badblocks 指定の解除
HDD 側で不良セクタの改修ができたなら、ファイルシステム側で避ける必要は無いので、badblocks 指定は解除しても問題無いと思います。-k
オプション無しで再度 e2fsck -cc
してやれば、不良ブロックが無いことを確認したうえで指定解除ができます。
$ sudo e2fsck -vcc /dev/sda1
解除するぐらいなら初めから設定しなければ良いのでは、という向きもあるかもしれませんが、少なくともファイルシステム上の修復は必要なので、少なくとも1度は fsck をかけるべきでしょうし、一度避けておけば修復も幾分気が楽なのでこの形をとりました。(もちろんフォーマットして使うなら不要です。)
おまけ: munin の smart plugin の警告を消す
HDD のエラーログはずっと残ってしまい、多分消す方法が無いので、一度エラーが発生すると smartctl の exit code には 64 が残ってしまいます。
munin の smart plugin はデフォルトでは exit code が非 0 だと警告を出して鬱陶しいので、以下の内容で /etc/munin/plugin-conf.d/smart_sda
を作成しました。
[smart_sda] env.ignoreexit 64
こうしておけば、このプラグインは smartctl の exit code で返された値から 64 のビットはマスクして扱うようになり、HDD にエラーログが記録されていても警告はでなくなります。セルフテストの失敗など、他のエラーコードは無視したりはしないので安心です。
参考: