2008.03.19 ZFSメンテナンスの日々 #7 ZFS Boot 編 ZFS Boot を攻めてみる。PC 1 台セットアップする手順を再現するの は大変なので, とりあえず USB メモリにでも。。 (^^; liveCD 作れるなら, pure ZFS 環境があなたの手に…。 動作確認環境 Let's note CF-R4 第三世代型(CF-R4 JW4AXR) FreeBSD 8.0-current 2008-03-18 版 with ZFS Boot パッチ 検証環境は 8-current ですが, 今ごろ以降の 7-stable でも ok と 思われる。7.1-R (出たら)安心して使えるかな。もっとも ZFS 本体 にかかわる変更が MFC されていないので, ZFS そのものの安定性を 考慮するとなんとも言えないところですが。。 あぁそうそう。USB からブートできるかどうかの問題があるので BTX のバージョンが 1.02 になってないとメディアが限定されます (IDE タイプの HDD のみとか)。確か現時点では MFC されてなかっ た記憶が…。 なおインストール先の USB メモリは下記のものとなります(2GB 品)。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - umass0: on uhub1 umass0: Get Max Lun not supported (STALLED) da0 at umass-sim0 bus 0 target 0 lun 0 da0: Removable Direct Access SCSI-2 device da0: 40.000MB/s transfers da0: 1959MB (4014078 512 byte sectors: 255H 63S/T 249C) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 一般的な HDD へのインストールを想定して, 1.スライスを切る, 2. disklabel を切る, 3. さらに swap (128MB) を確保するようにしま す。もちろんファイルシステムは ZFS で…。 /dev/da0 /dev/da0s1 FreeBSD スライス /dev/da0s1a ZFS /dev/da0s1b swap また基本的なセットアップが終わるまでは sysctl kern.geom.debugflags=16 を実行/有効にしておく。 sade(8) を使ってスライスを切ります。sade(8) は sysinstall(8) のスライス/ディスクラベル操作を抜き出したものです。スライスを まっさらにして Use Entire Disk (A) を選びます。さらに Write Changes(W) で保存します(確認の Yes/No を聞いてきます)。直後ブ ートローダーを聞いてくるのでとりあえず BootMgr を選択しておき ます。Q で抜けて, 次のステップ(ディスクラベルを切る)に進みます。 今回, スライス全体で 1953MB 確保できたので d パーティションに 1825MB, b パーティションに 128MB を割り当てます。なお d パー ティションは一時的に UFS を割り当てます(/tank)。いきなり a パーティション(/) は切れないようです(後述)。割り当てた後, Write(W) します(確認の Yes/No を聞いてきます)。 この時 /dev/da0s1d は /tank にマウント, /dev/da0s1b はスワップ オンされてるので, それぞれ umount / swapoff しておきます。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - umount /tank swapoff /dev/da0s1b - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - bsdlabel -e da0s1 を実行して調整します。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # /dev/da0s1: 8 partitions: # size offset fstype [fsize bsize bps/cpg] b: 262522 3737600 swap c: 4000122 0 unused 0 0 # "raw" part, don't edit d: 3737600 0 4.2BSD 2048 16384 28552 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - これを下記のように変更します。 1. d → a に変更及び順番を変更, 2. 4.2BSD以降を削除して ZFS に 変える。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # /dev/da0s1: 8 partitions: # size offset fstype [fsize bsize bps/cpg] a: 3737600 0 ZFS b: 262522 3737600 swap c: 4000122 0 unused 0 0 # "raw" part, don't edit - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - zpool / zfs を作成しましょうということで, 下記手順で作ってみる。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - zpool create tank da0s1a zfs set atime=off tank zfs create tank/usr zfs create tank/var zfs create tank/tmp zfs create tank/home zfs create tank/compat zfs create tank/usr/local zfs create -o readonly=on tank/var/empty zfs snapshot -r tank@origin - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ブートファイルシステムを指定する。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - zpool set bootfs=tank tank - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ※ローダーは /boot/loader とファイルシステムから固定の位置なので tank 上に存在することを指定する。 OS をインストールする。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cd /usr/src env DESTDIR=/tank make installworld distribution installkernel - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - とりあえず zpool.cache を作る。これ専用に作るコマンド欲しいなぁ。。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - cp /boot/zfs/zpool.cache /tank/boot/zfs/ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ちなみに pure ZFS 環境最大の罠のだったりする。 > /boot/zfs/zpool.cache このあたりの事情については後日にでも。 ZFS Zoot ローダーをインストールする。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - zpool export tank dd if=/boot/zfsboot1 of=/dev/da0s1 bs=512 count=1 dd if=/boot/zfsboot2 of=/dev/da0s1 bs=512 seek=1024 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - その他細かい設定を行う。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - zpool import tank vi /tank/etc/fstab - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # Device Mountpoint FStype Options Dump Pass# tank / zfs rw,noatime 0 0 /dev/da0s1b none swap sw 0 0 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - vi /tank/boot/loader.conf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - zfs_load="YES" vm.kmem_size="671088640" vm.kmem_size_max="671088640" vfs.zfs.prefetch_disable="1" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - vi /tank/etc/rc.conf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - zfs_enable="YES" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - vi /tank/etc/sysctl.conf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - vfs.zfs.zil_disable="1" - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - touch /tank/etc/wall_cmos_clock cp -p /tank/usr/share/zoneinfo/Asia/Tokyo /tank/etc/localtime - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - というわけで決断。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - zfs set mountpoint=legacy tank - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - この直後 tank から下にアクセスできなくなるので以後再起動 して残りを設定する。ちなみに zpool import したまま(つまり zpool export してはならない)にしておくことは重要で, pure ZFS 環境極大の罠だったりする。 起動後すぐに single user mode に移行し, 以下のセットアップ を行う。 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - zfs set mountpoint=/compat tank/compat zfs set mountpoint=/home tank/home zfs set mountpoint=/tmp tank/tmp zfs set mountpoint=/usr tank/usr zfs set mountpoint=/var tank/var - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - これでセットアップ完了。USB ブート可能な pure ZFS 環境が ゲットだぜ!と。 さて。ここまでの手順の一番重要な ZFS Boot Loader は下記のパ ッチとなります。 http://blog.ninth-nine.com/archives/zfsboot_20080319.tar.bz2 出どころは perforce.freebsd.org で開発中の pjd 氏と dfr 氏 の作業途中のコードに, simokawa さん作業分を反映したものと なります。ソースを見るとわかりますが, 1. zfsboot1, zfsboot2 の導入 zfsboot1 は boot1 の ZFS 対応版で, boot2 (zfsboot2?)の位置 が UFS とは違うため, その分を反映してあります。ただし, LBA のみのコードになっており, 古い BIOS では動きません。 zfsboot2 は ZPOOL/ZFS を解釈できる boot2 で, ファイルシス テムを解釈した上で /boot/loader を呼び出します。zfsboot2 が解釈可能なファイルシステムは compression=on,off,lzjb / checksum=on,off,fletcher2,fletcher4,sha256 の組み合わせと なります。つまり gzip で圧縮されてたりすると認識できません。 このあたりのコードのおおよそは dfr 氏の作業によるものです。 ディスクレイアウト等については参考文献の ondiskformat0822.pdf を御覧ください。ブートブロックが先頭から 512KB のところか ら始まる仕様なのが確認できます。 2. zfsboot コンパイル中に btxld が死にます。よって事前に btxld を入れ換えた上で buildworld しなければなりません。 3. ディスクラベルが無くても boot できます。 4. NFS と TFTP サポートは無効になります(ZFS サポートのコードが 大きすぎるため) 5. zpool export していてもとりあえず loader は立ち上がります。 以上 2〜5 までを simokawa さんのノウハウを反映したものとな ります。 6. lsdev した時に ZFS パーティションが見えます:-)。 7. zpool import してないと起動しません。 8. /boot/zfs/zpool.cache が zpool import した状態でないと起動 しません。 以上私ははまりました:-)。 なお ZFS パーティションの扱いは 7.0-R の後に入ったコードとな ります。8-current はもちろんのこと, 現時点で 7-stable でも通 用します。もっともとんでもない蟲がいたので, 今以降のコードを 使用した方がいいです。 また UFS 環境下でもいいのですが, 上記パッチをあてて, 一通り make installworld した後で作業することを前提としています。 参考文献: http://bsdhouse.org/yamasa/diary/20080311.html http://bsdhouse.org/yamasa/diary/20071119.html http://docs.sun.com/app/docs/doc/819-6260/6n89n6cis?l=ja&a=view http://docs.sun.com/app/docs/doc/819-6260/gavwg?a=view http://www.sun.com/bigadmin/hubs/multilingual/japanese/content/zfs-source.jsp http://opensolaris.org/os/community/zfs/whatis/ http://opensolaris.org/os/community/zfs/docs/ondiskformat0822.pdf Thanks: pjd@F.o 氏と dfr@F.o 氏の作業。 simokawa@F.o さんには色々と教えていただきました。 ところで仕切り(パーティション)ってありましたっけ? (爆) Written by 重村法克