zfs HDD入れ替え

日々自宅サーバの運営を続けていると・・・色々なトラブルに巻き込まれるもので、たいてい年末に何かある。で、今年のネタは・・・普段のメンテで再起動した方がいいだろうなということをやることはままあるのだけども(本来再起動は滅多にしなくていいのだが、うちの場合なぜかWebサーバの再起動がかけられず、Apache HTTPdのアップデートの時はほぼ再起動)、12月に入ってからどうも再起動してリモートログインするのに時間がかかる。コンソール出力を見ると確かに何かリトライしているなあと思っていて時間ができそうな年末にでも見てみようとなったわけである。すると・・・

ahcich3: Timeout on slot 5 port 0
ahcich3: is 00000000 cs 00000020 ss 00000000 rs 00000020 tfd 1d0 serr 00000000 cmd 0004c517
(aprobe3:ahcich3:0:0:0): ATA_IDENTIFY. ACB: ec 00 00 00 00 40 00 00 00 00 00 00
(aprobe3:ahcich3:0:0:0): CAM status: Command timeout
(aprobe3:ahcich3:0:0:0): Retrying command
run_interrupt_driven_hooks: still waiting after 60 seconds for xpt_config
ahcich3: Timeout on slot 6 port 0
ahcich3: is 00000000 cs 00000040 ss 00000000 rs 00000040 tfd 1d0 serr 00000000 cmd 0004c617
(aprobe3:ahcich3:0:0:0): ATA_IDENTIFY. ACB: ec 00 00 00 00 40 00 00 00 00 00 00
(aprobe3:ahcich3:0:0:0): CAM status: Command timeout
(aprobe3:ahcich3:0:0:0): Error 5, Retries exhausted
ahcich3: Timeout on slot 11 port 0
ahcich3: is 00000000 cs 00000800 ss 00000000 rs 00000800 tfd 1d0 serr 00000000 cmd 0004cb17
(aprobe3:ahcich3:0:0:0): ATA_IDENTIFY. ACB: ec 00 00 00 00 40 00 00 00 00 00 00
(aprobe3:ahcich3:0:0:0): CAM status: Command timeout
(aprobe3:ahcich3:0:0:0): Retrying command
run_interrupt_driven_hooks: still waiting after 120 seconds for xpt_config
ahcich3: Timeout on slot 12 port 0
ahcich3: is 00000000 cs 00001000 ss 00000000 rs 00001000 tfd 1d0 serr 00000000 cmd 0004cc17
(aprobe3:ahcich3:0:0:0): ATA_IDENTIFY. ACB: ec 00 00 00 00 40 00 00 00 00 00 00
(aprobe3:ahcich3:0:0:0): CAM status: Command timeout
(aprobe3:ahcich3:0:0:0): Error 5, Retries exhausted

というところが該当する・・・ (zfsをマウントするちょい前) これなんだろう・・・? しばらく待てば起動はするんだけど、とよく見たら、ahcich3がおかしい。どうも認識してないみたい。で、ahcich3ってなんだと思ったらATAデバイス・・・すなわちHDDですねと。こりゃやばい。状態を確認してみよう。

# zpool status
  pool: tank0
 state: DEGRADED
status: One or more devices could not be opened.  Sufficient replicas exist for
        the pool to continue functioning in a degraded state.
action: Attach the missing device and online it using 'zpool online'.
   see: http://illumos.org/msg/ZFS-8000-2Q
  scan: none requested
config:
        NAME                                            STATE     READ WRITE CKSUM
        tank0                                           DEGRADED     0     0     0
          mirror-0                                      DEGRADED     0     0     0
            gptid/942be1e0-46dd-11e2-bc4e-bc5ff483903d  ONLINE       0     0     0
            15410413389541041658                        UNAVAIL      0     0     0  was /dev/gptid/92b0a871-46dd-11e2-bc4e-bc5ff483903d
errors: No known data errors

やはりmirrorが片肺運転になっている・・・これはまずい。片方がやられたとなるとほぼ似たような時期に買った生き残っている方も時間の問題と言える。ということで、2台HDDを購入して完全にreplaceすることに。余計な出費である。広瀬さんとこの「[zfs HDD交換練習](zfs HDD交換練習)」を参考に・・・全く同じ作業をやってみる。
とりあえずお亡くなりになったHDDはOFFLINEにする。

# zpool offline tank0 15410413389541041658
# zpool status
  pool: tank0
 state: DEGRADED
status: One or more devices has been taken offline by the administrator.
        Sufficient replicas exist for the pool to continue functioning in a
        degraded state.
action: Online the device using 'zpool online' or replace the device with
        'zpool replace'.
  scan: none requested
config:
        NAME                                            STATE     READ WRITE CKSUM
        tank0                                           DEGRADED     0     0     0
          mirror-0                                      DEGRADED     0     0     0
            gptid/942be1e0-46dd-11e2-bc4e-bc5ff483903d  ONLINE       0     0     0
            15410413389541041658                        OFFLINE      0     0     0  was /dev/gptid/92b0a871-46dd-11e2-bc4e-bc5ff483903d
errors: No known data errors

dmesgを確認して、生き残っているHDDのシリアル番号を念のためチェック。こっちはとりあえず接続したままにして、お亡くなりになったHDDを物理的に外して、新規に買ってきたHDDを接続。2台買ってきたが、HDDの物理的な配置スペースの関係上1台ずつ作業を行う。(実際は、2台一気に接続しちゃって構わない。) あとパーティション情報も確認。前回インストールの時に適当に自動で作業したら・・・なんだこのパーティションテーブルは。でも、もう今のところは修正しようがない。次回マシン変更の時にでもやりましょう。(何年後か・・・5年は先だな。)

# dmesg | grep ada
ada0 at ahcich2 bus 0 scbus2 target 0 lun 0
ada0: <ST2000DM001-9YN164 CC4H> ATA8-ACS SATA 3.x device
ada0: Serial Number W1E28G6X
ada0: 600.000MB/s transfers (SATA 3.x, UDMA6, PIO 8192bytes)
ada0: Command Queueing enabled
ada0: 1907729MB (3907029168 512 byte sectors)
ada0: quirks=0x1<4K>
ada0: Previously was known as ad8
ada1 at ahcich6 bus 0 scbus6 target 0 lun 0
ada1: <WDC WD20EFRX-68EUZN0 82.00A82> ACS-2 ATA SATA 3.x device
ada1: Serial Number WD-WCC4M4CN6JP0
ada1: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)
ada1: Command Queueing enabled
ada1: 1907729MB (3907029168 512 byte sectors)
ada1: quirks=0x1<4K>
ada1: Previously was known as ad16
# gpart show ada0
=>        34  3907029101  ada0  GPT  (1.8T)
          34         128     1  freebsd-boot  (64K)
         162           6        - free -  (3.0K)
         168  3907008512     2  freebsd-zfs  (1.8T)
  3907008680       20455        - free -  (10M)

この情報をもとに新しいHDDにパーティションを作成。パーティションタイプを間違わないようにする。

# gpart create -s gpt ada1
# gpart add -t freebsd-boot -b 34 -s 64k ada1
# gpart add -t freebsd-zfs -b 168 -s 3907008512 ada1
ada1p2 added
# gpart show ada0
=>        34  3907029101  ada0  GPT  (1.8T)
          34         128     1  freebsd-boot  (64K)
         162           6        - free -  (3.0K)
         168  3907008512     2  freebsd-zfs  (1.8T)
  3907008680       20455        - free -  (10M)
# gpart show ada1
=>        34  3907029101  ada1  GPT  (1.8T)
          34         128     1  freebsd-boot  (64K)
         162           6        - free -  (3.0K)
         168  3907008512     2  freebsd-zfs  (1.8T)
  3907008680       20455        - free -  (10M)

全く同じものが作成できたようだ。今回は2TBのHDDがつながっている環境に2TBのHDDを購入してきたので、後で領域の拡張はしなくてOK。このHDDは常に9割くらい空いているので、2TBのHDDが入手できる限りは2TBで運用しよう。で、bootcodeを書き込む。

# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada1
partcode written to ada1p1
bootcode written to ada1

ここまでで準備はできたので、先ほどOFFLINEにしたHDDとreplace。

# zpool replace tank0 15410413389541041658 ada1p2
Make sure to wait until resilver is done before rebooting.
If you boot from pool 'tank0', you may need to update
boot code on newly attached disk 'ada1p2'.
Assuming you use GPT partitioning and 'da0' is your new boot disk
you may use the following command:
        gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0
# zpool status
  pool: tank0
 state: DEGRADED
status: One or more devices is currently being resilvered.  The pool will
        continue to function, possibly in a degraded state.
action: Wait for the resilver to complete.
  scan: resilver in progress since Thu Dec 27 13:17:31 2018
        1.25G scanned out of 200G at 30.5M/s, 1h51m to go
        1.25G resilvered, 0.62% done
config:
        NAME                                            STATE     READ WRITE CKSUM
        tank0                                           DEGRADED     0     0     0
          mirror-0                                      DEGRADED     0     0     0
            gptid/942be1e0-46dd-11e2-bc4e-bc5ff483903d  ONLINE       0     0     0
            replacing-1                                 OFFLINE      0     0     0
              15410413389541041658                      OFFLINE      0     0     0  was /dev/gptid/92b0a871-46dd-11e2-bc4e-bc5ff483903d
              ada1p2                                    ONLINE       0     0     0  (resilvering)
errors: No known data errors

作業が始まったので、resilveringが終わるまで放置。(再起動とかはしちゃいけません。)

# zpool status
  pool: tank0
 state: ONLINE
  scan: resilvered 200G in 0h41m with 0 errors on Thu Dec 27 13:58:41 2018
config:
        NAME                                            STATE     READ WRITE CKSUM
        tank0                                           ONLINE       0     0     0
          mirror-0                                      ONLINE       0     0     0
            gptid/942be1e0-46dd-11e2-bc4e-bc5ff483903d  ONLINE       0     0     0
            ada1p2                                      ONLINE       0     0     0
errors: No known data errors

無事置き換わったようだ。あとは残っていたHDDをOFFLINEにして再度同じ作業をやればOK。一体どうしたものか・・・と思っていたが、やってみるとかなり簡単で、こうしてメモとしておけばよさそう。