先に起動ディスクをHDDからUSBメモリに変更してからしばらく運用を続けていたところ、深刻な性能問題に直面してHDDに戻したのは先月のことだった。
定常的に書込が発生するディレクトリは当然ながら外出ししており、たまのmake installworld
くらいしかろくな書込が発生することはなかったにも関わらず、気が付くと、そのmake installworld
に8時間も掛かるようになってしまっていた。
単に、USBメモリ自体がずっと通電しての読み書き(書くのはまれだが)に耐えうる設計になっていないからなのか、特定部分へのアクセスが重なった結果へたってしまったのかはよくわからないが、ともかく常時稼働は荷が重かったということは言えるだろう。
HDDに戻したところたちまち安定して快適にはなったが、ただの撤退ではおもしろくないので、安くなってきたSSDを導入することにした。ちょうど、Crucial m4 64GBが7,000円を切っているので、これを採用した。
さて、FreeBSDに限らないが、SSDを使う上で当然気になるのがTRIM命令のサポート有無である。FreeBSD 9.0や8.3ではadaドライバ、GEOM、UFS2がこれをサポートしており、シンプルな非冗長構成ではすんなりこれを享受できる。だが、ZFSは未サポート、さらにGEOMもmirrorやjournalを通すとUFS2がTRIM命令のサポート有無を検知できず無効になってしまうようだ。
何とも残念な現状だが、システム(前述のように/usr/local
, /var
等は含まない)は書込がほとんど発生せず、また同居予定のZFS ZIL, L2ARCパーティションは多くの書込があるものの、冗長化した上でたまに片肺にしてTRIMすれば十分だと考えた。そして/
のファイルシステムは、ZFSとUFS+GEOM mirrorを比較検討し、読み込み主体であることと、先にTRIMがサポートされそうなことから後者にした。信頼性を重視し、ジャーナリングはGEOM journalではなくSUJを選択。
前置きが長くなったが、購入したSSD二台にシステムを載せ替える手順のメモを開陳。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# Suppose the SSD #2 is at /dev/ada2 # TRIM the disk using newfs(8) newfs -E ada2 # Create a GPT partition table gpart create -s got ada2 # Put the FreeBSD boot loader in it # "-b 34" will suffice but it is always nice to align partitions with 4KB gpart add -b 40 -s 64k -t freebsd-boot ada2 # Install the (non-ZFS) boot loader gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 ada2 # Add a UFS partition for the system root # Create a partition for / (20GB) gpart add -t freebsd-ufs -s 20g ada2 # Make it GEOM mirrored gmirror load gmirror label root ada2p2 # Make sure GEOM mirror is available on boot echo 'geom_mirror_load="YES"' >> /boot/loader.conf # Create a UFS2 filesystem on it newfs -j -t /dev/mirror/root # Copy the system root to /dev/mirror/root using: # - dump(8) & restore(8) from a snapshot of the current / if it is UFS # - rsync -aHAX # or: # - good old tar|tar # Add a swap partition (20GB - sufficiently bigger than the amount of RAM on this box) gpart add -t freebsd-swap -s 20g ada2 # Make it GEOM mirrored gmirror label swap ada2p3 # Create a partition for ZIL (8GB - half the amount of the RAM on this box) gpart add -t freebsd-zfs -l zil1 -s 8g ada2 zpool add tank log /dev/gpt/zil1 # Use the rest of the disk for ZFS L2ARC gpart add -t freebsd-zfs -l l2arc1 ada2 zpool add tank cache /dev/gpt/l2arc1 # Edit /etc/fstab /dev/mirror/root / ufs rw,noatime 1 1 /dev/mirror/swap none swap sw 0 0 # Edit /boot/loader.conf vfs.root.mountfrom="ufs:/dev/mirror/root" # # Boot from the SSD #2 # # This may be needed zpool import -fa # Suppose the SSD #1 is at /dev/ada2 # TRIM the disk using newfs(8) newfs -E ada1 # Create a GPT partition table gpart create -s gpt ada1 # Put the FreeBSD boot loader in it gpart add -b 40 -s 64k -t freebsd-boot ada1 gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 ada1 # Get the system root mirrored gpart add -t freebsd-ufs -s 20g ada1 gmirror insert root ada1p2 # Get the swap area mirrored gpart add -t freebsd-swap -s 20g ada1 gmirror insert swap ada1p3 # Get the ZIL area mirrored gpart add -t freebsd-zfs -l zil0 -s 8g ada1 zpool attach tank /dev/gpt/zil1 /dev/gpt/zil0 # Add a second L2ARC partition (mirroring N/A) gpart add -t freebsd-zfs -l l2arc0 ada1 zpool add tank cache /dev/gpt/l2arc0 |
こんな感じです。けっこう簡単だよね。
ポイントは、移行後の新システムを作る際、単一パーティションでGEOM mirrorを構成し、そこに/
を作って構築すること。GEOM mirrorは、マウントした状態のファイルシステムパーティションをミラー構成にすることはできないようだ。上記のように片肺(というか単肺)のGEOM mirrorボリュームを作ってそこからブートすれば、あとは二肺目をそこにアタッチ(GEOM用語ではinsert)するだけで良い。
おまけ情報1
こうして構築は完了したが、不意のシステムダウンが起きると、リブート後にZFSボリュームが見えない(zpool import
しないといけない)問題が発生しており少し困っている。最近VirtualBoxが不安定(4.1.10くらいから?)で、たまにカーネルパニックを起こすので少し深刻だ。
そのときは/var/named/etc/namedb
が見えないため/etc/rc.d/named
が/etc/namedb
を壊してしまうので、シングルユーザモードで
1 2 |
ln -sf /var/named/etc/namedb /etc/ zpool import -fa |
と直してからスタートアップする必要がある。
おまけ情報2
GEOM mirrorは何やら曲者で、まちがえて作ってしまったときなどに、削除しようとgmirror stop name
としてもGPTラベル名やGPTIDやらのデバイス名で設定が生き残ってしまう。ちゃんと削除するには、
1 2 |
sysctl kern.geom.label.gpt.enable=0 sysctl kern.geom.label.gptid.enable=0 |
と一時的に別名デバイスが生えない状態にしてから
1 |
gmirror stop <i>name</i> |
とすれば良いようだ。
おまけ情報3
以前発見した問題が解決。少なくともFreeBSD 9.0では、eSATA port multiplierにディスクを差したときに既存ディスクのデタッチが発生しないようになっていた。ヤッタネ\(^o^)/