HOME 用途を別の ZFS pool に移行する
新し目の OpenSolaris をインストールすると、HOME 領域のファイルシステムも起動領域を含む rpool に内包される形式で作成されるのだが、root と HOME は媒体を分けておきたいよね?というのが旧世紀遺物エンジニアの感覚なので、/export/home 配下を別途作成した ZFS pool に移行することに。
現状だと、rpool は mirror 限定なので、RAID-Z/Z2 とかで安全性と容量のバランスを取りたいような領域がある場合も、rpool からの分離が必須。
流石にマルチユーザ稼働状態で /export/home 配下を弄繰り回すのは危険極まりないので、まずはシングルユーザモードで起動しておいて、移行先の新規 ZFS pool を作成。
$ zpool create -m none homepool /dev/dsk/c7t2d0
"-m none" は「pool 作成後も mount しない」ためのオプション。
"zfs receive" において「受け側ファイルシステムをマウントしない」ための "-u" オプションが指定できるので、下手に暫定位置にマウントするよりは、"zfs send" では「マウント位置を含むプロパティの全複製」をしておいて、マウントしない状態の pool において "zfs receive" で受ける方が簡単。
シングルユーザモードで起動した場合、メンテナンスモードでは /export 配下のファイルシステムも未マウント状態なので、未マウントファイルシステム間での複製になるから、途中アクセス等の心配も無いし。
次は、スナップショットを作成しておいて、"zfs send" + "zfs receive" で複製を実施。
$ zfs snapshot -r rpool/export/home@2011-04-09.01 $ zfs send -vRp rpool/export/home@2011-04-09.01 | zfs receive -uvdF homepool
"zfs snapshot" の -r と、"zfs send" の -R は共に再帰実行の指定。-v は verbose ね。"zfs receive" の -F は初回複製の際に、書き込みを強制するためのもの。
"zfs send" の -p は属性情報(property)を転送するための指定。マウント位置情報ごと複製するためには必須。
"zfs receive" の -u は、先述したように「転送先をマウントしない」指定。
"zfs receive" の -d は、例えば rpool/export/home ファイルシステムからの送信を受けた際に、export/home ファイルシステムが無ければ新規作成する、的な挙動を指定するもの。
マニュアルを読む限りでは、-d と -e の2種類のパス解釈方式があるのだけれど、何というか今回の用途的にはどちらもイマイチしっくり来ないので、比較的マシな仕様である -d を採用。
「しっくり来ない」のは、上記のコマンド実行により、homepool 配下に homepool/export なる微妙なファイルシステムが作成されてしまう点。
$ zfs list -r homepool NAME USED AVAIL REFER MOUNTPOINT homepool 30.1M 219G 21K none homepool/export 30.0M 219G 21K none homepool/export/home 30.0M 219G 21K /export/home homepool/export/home/fujiwara 29.9M 219G 29.9M /export/home/fujiwara $
まぁ、「マウントされない無用のファイルシステム」という点では、homepool もそうなのだが....
かといって、"zfs receive" の -e で受けると、それはそれで期待に反した構成になってしまうので、とりあえず -d で良いか... という判断。
どーしても気に入らない場合は、一括 send/receive ではなく、階層を辿りつつ1つ1つ複製するしかなさそう。まぁ、その方が古き良き UNIX っぽい気がしないでもないけどね。
以上で複製が完了したので、次回起動の際に rpool 側の HOME 領域がマウントされないように、/export/home 配下に対して canmount プロパティを off にしておく。
$ zfs list -H -r rpool/export/home |
awk '{ print $0 }' |
while read target; do zfs set canmount=off ${target}; done
速攻で "zfs destroy" しても構わないのだけれど、「再起動してみたら上手く複製できてませんでした」では目も当てられないので、安全が確認されるまでは残しておくのが吉 > 旧ファイルシステム
以上で移行が完了した筈なので、再起動してみる .... あれ?変なエラーメッセージが出てるぞ?
/export 配下は空じゃないからマウント出来なかったよ(意訳)
あちゃー、/export/home 配下のマウントに失敗したか?と思い、とりあえず login してみると、/export/home 配下へのアクセスは問題なく実施できる。
おかしいなぁ?と df 出力を見てみると、homepool/export/home はマウントされているのに、rpool/export はマウントされていない!
あ!わかった!rpool 配下の /export よりも先に、homepool 配下の /export/home のマウント処理が走ってしまってるんだ!で、"mkdir -p" 相当が実施されてしまっているに違いない。
あぁ、複数 pool 間での実行優先順位って、どーなってんだろ? zpool(1) にも zfs(1) にも、依存関係の情報なんて書いてないしなぁ。
考えること暫し ..... 辞書順(homepool → rpool)で処理してんじゃねぇ?ということで、ものは試しと、pool 名を zhomepool に改めて、もう一度移行手順を再実行してみると .... 上手くいった!
ひょっとして、ZFS のサンプルにおける pool 名が tank なのは、rpool との順序性まで考えた上での選択なのかも?などと思ってみたり(笑)