FreeBSD10でRAID-Z2のディスク交換をしたメモ

# 前提

* 我が家のファイルサーバのお話です。業務用システムではありません。
* FreeBSD 10で構築していますが、私はFreeBSDに不慣れです。
* ルートパーティションそのものもZFSになっています。
* プールはRAID-Z2で構成しています。

# ZFSの構成ディスクが壊れた

`zpool scrub zroot` を実行したらひどく時間がかかり、repairedなんて表示がありました。ガーン

`dmesg` してみた結果、ATAのDRDY ERRが大量に出ている状況。(ﾉ∀`)ｱﾁｬｰ

```
...snip...
(ada0:ahcich2:0:0:0): CAM status: ATA Status Error
(ada0:ahcich2:0:0:0): ATA status: 41 (DRDY ERR), error: 40 (UNC )
(ada0:ahcich2:0:0:0): RES: 41 40 38 06 40 40 00 00 00 00 00
(ada0:ahcich2:0:0:0): Retrying command
(ada0:ahcich2:0:0:0): READ_FPDMA_QUEUED. ACB: 60 10 38 06 40 40 00 00 00 00 00 00
(ada0:ahcich2:0:0:0): CAM status: ATA Status Error
(ada0:ahcich2:0:0:0): ATA status: 41 (DRDY ERR), error: 40 (UNC )
(ada0:ahcich2:0:0:0): RES: 41 40 38 06 40 40 00 00 00 00 00
(ada0:ahcich2:0:0:0): Retrying command
(ada0:ahcich2:0:0:0): READ_FPDMA_QUEUED. ACB: 60 10 38 06 40 40 00 00 00 00 00 00
(ada0:ahcich2:0:0:0): CAM status: ATA Status Error
(ada0:ahcich2:0:0:0): ATA status: 41 (DRDY ERR), error: 40 (UNC )
(ada0:ahcich2:0:0:0): RES: 41 40 38 06 40 40 00 00 00 00 00
(ada0:ahcich2:0:0:0): Error 5, Retries exhausted
```

他のディスクは大丈夫そうだったので、ada0故障としてディスクを交換することになりました。

# 事前調査

問題のあったada0の情報を調べておきます。

## シリアルナンバー

```
freebsd# camcontrol identify ada0
pass0: <WDC WD20EZRX-00D8PB0 80.00A80> ATA-9 SATA 3.x device
pass0: 300.000MB/s transfers (SATA 2.x, UDMA6, PIO 8192bytes)

protocol              ATA/ATAPI-9 SATA 3.x
device model          WDC WD20EZRX-00D8PB0
firmware revision     80.00A80
serial number         WD-WCC4M2770577
WWN                   50014ee2b4ca1811
cylinders             16383
heads                 16
sectors/track         63
sector size           logical 512, physical 4096, offset 0
LBA supported         268435455 sectors
LBA48 supported       3907029168 sectors
PIO supported         PIO4
DMA supported         WDMA2 UDMA6
media RPM             5400
...snip...
```

## パーティション情報

```
freebsd# gpart show ada0
=>        34  3907029101  ada0  GPT  (1.8T)
          34           6        - free -  (3.0K)
          40        1024     1  freebsd-boot  (512K)
        1064     4194304     2  freebsd-swap  (2.0G)
     4195368  3902833760     3  freebsd-zfs  (1.8T)
  3907029128           7        - free -  (3.5K)
```

元々のディスクのパーティション構成を参照しましたが、他の3台も同じ構成なので特にこだわりはありません。
次の作業はZFSパーティションの `rawuuid` を調査するためのものです。ada0p3がZFSパーティションなのは先のコマンドでわかっていますので、そこを確認します。

```
freebsd# gpart list ada0
Geom name: ada0
modified: false
state: OK
fwheads: 16
fwsectors: 63
last: 3907029134
first: 34
entries: 128
scheme: GPT
Providers:
...snip...
3. Name: ada0p3
   Mediasize: 1998250885120 (1.8T)
   Sectorsize: 512
   Stripesize: 4096
   Stripeoffset: 0
   Mode: r1w1e2
   rawuuid: edea0237-d1fa-11e3-9ad5-bc5ff4fc4f55
   rawtype: 516e7cba-6ecf-11d6-8ff8-00022d09712b
   label: zfs0
   length: 1998250885120
   offset: 2148028416
   type: freebsd-zfs
   index: 3
   end: 3907029127
   start: 4195368
Consumers:
1. Name: ada0
   Mediasize: 2000398934016 (1.8T)
   Sectorsize: 512
   Stripesize: 4096
   Stripeoffset: 0
   Mode: r2w2e5
```

`edea0237-d1fa-11e3-9ad5-bc5ff4fc4f55` ですね。

## ZFSの構成ディスク情報

冗長かもしれませんが、一応見ておきます。

```
freebsd# zdb
zroot:
    version: 5000
    name: 'zroot'
    state: 0
    txg: 35377
    pool_guid: 8898421204376808293
    hostid: 4266313884
    hostname: 'freebsd'
    vdev_children: 1
    vdev_tree:
        type: 'root'
        id: 0
        guid: 8898421204376808293
        children[0]:
            type: 'raidz'
            id: 0
            guid: 3251282675639060840
            nparity: 2
            metaslab_array: 33
            metaslab_shift: 35
            ashift: 12
            asize: 7992984469504
            is_log: 0
            create_txg: 4
            children[0]:
                type: 'disk'
                id: 0
                guid: 12425838491564392765
                path: '/dev/gptid/edea0237-d1fa-11e3-9ad5-bc5ff4fc4f55'
                phys_path: '/dev/gptid/edea0237-d1fa-11e3-9ad5-bc5ff4fc4f55'
                whole_disk: 1
                DTL: 123
                create_txg: 4
            children[1]:
                type: 'disk'
                id: 1
                guid: 11970705104448422009
                path: '/dev/gptid/917210e6-d1df-11e3-ad9c-bc5ff4fc4f55'
                phys_path: '/dev/gptid/917210e6-d1df-11e3-ad9c-bc5ff4fc4f55'
                whole_disk: 1
                DTL: 122
                create_txg: 4
            children[2]:
                type: 'disk'
                id: 2
                guid: 3324830681772726295
                path: '/dev/gptid/2622a6c7-d179-11e3-a601-bc5ff4fc4f55'
                phys_path: '/dev/gptid/2622a6c7-d179-11e3-a601-bc5ff4fc4f55'
                whole_disk: 1
                DTL: 121
                create_txg: 4
            children[3]:
                type: 'disk'
                id: 3
                guid: 11650913671101100370
                path: '/dev/gptid/c62cbbc8-d131-11e3-b779-bc5ff4fc4f55'
                phys_path: '/dev/gptid/c62cbbc8-d131-11e3-b779-bc5ff4fc4f55'
                whole_disk: 1
                DTL: 229
                create_txg: 4
    features_for_read:
```

## zpoolの状態

プールとしては異常ありません。2回目のscrubに恐ろしく時間がかかったのでキャンセルしました。

目的のディスクは一番上ですね。

```
freebsd# zpool status
  pool: zroot
 state: ONLINE
  scan: scrub canceled on Sun Nov 23 15:57:15 2014
config:

        NAME                                            STATE     READ WRITE CKSUM
        zroot                                           ONLINE       0     0     0
          raidz2-0                                      ONLINE       0     0     0
            gptid/edea0237-d1fa-11e3-9ad5-bc5ff4fc4f55  ONLINE       0     0     0
            gptid/917210e6-d1df-11e3-ad9c-bc5ff4fc4f55  ONLINE       0     0     0
            gptid/2622a6c7-d179-11e3-a601-bc5ff4fc4f55  ONLINE       0     0     0
            gptid/c62cbbc8-d131-11e3-b779-bc5ff4fc4f55  ONLINE       0     0     0

errors: No known data errors
```

## メモする

情報を整理してメモしておきます。

* 問題があるディスクは `ada0`
* ada0 のモデルナンバーは `WD20EZRX` (Western Digital社のWD Greenシリーズ 2TB キャッシュ64MB)
* ada0 のシリアルナンバーは `WD-WCC4M2770577`
* ZFSのプール `zroot` では `gpart list ada0` の結果より `gptid/edea0237-d1fa-11e3-9ad5-bc5ff4fc4f55` が該当

# ディスク交換

## ディスクをアレイから外す

当該ディスクをアレイから外しておきます(OFFLINEにする)。

```
freebsd# zpool offline zroot gptid/edea0237-d1fa-11e3-9ad5-bc5ff4fc4f55
freebsd# zpool status
  pool: zroot
 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: scrub canceled on Sun Nov 23 15:57:15 2014
config:

        NAME                                            STATE     READ WRITE CKSUM
        zroot                                           DEGRADED     0     0     0
          raidz2-0                                      DEGRADED     0     0     0
            12425838491564392765                        OFFLINE      0     0     0  was /dev/gptid/edea0237-d1fa-11e3-9ad5-bc5ff4fc4f55
            gptid/917210e6-d1df-11e3-ad9c-bc5ff4fc4f55  ONLINE       0     0     0
            gptid/2622a6c7-d179-11e3-a601-bc5ff4fc4f55  ONLINE       0     0     0
            gptid/c62cbbc8-d131-11e3-b779-bc5ff4fc4f55  ONLINE       0     0     0

errors: No known data errors
```

## シャットダウンしてディスク交換

間違えてディスクを取り外してしまう事故を避けたかったので、一旦シャットダウンしてディスクを交換します。

今回用意したディスクは WD20EFRX (Western Digital社 WD Redシリーズ)。ヨドバシカメラで12,000円でした。長持ちしてくれますように...

ちなみに壊れたディスクの `Power_On_Hours` SMART値は2126。88.58日ということで、のべ3ヶ月くらいしか働いてくれませんでした。他の3台もまとめて購入しているので、もしかしたらじきにダメになるかもしれません。

# 新しいディスクをRAID-Z2に組み込む

## 新しいディスクにGPTを作成

新しいディスクはada0で認識しているはずです。
`gpart show ada0` して、GPTが作られていなければ正解ということで。

問題なければada0にGPTを作ります。

```
freebsd# gpart show ada0
gpart: No such geom: ada0.
freebsd# gpart create -s gpt ada0
ada0 created
freebsd# gpart show ada0
=>        34  3907029101  ada0  GPT  (1.8T)
          34  3907029101        - free -  (1.8T)
```

## パーティションを作成

パーティションテーブルをバシバシ作っていきます。交換前に調べたものか、他のディスクの構成をパクります。

今回やり忘れてしまったのですが、ここでGPTラベルをつけておくと良いです(`-l ラベル名`)。

```
freebsd# gpart add -i 1 -t freebsd-boot -b 40 -s 1024 ada0
ada0p1 added
freebsd# gpart add -i 2 -t freebsd-swap -b 1064 -s 4194304 ada0
ada0p2 added
freebsd# gpart add -i 3 -t freebsd-zfs -b 4195368 -s 3902833760 ada0
ada0p3 added
freebsd# gpart show ada0
=>        34  3907029101  ada0  GPT  (1.8T)
          34           6        - free -  (3.0K)
          40        1024     1  freebsd-boot  (512K)
        1064     4194304     2  freebsd-swap  (2.0G)
     4195368  3902833760     3  freebsd-zfs  (1.8T)
  3907029128           7        - free -  (3.5K)
```

## 組み込み

今作ったfreebsd-zfsパーティションのrawuuid(GPTID)を調べます。

```
freebsd# gpart list ada0
Geom name: ada0
modified: false
state: OK
fwheads: 16
fwsectors: 63
last: 3907029134
first: 34
entries: 128
scheme: GPT
Providers:
1. Name: ada0p1
...snip...
3. Name: ada0p3
   Mediasize: 1998250885120 (1.8T)
   Sectorsize: 512
   Stripesize: 4096
   Stripeoffset: 0
   Mode: r0w0e0
   rawuuid: 12357f00-73da-11e4-9e4c-bc5ff4fc4f55
   rawtype: 516e7cba-6ecf-11d6-8ff8-00022d09712b
   label: (null)
   length: 1998250885120
   offset: 2148028416
   type: freebsd-zfs
   index: 3
   end: 3907029127
   start: 4195368
...snip...
```

`12357f00-73da-11e4-9e4c-bc5ff4fc4f55` が新しいGPTIDとなります。

置き換え対象の部分の(ZFSの)GUIDを調べます。
`zpool status` でOFFLINEになっているところの名前です。古いGPTID(was gptid/xxxx)ではありません。
ちなみに`zdb`コマンドを走らせた時にも出てきます。

```
freebsd# zpool status
  pool: zroot
 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: scrub canceled on Sun Nov 23 15:57:15 2014
config:

        NAME                                            STATE     READ WRITE CKSUM
        zroot                                           DEGRADED     0     0     0
          raidz2-0                                      DEGRADED     0     0     0
            12425838491564392765                        OFFLINE      0     0     0  was /dev/gptid/edea0237-d1fa-11e3-9ad5-bc5ff4fc4f55
            gptid/917210e6-d1df-11e3-ad9c-bc5ff4fc4f55  ONLINE       0     0     0
            gptid/2622a6c7-d179-11e3-a601-bc5ff4fc4f55  ONLINE       0     0     0
            gptid/c62cbbc8-d131-11e3-b779-bc5ff4fc4f55  ONLINE       0     0     0

errors: No known data errors
```

GUIDは`12425838491564392765`ということがわかりました。

`12425838491564392765` を `gptid/12357f00-73da-11e4-9e4c-bc5ff4fc4f55` で置き換えれば良さそうです。

```
freebsd# zpool replace zroot 12425838491564392765 gptid/12357f00-73da-11e4-9e4c-bc5ff4fc4f55
Make sure to wait until resilver is done before rebooting.

If you boot from pool 'zroot', you may need to update
boot code on newly attached disk 'gptid/12357f00-73da-11e4-9e4c-bc5ff4fc4f55'.

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
```

親切な案内が表示されます。

* 再同期が終わるまでは再起動しないでね
* zrootプールから起動しているなら、新しくつけたディスクのぶーとコードも更新する必要があるよ
* GPT使っているならこのコマンドで出来るよ。ただ`da0`は読み替えてね: `gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 da0`

`zpool status` で状態を確認すると、`resilvering`になっており、再構築が始まっていることがわかります。

```
freebsd# zpool status
  pool: zroot
 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 Mon Nov 24 22:09:54 2014
        9.68G scanned out of 3.24T at 160M/s, 5h53m to go
        2.33G resilvered, 0.29% done
config:

        NAME                                              STATE     READ WRITE CKSUM
        zroot                                             DEGRADED     0     0     0
          raidz2-0                                        DEGRADED     0     0     0
            replacing-0                                   OFFLINE      0     0     0
              12425838491564392765                        OFFLINE      0     0     0  was /dev/gptid/edea0237-d1fa-11e3-9ad5-bc5ff4fc4f55
              gptid/12357f00-73da-11e4-9e4c-bc5ff4fc4f55  ONLINE       0     0     0  (resilvering)
            gptid/917210e6-d1df-11e3-ad9c-bc5ff4fc4f55    ONLINE       0     0     0
            gptid/2622a6c7-d179-11e3-a601-bc5ff4fc4f55    ONLINE       0     0     0
            gptid/c62cbbc8-d131-11e3-b779-bc5ff4fc4f55    ONLINE       0     0     0

errors: No known data errors
```

再構築中でも次のステップは可能です。

## ブートレコードの書き込み

先ほどの指示どおり、ブートコードを更新しておきます。

```
freebsd# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 /dev/ada0
bootcode written to ada0
```

## ラベル付け

各パーティションにラベルを付け忘れていたので、今のうちにやっておきます。
ラベルの命名については他のパーティションのものを参考にしました。
`gpart show -l ada1`などとするとラベルが見えます。

```
freebsd# gpart modify -i 1 -l gptboot0 ada0
ada0p1 modified
freebsd# gpart modify -i 2 -l swap0 ada0
ada0p2 modified
freebsd# gpart modify -i 3 -l zfs0 ada0
ada0p3 modified
freebsd# gpart show -l ada0
=>        34  3907029101  ada0  GPT  (1.8T)
          34           6        - free -  (3.0K)
          40        1024     1  gptboot0  (512K)
        1064     4194304     2  swap0  (2.0G)
     4195368  3902833760     3  zfs0  (1.8T)
  3907029128           7        - free -  (3.5K)
```

今回のようにあとからラベルを付けた場合は`/dev/gpt/`以下に現れない(更新されない)ため、後で再起動します。

## 同期後の状態確認

```
freebsd# zpool status zroot
  pool: zroot
 state: ONLINE
  scan: resilvered 805G in 2h50m with 0 errors on Tue Nov 25 01:00:29 2014
config:

        NAME                                            STATE     READ WRITE CKSUM
        zroot                                           ONLINE       0     0     0
          raidz2-0                                      ONLINE       0     0     0
            gptid/12357f00-73da-11e4-9e4c-bc5ff4fc4f55  ONLINE       0     0     0
            gptid/917210e6-d1df-11e3-ad9c-bc5ff4fc4f55  ONLINE       0     0     0
            gptid/2622a6c7-d179-11e3-a601-bc5ff4fc4f55  ONLINE       0     0     0
            gptid/c62cbbc8-d131-11e3-b779-bc5ff4fc4f55  ONLINE       0     0     0

errors: No known data errors
```

終わり！

と、ここで一度再起動して、先ほどのラベルを有効化します。
`/etc/fstab`にスワップパーティションをラベルで書いているのですが、毎回編集するのもアレなので...

# 雑感

Linuxのmdraidと比べると少し手数は多い気がしますが、ブートローダを入れるのが楽ですね。
再同期自体も使っている分だけなので早く済みました。

FreeBSDやZFSをよく理解していないので、毎度ドキドキしますね。

ところで、mdraidだと全域検査みたいなことできますけど、ZFSはどうやるんでしょうか。
scrubって、データあるところしか見てくれませんし...