RAID5なbtrfsのHDDをreplaceした話

btrfsで作ったディスクアレイのHDDを交換したので、やり方のメモです。 前に書いた完全にディスクが死んでいる場合の記事とは違って、今回は一応マウント出来る状態での交換です。

故障の発見 / 状況を確認する

なんだかやたらとファイルサーバへのアクセスが遅くなっていたので調べてみたところ、dmesgに以下のようなエラーが大量に記録されていました。

$ sudo dmesg
[17415.702324] BTRFS info (device sdf): read error corrected: ino 1 off 60428511150080 (dev /dev/sdd sector 3575050240)
[17415.718786] BTRFS info (device sdf): read error corrected: ino 1 off 60428511154176 (dev /dev/sdd sector 3575050248)
[18003.357383] BTRFS warning (device sdf): sdf checksum verify failed on 60428489015296 wanted 65315BEF found CDF7F87E level 0
[18112.286563] BTRFS warning (device sdf): sdf checksum verify failed on 60428489015296 wanted 65315BEF found CDF7F87E level 0
[29995.452458] BTRFS error (device sdf): bad tree block start 7611175298055105740 60427922653184
[29995.465097] BTRFS error (device sdf): bad tree block start 7611175298055105740 60427922866176

うーん、/dev/sddが死にそう。

device statsにもエラーが記録されていました。

$ sudo btrfs device stats /mnt/data
... 省略 ...
[/dev/sdd].write_io_errs    0
[/dev/sdd].read_io_errs     0
[/dev/sdd].flush_io_errs    0
[/dev/sdd].corruption_errs  58650
[/dev/sdd].generation_errs  0
... 省略 ...

死にそうではあるのですが、degradedオプションを付けなくてもマウント出来る状態です。 btrfs scrubとかやっても一応読めている(でもdmesgに大量にエラーが出る)みたいでした。 瀕死だけど死んでない。

この「degraded付けなくてもマウント出来る」状態であれば、この記事の方法を使うことが出来ます。

もしもdegradedオプションを付けないとエラーが出てマウント出来ないような場合は、以下の記事の方法を試してみてください。
btrfsで作ったRAIDのHDDが壊れた。ので、交換した。

新しいHDDを接続する

新しいHDDが届いたら、通常通りPCに接続します。

今回はreplaceを使うので、壊れかけの古いHDDも繋いだままにしておきます。

古いHDDから新しいHDDにデータをコピーする

接続出来て動作することが確認出来たら、以下のコマンドでreplaceを開始します。

$ sudo btrfs replace start /dev/sdd /dev/sdg /mnt/data

ここでは、/dev/sddが古いディスク、/dev/sdgが新しいディスクで、/mnt/dataがマウント先になっています。

状況を確認しながら待つ

以下のコマンドで進捗状況を確認することが出来ます。

$ sudo btrfs replace status /mnt/data
0.0% done, 0 write errs, 0 uncorr. read errs

めちゃくちゃ時間が掛かるので、のんびり待つと良いと思います。 といってもaddしてremoveする時よりも速いし進捗も見やすいので、比較的待つのは辛くない感じがあります。

コピーが完了すると、replace statusの結果が以下のように変わります。

$ sudo btrfs replace status /mnt/data
Started on 13.Jun 19:17:06, finished on 15.Jun 23:25:21, 0 write errs, 0 uncorr. read errs

これで、HDDの置き換えは完了です。 古いHDDを外して処分しましょう。

エラーカウントをリセットしておく

今回の例だと/dev/sddを交換しましたが、これだけだとdevice statsに記録されたエラーはそのままになっています。 そうなると今後エラーを見つけられなくて困るので、カウントをリセットしておきましょう。

$ sudo btrfs device stats --reset /mnt/data
... 省略 ...
[/dev/sdd].write_io_errs    0
[/dev/sdd].read_io_errs     0
[/dev/sdd].flush_io_errs    0
[/dev/sdd].corruption_errs  58650
[/dev/sdd].generation_errs  0
... 省略 ...

もう一回statsを見てみると、綺麗に消えているはずです。

$ sudo btrfs device stats /mnt/data
... 省略 ...
[/dev/sdd].write_io_errs    0
[/dev/sdd].read_io_errs     0
[/dev/sdd].flush_io_errs    0
[/dev/sdd].corruption_errs  0
[/dev/sdd].generation_errs  0
... 省略 ...

これで次にエラーが起きたときも分かりやすくて安心。

容量の大きいHDDに交換した場合

HDDの交換が完了した後でdevice usageを見てみると、以下のようになっていました。

$ sudo btrfs device usage /mnt/data
... 省略 ...

/dev/sdf, ID: 6
   Device size:             2.73TiB
   Device slack:              0.00B
   Data,RAID10:             2.68TiB
   System,RAID1:           32.00MiB
   Unallocated:            47.49GiB

/dev/sdg, ID: 7
   Device size:             5.46TiB
   Device slack:            1.82TiB
   Data,RAID10:             3.57TiB
   Metadata,RAID1:         14.00GiB
   System,RAID1:           64.00MiB
   Unallocated:            53.96GiB

ずっと繋いでいる/dev/sdf(3TB)はDevice slackが0Bなのですが、今回追加した/dev/sdg(4TBから6TBに増やした)はDevice slackが2TBになっています。

単純に容量の大きいストレージを繋いだだけだと、余剰扱いになってしまって使ってくれないみたいです。

なので、以下のコマンドでフルに使って良いことをbtrfsに伝えます。

$ sudo btrfs filesystem resize 7:max /mnt/data
Resize '/mnt/data' of '7:max'

ここで書いている7はさっきのdevice usageで見れるIDの番号です。

このコマンドはわりとすぐ終わります。 終わったら、以下のような感じでフルに使えるようになっているはず。

$ sudo btrfs device usage /mnt/data
... 省略 ...

/dev/sdf, ID: 6
   Device size:             2.73TiB
   Device slack:              0.00B
   Data,RAID10:             2.68TiB
   System,RAID1:           32.00MiB
   Unallocated:            47.49GiB

/dev/sdg, ID: 7
   Device size:             5.46TiB
   Device slack:              0.00B
   Data,RAID10:             3.57TiB
   Metadata,RAID1:         14.00GiB
   System,RAID1:           64.00MiB
   Unallocated:             1.87TiB

この時点ではデータが偏って配置されてしまっているので、最後にbalanceを実行してあげましょう。(これが時間掛かる…)

$ sudo btrfs balance start --bg --full-balance /mnt/data

これも、適当に状況を見ながら待ちます。

$ sudo btrfs balance status /mnt/data
Balance on '/mnt/data' is running
1 out of about 3674 chunks balanced (2 considered), 100% left

参考: btrfs wikiに書いてないハマりどころメモ (RAID5障害・拡張) - Qiita