Seichan です.こんばんわ.
2TB あたりから 1Block が 512Byte ではなく,4KB な HDD が出てますよね.
内部的には 4KB なのですが,表面上は 512Byte/Sector と偽るようですが…
512Byte のままでも使えますが,パフォーマンスの観点から 4KB Block アクセスさせた方がヨロシイ感じですので,自宅のファイルサーバもディスク更新に合わせて 4KB 化してみました.
AFT(4k block) HDD を ZFS で使う場合の良い方法
FreeBSD で 4KB ZFS とするにあたり,2つの方法があります.
- loader prompt で kern.cam.ada.X.quirks=”1″ を設定する方法
- GPT Partition でパーティション開始位置を 4K に設定する方法
どちらの方法でも 4K 化は出来るのですが,Seichan 的に前者はディスクの追加削除時に追いかけるのが面倒なのでは? と思った為,後者の GPT で開始位置を合わせる方法で実施する事にしました.
# ディスク番号 (ada0 とか) が変わらない環境であれば,kern.cam.ada.X.quirks の方が絶対楽です.
GPT で合わせる場合はこんな感じになります.da1 da2 da3 の3本を ZFS 化します.
1. gpart create で GPT ディスクを作成する
3本のディスクを GPT パーティションを作成すべく,gpart create します.
# gpart create -s gpt da1 da1 created # gpart create -s gpt da2 da2 created # gpart create -s gpt da3 da3 created
2. gpart add で GPT パーティションを作成する
GPT ディスクとなった3本のディスクに,パーティションを作成します.パーティション種別は ZFS 用ですので freebsd-zfs です.
-a オプションがアライメントサイズで,4k のアライメントを取ってそれ以降にパーティションを作る.ということになります.
# gpart add -a 4k -t freebsd-zfs da1 da1p1 added # gpart add -a 4k -t freebsd-zfs da2 da2p1 added # gpart add -a 4k -t freebsd-zfs da3 da3p1 added
3. 作成されたパーティションを確認する
(2.) で作成したパーティションを確認します.freebsd-zfs の開始位置が 40 から始まっていれば 4K のアライメントが取れている事になります.
# gpart show da1 > 34 41942973 da1 GPT (20G) 34 6 - free - (3.0k) 40 41942960 1 freebsd-zfs (20G) 41943000 7 - free - (3.5k)
x. ZFS を作成する (これは失敗パターンです.例示の為)
(3.) 完了後,なにも考えず ZFS(zpool) を作成すると,当然作成は出来ます.ですが,zdb で確認すると ashift: 9 となり,512Byte セクタアクセスとなってしまいます.ちなみに,4K セクタアクセスは ashift: 12 です.
# zpool create pool0 raidz da1p1 da2p1 da3p1 # zdb -C pool0 | grep ashift ashift: 9
ということで,こういう状態になっている場合は zpool を一度削除してください.
4. gnop で透過的な 4KB セクタデバイスを作成する
GEOM_NOP を使う事でディスクのセクタサイズ等を変えた透過デバイスを作成する事が出来ます.kern.cam.ada.X.quirks を使う場合はこの手順がいらない為,デバイス名が変わらない場合は絶対楽と言ったのはこういう理由でした.
# gnop create -S 4096 da1p1 # gnop create -S 4096 da2p1 # gnop create -S 4096 da3p1 # gnop status Name Status Components da1p1.nop N/A da1p1 da2p1.nop N/A da2p1 da3p1.nop N/A da3p1 # gnop list da1p1.nop Geom name: da1p1.nop WroteBytes: 0 ReadBytes: 249856 Writes: 0 Reads: 0 Error: 0 WriteFailProb: 0 ReadFailProb: 0 Offset: 0 Providers: 1. Name: da1p1.nop Mediasize: 21474795520 (20G) Sectorsize: 4096 Mode: r0w0e0 Consumers: 1. Name: da1p1 Mediasize: 21474795520 (20G) Sectorsize: 512 Stripesize: 0 Stripeoffset: 20480 Mode: r0w0e0
gnop create の -S オプションでセクタサイズを 4096 (4k) にして透過デバイスを作成します.作成された結果は gnop status や gnop list で確認出来ます.
gnop list の Providers: にある [デバイス名].nop のところの Sectorsize が 4096 であることを確認してください.
5. ZFS を作成する (成功パターン)
gnop デバイスを対象に ZFS (zpool) を作成します.デバイス名を gnop で作成したデバイス名にする事だけは忘れないでください.
作成後 zdb コマンドで ashift: 12 であることを確認しましょう.
# zpool create pool0 raidz da1p1.nop da2p1.nop da3p1.nop # zdb -C pool0 | grep ashift ashift: 12
6. gnop デバイスを削除する
(5.) で4K アクセスの ZFS が作成出来ました.ですが,gnop デバイスを指定して作成していますので,再起動時そんなデバイスは無い.と怒られてしまいます.
また,ZFS 作成時に ashift の値が決まり,以降はなにをやっても ashift は変わらない為,ここで gnop デバイスは削除してしまいます.
gnop デバイスを削除するにあたり,一度 ZFS (zpool) をエクスポートします.その後,gnop destroy で先ほど作成した gnop デバイスを全て削除します.
最後に,エクスポートしていた zpool をインポートします.この際,特になにも考えずに zpool import しても大丈夫です.
無事インポート出来たら,念のため ashift を確認してみましょう.変わらずに ashift: 12 であれば,以降は 4K アクセスとなります.
# zpool export pool0 # gnop destroy da1p1.nop da2p1.nop da3p1.nop # zpool import pool0 # zdb -C pool0 | grep ashift ashift: 12
ちょっとステップが多いのが難点ですが,kern.cam.ada.X.quirks が存在しないバージョンでも対応できるので,その点は本方法は利点なのだと思います.
コメント