#ネタ元
この記事の大部分はfreebsd-stableのアーカイブにあるreboot-less zfs volmode property refresh?に基づいている。
#動機
vm-bhyveで仮想化しているVMのディスクイメージにZFS volumeを使っている時に、ホスト側からディスクの中身にアクセスしたいことがある。例えばインストールがうまく行っておらず、ブートローダの状況を確かめたい場合など。
#前提
- FreeBSD 11.1-RELEASE-p9
#問題点
vm-bhyveでZFS volume (zvol)をディスクイメージに使うと、volmode=dev
で作成されているためそのままではGEOMベースのツールが使えない。たとえばgpart
でGPTパーティションを見ることもできないし、マウントすることもできない。
#解決法
##volmode=geomを使う
volmode=dev
になっているのがいけないので、volmode=geom
にしてやればいい。ただ話はそんなに簡単ではなく、単にzfs set volmode=geom
とするだけではダメ。
> zfs get volmode tank/vm/ubuntu/disk0
NAME PROPERTY VALUE SOURCE
tank/vm/ubuntu/disk0 volmode dev local
> gpart show /dev/zvol/tank/vm/ubuntu/disk0
gpart: No such geom: /dev/zvol/tank/vm/ubuntu/disk0.
> sudo zfs set volmode=geom tank/vm/ubuntu/disk0
> zfs get volmode tank/vm/ubuntu/disk0
NAME PROPERTY VALUE SOURCE
tank/vm/ubuntu/disk0 volmode geom local
> gpart show /dev/zvol/tank/vm/ubuntu/disk0
gpart: No such geom: /dev/zvol/tank/vm/ubuntu/disk0.
これはシステムがvolmodeプロパティを1回しか参照しないため。既にシステムから見えているzvolをvolmode=geomに変更しても、その時点ではGEOM providerとして認識されない。
###再起動する
システム自体を再起動してやれば、起動時にGEOM providerとして認識される。
> gpart show /dev/zvol/tank/vm/ubuntu/disk0
=> 34 8388541 zvol/tank/vm/ubuntu/disk0 GPT (4.0G)
34 2014 - free - (1.0M)
2048 1048576 1 efi (512M)
1050624 5335040 2 linux-data (2.5G)
6385664 2000896 3 linux-swap (977M)
8386560 2015 - free - (1.0M)
めでたしめでたし。
###クローンを使う(読み込み専用)
でも再起動したくない時もある。そんなときはクローンを作成する時にvolmode=geomとする方法がある。
> sudo zfs snapshot tank/vm/ubuntu/disk0@snap
> sudo zfs clone -o volmode=geom tank/vm/ubuntu/disk0@snap tank/vm/ubuntu/clone0
> gpart show /dev/zvol/tank/vm/ubuntu/clone0
=> 34 8388541 zvol/tank/vm/ubuntu/clone0 GPT (4.0G)
34 2014 - free - (1.0M)
2048 1048576 1 efi (512M)
1050624 5335040 2 linux-data (2.5G)
6385664 2000896 3 linux-swap (977M)
8386560 2015 - free - (1.0M)
> sudo mount -t msdosfs -o ro /dev/zvol/tank/vm/ubuntu/clone0p1 /mnt
> ls -la /mnt
total 17
drwxr-xr-x 1 root wheel 4096 Jan 1 1980 ./
drwxr-xr-x 22 root wheel 28 Apr 26 22:21 ../
drwxr-xr-x 1 root wheel 4096 Apr 25 17:37 EFI/
> sudo umount /mnt
> sudo zfs destroy -R tank/vm/ubuntu/disk0@snap
ただこの方法は元々のzvolに書き込むことはできない。あくまでちょっと中身を覗きたい時向け。
##CAM Target Layerを使う
再起動せずにzvolの中身を書き換えたい場合は、ちょっと煩雑だがctl(4)を使ってGEOM providerを生成する方法がある。
> sudo ctladm create -b block -d zvol-for-write -o file=/dev/zvol/tank/vm/ubuntu/disk0
LUN created successfully
backend: block
device type: 0
LUN size: 4294967296 bytes
blocksize 512 bytes
LUN ID: 0
Serial Number: MYSERIAL 0
Device ID; zvol-for-write
> sudo ctladm port -p `sudo ctladm port -l | grep "camsim.*naa" | cut -w -f 1` -o on
Front End Ports enabled
> gpart show da0
=> 34 8388541 da0 GPT (4.0G)
34 2014 - free - (1.0M)
2048 1048576 1 efi (512M)
1050624 5335040 2 linux-data (2.5G)
6385664 2000896 3 linux-swap (977M)
8386560 2015 - free - (1.0M)
> sudo mount -t msdosfs /dev/da0p1 /mnt
> ls -la /mnt
total 17
drwxr-xr-x 1 root wheel 4096 Jan 1 1980 ./
drwxr-xr-x 22 root wheel 28 Apr 26 22:21 ../
drwxr-xr-x 1 root wheel 4096 Apr 25 17:37 EFI/
> sudo mkdir /mnt/test
> ls -la /mnt
total 21
drwxr-xr-x 1 root wheel 4096 Jan 1 1980 ./
drwxr-xr-x 22 root wheel 28 Apr 26 22:21 ../
drwxr-xr-x 1 root wheel 4096 Apr 25 17:37 EFI/
drwxr-xr-x 1 root wheel 4096 Apr 26 22:43 test/
> sudo umount /mnt
> sudo ctladm port -p `sudo ctladm port -l | grep "camsim.*naa" | cut -w -f 1` -o off
Front End Ports disabled
> sudo ctladm remove -b block -l `sudo ctladm devl | grep "zvol-for-write" | cut -w -f 2`
LUN 0 removed successfully