freebsd-壊れたHDDの復旧

インシデント対応のきっかけ

教頭先生のUSB-HDDが壊れた。WindowsでUSB-HDDをさすとブルー画面になり、Windowsが落ちる。
ブルー画面がいうには、割り込みに失敗しているっぽい。
割り込み無視する設定がWindows上でできるらしいので、やってみるが、意味がなかった。
ただ、校内サーバ[freeBSD]でUSB-HDDをさすと、落ちない。
dmesg すると、HDD自体は見えているが、マウントに失敗しているようだったので、家に帰り本格的に調査することにした。

以下、備忘録としてインシデント対応の手順を記述する。

21:48 HDD修復ユーティリティffs2recovをインストールする。

$cd /usr/ports/sysutils/ffs2recov
$make
$make install

21:51 USB-HDDのボリュームラベルを調べる

こういう時はdmesgを使えばよいので、dmesgを使う。以下結果の一部抜粋。
ただし、 HDDのシリアルナンバーは*で隠ぺいした。

$dmesg
umass0 on uhub5
umass0: <FUJITSU MB86C311, class 0/0, rev 2.10/0.01, addr 2> on usbus1
umass0:  SCSI over Bulk-Only; quirks = 0x0100
umass0:6:0: Attached to scbus6
(probe0:umass-sim0:0:0:0): REPORT LUNS. CDB: a0 00 00 00 00 00 00 00 00 10 00 00
(probe0:umass-sim0:0:0:0): CAM status: SCSI Status Error
(probe0:umass-sim0:0:0:0): SCSI status: Check Condition
(probe0:umass-sim0:0:0:0): SCSI sense: ILLEGAL REQUEST asc:20,0 (Invalid command operation code)
(probe0:umass-sim0:0:0:0): Error 22, Unretryable error
da0 at umass-sim0 bus 0 scbus6 target 0 lun 0
da0: <TOSHIBA MQ01ABF050 AM00> Fixed Direct Access SPC-4 SCSI device
da0: Serial Number 00000000000*****
da0: 40.000MB/s transfers
da0: 476940MB (976773168 512 byte sectors)
da0: quirks=0x2<NO_6_BYTE>

従って、

da0: <TOSHIBA MQ01ABF050 AM00> Fixed Direct Access SPC-4 SCSI device

より、USB-HDDのボリュームラベルは予想通り da0 であることが分かった。

Probe0:umass-sim0:0:0:0 SCSI Status Error
Probe0:umass-sim0:0:0:0 SCSI sense: ILLEGAL REQUEST

がキーワードっぽい。 しかし、いまだにUSBがSCSIとは。昔の名残か。
それとも内部的なSCSIなのか、調べる気はないけど、面白い。

21:56 とりあえず修復を試みる ffs2recov

とりあえず、HDDが物理的にではなく、論理的に壊れていることが分かったので、ソフトウェア的に修復を試みる。

$ffs2recov –s /dev/da0

青色LEDが激しく点滅。大丈夫か。

22:43 点滅一時間。もう待てません。

1時間大人しく待ってみたが、点滅するのみで変化がない・・。
もしかして、点滅しているだけで、システムの処理はkillされているのかも、と疑う。
タスクが生きているか確認する。

$top
Mem: 97M Active, 3585M Inact, 130M Laundry, 4307M Wired, 775M Buf, 328M Free
ARC: 2125M Total, 1075M MFU, 321M MRU, 32K Anon, 46M Header, 683M Otherr
     1026M Compressed, 1612M Uncompressed, 1.57:1 Ratio
Swap: 4096M Total, 4096M Free

  PID USERNAME    THR PRI NICE   SIZE    RES STATE    C   TIME    WCPU COMMAND
60231 root          1  21    0    11M  2496K physrd   0   1:53   4.15% ffs2recov
63533 root          1  20    0    13M  3828K CPU0     0   0:00   0.10% top
62820 root          1  20    0    20M  9848K select   0   0:00   0.01% sshd

一応、PID 60231 で生きていた。
さっぱりわからない。
ffs2recovはそのまま実行させておきながら、別方法試すことにした。

22:45 無理やりマウントを試みる

そもそもWindowsファイルシステムntfs[NT-File System]であり、外付けUSBは大体FAT32[File Allocation Table32bits]であることが多い。
自宅サーバや校内サーバはFreeBSDで構築しているため、UFS[Unix File System]だ。しかも、データ領域は堅牢性を極限まで高めたZFS[Zeta Byte File System]である。そもそも現況ではntfsを読み込めないので、読み込む方法を考える。

mount -t ntfs /dev/da0 /mnt

→怒られる。
昔はこれでいけたのに。

調べると、ntfsをマウントするためには、fusefs-ntfsというやつがあるらしい。

cd /usr/ports/sysutils/fusefs-ntfs
make
make install

22:48 fuseの有効化

fuse を有効化する。 Fuseとは何のことがさっぱりわからないけれども、そういえば、
ラズパイでなんちゃってzfsをしたいときにfuseのインストールをしたことがあったので、それっぽい。

安定性が怖くて、結局純正のzfsを使うために、学校も家もOSをfreebsdにしたが。

$kldload fuse
$ ntfs-3g -oro /dev/da0s1 /mnt/
$

反応がなく、エラーも出ない。
そのままマウントされた?
淡い期待が。

22:52 マウントステータスの確認

とりあえず、マウントステータスを確認する。

root@:/usr/ports/sysutils/fusefs-ntfs # mount
/dev/ada4s1a on / (ufs, local, journaled soft-updates)
devfs on /dev (devfs, local, multilabel)
tank/jail on /jail (zfs, local, noatime, nfsv4acls)
tank/jail/fulljail on /jail/fulljail (zfs, local, noatime, nfsv4acls)
tank on /storage (zfs, local, noatime, nfsv4acls)
tank/ezjail on /storage/jail (zfs, local, noatime, nfsv4acls)
tank/ezjail/basejail on /storage/jail/basejail (zfs, local, noatime, nfsv4acls)
tank/ezjail/newjail on /storage/jail/newjail (zfs, local, noatime, nfsv4acls)
/dev/fuse on /mnt (fusefs, local, read-only, synchronous)

jailは、仮想化技術のjail環境のこと。
一つのPCの中に仮想的に別のPCをインストールして外部からはまるで複数のPCがあるかのように振る舞わせることができるのが仮想化。
ただし、仮想化PCが親PCの核心部分を変更できてしまうと大問題なので、jail[牢屋]に入れて悪さができないような環境構築技術の事。

tankは複数のHDDをRaid-Zで構築するためのストレージプール。これで2TB5台を8TBの一つのHDDとして取り扱っている。2TB少なくなっていまうが、5台の内、どのHDDが一つ故障しても新しいHDDをさしなおしたら自動的に完全修復してくれる。
どういう技術かさっぱりわからない。
一応、備忘録の為に引用しておく。

blogs.oracle.com

RAID-Z 入門

RAID-Z は RAID-5 と似たデータ/パリティスキーマですが、ストライプ幅が可変である点が異なります。ブロックサイズにかかわらず、すべてのブロックで RAID-Z のストライプを構成します。つまり、RAID-Z への書き込みはすべてストライプ全体の書き込みになります。これを ZFSトランザクションセマンティクスであるコピーオンライトと組み合わせると、RAID の書き込みホールを完全に回避できます。RAID-Z は、リードモディファイライトを行わないため、従来の RAID と比較して速度も向上しています。

あれ、それで全部 ? 可変幅ストライプ ? まったくわかりきったことだ。そんなに名案なら、皆がやってるはずだろう ?

仕掛けがあるのは、RAID-Z の再構築機能です。ストライプのサイズがそれぞれに異なるため、「全ディスクでの XOR をゼロにする」といった単純な処理ではありません。ファイルシステムメタデータを走査して、RAID-Z のジオメトリを判断する必要があります。これは、ファイルシステムRAID アレイが分離した製品では不可能なことで、RAID-Z のような仕組みがこれまでストレージ市場になかったことの理由でもあります。データの論理的構造と物理的構造を総合的に把握する必要があります。 

一応、折角なので読んでみたが、多分日本語訳が悪い。例えば、
サイレント破損→わからない。[サイレントクラッシュのこと]
リードモディファイライト→よく読めばわかる[リード・モディファイ・ライトのこと]

閑話休題

という訳で、
めでたく、

/dev/fuse on /mnt (fusefs, local, read-only, synchronous)

を発見できた。
ただ、read-only の通り、書き込みができないっぽい。これは想定内。Windowsでは書き込みできるだろうが。
もしかして勝ったのか?

22:55 やばい

root@:/usr/ports/sysutils/fusefs-ntfs # ls /mnt/
$RECYCLE.BIN                    R1                              UnplugDrive.exe                 found.000                       ??????
H30                             System Volume Information       diskmirroring.exe               ~$??????????????????.docx

やばい。見えた。
でも、日本語見えない。

shから、チューニングしているbashにシェルを切り替える。

$bash
$ls /mnt
~$次会のご案内.docx             diskmirroring.exe               H30                             System Volume Information       印刷
$RECYCLE.BIN                    found.000                       R1                              UnplugDrive.exe

やばい。見えた。
ディレクトリを掘ってみる。

[root@ /mnt]# cd H30
[root@ /mnt/H30]# ls
日課表の変更について.docx                             ㊼学校要覧                                                      ㉚自主学習ノートの手引き
?H30  写真                                                    
[root@ /mnt/H30]# cd ..
[root@ /mnt]# ls
~$次会のご案内.docx             diskmirroring.exe               H30                             System Volume Information       印刷
$RECYCLE.BIN                    found.000                       R1                              UnplugDrive.exe

めっちゃやばい。

22:58 取り込み方法を考える。

これをどうやって取り込もうか。
やり方がわからない。
$cp -r でえいやとしてしまうか、丁寧に rsyncミラーリングするか。
取り合えず、バックアップ用のディレクトリを作成する。

[root@ /storage]# su ymlab
ymlab@:/storage % mkdir abc
ymlab@:/storage % exit
exit
[root@ /storage]#

23:00 悩む

23:03 cp -r することにする。

crontab組むのがめんどくさいので、とりあえずcp –r してみて、失敗したらおとなしくcronすることにする。
しかし、相変わらず、最初にやったffs2recovの反応はない。アクセスランプは激しく点滅している。

23:05 コピー実行 –r 再帰的に –P パーミッション維持 v 見える化

[root@ /storage]# cp -rPv /mnt/* /storage/abc/

23:05 ゴミ箱フォルダまでコピーしている。やっぱりrsyncするべきでした。

23:26 まだコピーしている。

23:39 暇つぶしにログノートにまとめることにした。

24:30 コピー完了

これでサーバのabcディレクトリをSambaでファイル共有させればWindowsから見える。
f:id:ymlab:20191029003209p:plain

見えた。勝った。

後は、USBでミラーリングすればいいだけ。

26:00 コピー開始

WindowsにUSBをさしてサーバー越しにコピーしようとしたら、3時間かかるといわれた。
しょうがないから、サーバにUSBメモリをさしてコピーしようとした。
命令は以下

$mount -t msdosfs /dev/da1 /media

マウントができたが、日本語回りでコピーに失敗する。
残念ながら今からネットワーク越しにコピー。3時間待つことにする。
しかし、まだffs_recovの点滅が終わらない。今から寝たいので、熱暴走が怖いからアンマウントすることにする。