ZFSモジュール
WSL2標準kernelに組み込めるZFSモジュールの作り方。
ZFS有効なカスタムカーネルを作る方法はここを、WSL2標準kernelのソースコードでビルドする方法はここ、dxgkrnl有効カーネルを作る方法はここを参照。
zfsモジュールのビルドスクリプト。
スクリプトの93行目をコメントアウトすると、5.15.79.1以降で "BPF:[134983] FWD" エラーによるモジュールロードに失敗しなくなる(正しい方法かどうかは不明)。 カーネルとモジュールを同じツールチェインでビルドすれば BPF のエラーは出なくなる。
build_wsl_module.sh
#!/bin/sh
set -xe
#ZFS_VERSION="2.1.2"
#ZFS_VERSION="2.1.3"
#ZFS_VERSION="2.1.4"
#ZFS_VERSION="2.1.5"
ZFS_VERSION="2.1.6"
ZFS_RELEASE="1"
KERNELVER=$(uname -r)
#KERNELVER="5.10.43.3-microsoft-standard-WSL2"
#KERNELVER="5.10.60.1-microsoft-standard-WSL2"
#KERNELVER="5.10.93.2-microsoft-standard-WSL2"
#KERNELVER="5.10.102.1-microsoft-standard-WSL2"
#KERNELVER="5.15.57.1-microsoft-standard-WSL2"
#KERNELVER="5.15.68.1-microsoft-standard-WSL2"
#KERNELVER="5.15.74.2-microsoft-standard-WSL2"
LINUX_VERSION=$(echo ${KERNELVER}|awk -F'[-]' '{print $1}')
LINUX_RELEASE="1"
SCRIPTDIR=$(pwd)
KERNELSRCDIR=${SCRIPTDIR}/WSL2-Linux-Kernel
ZFSSRCDIR=${SCRIPTDIR}/zfs
#
# Install pre-requisites
#
sudo apt update && \
sudo apt upgrade -y && \
sudo apt install tzdata
sudo apt install \
autoconf \
automake \
bc \
binutils \
bison \
build-essential \
curl \
dwarves \
fakeroot \
flex \
gawk \
gcc-9 \
libblkid-dev \
libelf-dev \
libffi-dev \
libssl-dev \
libtool \
python3 \
python3-setuptools \
uuid-dev \
wget \
zlib1g-dev
#
# Download source code
#
if [ ! -d ${KERNELSRCDIR} ];then
git clone https://github.com/microsoft/WSL2-Linux-Kernel.git
fi
if [ ! -d ${ZFSSRCDIR} ];then
git clone https://github.com/openzfs/zfs.git
fi
#
# kernel build prepare
#
cd ${KERNELSRCDIR}
git fetch --tags origin
KERNELTAG=$(git tag | grep wsl | grep ${LINUX_VERSION})
git checkout ${KERNELTAG}
make mrproper
cp Microsoft/config-wsl .config
if [ -f ${SCRIPTDIR}/add_module_config ];then
cat ${SCRIPTDIR}/add_module_config >> .config
fi
make CC=gcc-9 olddefconfig
make CC=gcc-9 LOCALVERSION= modules -j$(nproc)
#
# original kernel (5.15.74.2-microsoft-standard-WSL2) can't load module.
# dmesg say below:
#[ 4.655440] BPF:[134983] FWD
#[ 4.655837] BPF:struct
#[ 4.656047] BPF:
#[ 4.656277] BPF:Invalid name
#[ 4.656610] BPF:
#
#[ 4.790484] modprobe: ERROR: could not insert 'zfs': Invalid argument
# to fix this error, comment out
#
#cp /sys/kernel/btf/vmlinux ${KERNELSRCDIR}
#
# build zfs
#
cd ${ZFSSRCDIR}
git fetch --tags origin
git checkout zfs-${ZFS_VERSION}
sh autogen.sh
CC=gcc-9 ./configure \
--prefix=/usr \
--sysconfdir=/etc \
--libdir=/lib \
--includedir=/usr/include \
--datarootdir=/usr/share \
--enable-linux-builtin=no \
--with-linux=${KERNELSRCDIR} \
--with-linux-obj=${KERNELSRCDIR}
rm -rf ${ZFSSRCDIR}/debwork
make CC=gcc-9 -j$(nproc) DESTDIR=${ZFSSRCDIR}/debwork
make CC=gcc-9 -j$(nproc) DESTDIR=${ZFSSRCDIR}/debwork install
rm -rf ${ZFSSRCDIR}/debwork/lib/modules/
INSTALLED_SIZE=$(du -ks debwork|awk '{print $1}')
mkdir -p ${ZFSSRCDIR}/debwork/DEBIAN
cat > ${ZFSSRCDIR}/debwork/DEBIAN/control << EOF
Package: zfs
Priority: extra
Section: kernel
Installed-Size: ${INSTALLED_SIZE}
Maintainer: $(whoami)@$(hostname)
Architecture: amd64
Version: ${ZFS_VERSION}-${ZFS_RELEASE}
Provides: zfs
Description: zfs for WSL linux
EOF
fakeroot dpkg-deb --build debwork ${SCRIPTDIR}
#
# build kernel module
#
rm -rf ${KERNELSRCDIR}/debwork
cd ${ZFSSRCDIR}/module
make CC=gcc-9 -j$(nproc) DESTDIR=${KERNELSRCDIR}/debwork
make CC=gcc-9 -j$(nproc) DESTDIR=${KERNELSRCDIR}/debwork install
cd ${KERNELSRCDIR}
make CC=gcc-9 -j$(nproc) INSTALL_MOD_PATH=${KERNELSRCDIR}/debwork LOCALVERSION= modules
make CC=gcc-9 -j$(nproc) INSTALL_MOD_PATH=${KERNELSRCDIR}/debwork LOCALVERSION= modules_install
INSTALLED_SIZE=$(du -ks debwork|awk '{print $1}')
mkdir -p ${KERNELSRCDIR}/debwork/DEBIAN
cat > ${KERNELSRCDIR}/debwork/DEBIAN/control << EOF
Package: linux-module-${KERNELVER}
Priority: extra
Section: kernel
Installed-Size: ${INSTALLED_SIZE}
Maintainer: $(whoami)@$(hostname)
Architecture: amd64
Version: ${LINUX_VERSION}-${LINUX_RELEASE}
Provides: linux-module
Description: module files (zfs-${ZFS_VERSION}) for WSL linux kernel
Enable modules:
CONFIG_ZFS=m$(test -f ${SCRIPTDIR}/add_module_config && echo &&
sed 's/^/ /' ${SCRIPTDIR}/add_module_config)
EOF
cat > ${KERNELSRCDIR}/debwork/DEBIAN/postinst << EOF
#!/bin/sh
depmod ${KERNELVER}
EOF
chmod 755 ${KERNELSRCDIR}/debwork/DEBIAN/postinst
fakeroot dpkg-deb --build debwork ${SCRIPTDIR}
set +x
echo '================================================================================================='
echo '# edit /etc/wsl.conf'
echo '$ cat /etc/wsl.conf
[boot]
command=modprobe zfs
'
echo '# install deb packages for zfs'
echo '$ sudo dpkg -i' linux-module-$(echo ${KERNELVER}|tr A-Z a-z)_${LINUX_VERSION}-${LINUX_RELEASE}_amd64.deb
echo '$ sudo dpkg -i' zfs_${ZFS_VERSION}-${ZFS_RELEASE}_amd64.deb
echo ''
echo '# check zfs'
echo '$ sudo zfs version'
echo '================================================================================================='
ここ先は古い情報なのでbuild_wsl_module.shを使ってください (5.15.79.1-microsoft-standard-WSL2で確認済み)。
WSL2 バージョンの確認
Windowsのバージョン:
Microsoft Windows [Version 10.0.22621.1105]
WSL2のカーネルバージョン(Windows Subsystem for Linux Preview):
$ uname -r
5.15.79.1-microsoft-standard-WSL2
作業ディレクトリを作成
$ mkdir ${HOME}/wsl2kernel
kernelのソースコードを取得
WSL2のカーネルバージョンと一致するソースコードを取得する。
$ cd ${HOME}/wsl2kernel
$ git clone https://github.com/microsoft/WSL2-Linux-Kernel.git
$ cd WSL2-Linux-Kernel
$ git tag | grep 5.15.79.1
linux-msft-wsl-5.15.79.1
$ git checkout linux-msft-wsl-5.15.79.1
kernelの準備
- LOCALVERSION= の理由はここを参照
- コンパイルに時間がかかるので注意
$ make mrproper
$ cp Microsoft/config-wsl .config
$ make oldconfig
$ make LOCALVERSION= modules -j12
ZFSのソースコードを取得
$ cd ${HOME}/wsl2kernel
$ git clone https://github.com/openzfs/zfs.git
$ cd zfs
$ git checkout zfs-2.1.6
ZFSのビルド及びインストール
スクリプト(debwork_module.sh,debwork_zfs.sh)でdebパッケージを作る
$ sh autogen.sh
$ mkdir ../zfs-2.1.1_build
$ cd ../zfs-2.1.1_build
$ ../zfs-2.1.1/configure --prefix=/usr --sysconfdir=/etc --libdir=/lib --includedir=/usr/include --datarootdir=/usr/share --enable-linux-builtin=no --with-linux=${HOME}/wsl2kernel/WSL2-Linux-Kernel --with-linux-obj=${HOME}/wsl2kernel/WSL2-Linux-Kernel
$ make -j12
$ sh debwork_zfs.sh #version, release番号等 スクリプトを編集する
$ cd ../WSL2-Linux-Kernel
$ sh debwork_module.sh #version, release番号等 スクリプトを編集する
$ cd ../zfs-2.1.1_build
$ sudo dpkg -i zfs_2.1.1-2_amd64.deb
$ sudo dpkg -i ../WSL2-Linux-Kernel/linux-module-5.10.60.1-microsoft-standard-wsl2_5.10.60.1-2_amd64.deb
ZFSの動作確認
$ sudo modprobe zfs
$ sudo zfs version
zfs-2.1.1-1
zfs-kmod-2.1.1-1
wsl.confの編集
wsl 起動時にmodprobeを実行するようにする。
$ sudo vi /etc/wsl.conf
$ cat /etc/wsl.conf
[boot]
command=/sbin/modprobe zfs
おまけ
ZFSなHDDにインストール済みのUbuntuをwslから使う。
DriveNameの確認
PowerShellコマンドでHDDのドライブ名を調べる。\\.\PHYSICALDRIVE1 と \\.\PHYSICALDRIVE2 がHDDのドライブ名。
$ /mnt/c/Windows/system32/WindowsPowerShell/v1.0/powershell.exe \
-NoProfile -ExecutionPolicy unrestricted \
-Command Get-CimInstance Win32_DiskDrive
-------- ------- ---------- ---- -----
\\.\PHYSICALDRIVE2 WDC WD40EZRZ-00GXCB0 5 4000784417280 WDC WD40EZRZ-00GXCB0
\\.\PHYSICALDRIVE1 WDC WD40EZRZ-00GXCB0 5 4000784417280 WDC WD40EZRZ-00GXCB0
\\.\PHYSICALDRIVE0 WDC WDS500G1B0A-00H9H0 4 500105249280 WDC WDS500G1B0A-00H9H0
HDDのマウント
管理者権限でwsl.exeを実行, \\.\PHYSICALDRIVE1 と \\.\PHYSICALDRIVE2をマウントする。
$ /mnt/c/Windows/system32/WindowsPowerShell/v1.0/powershell.exe \
-NoProfile -ExecutionPolicy unrestricted \
-Command Start-Process powerShell.exe -Wait \
-ArgumentList \"-Command wsl --mount \\\\.\\PHYSICALDRIVE1 --bare\; wsl --mount \\\\.\\PHYSICALDRIVE2 --bare\" -Verb runas
zpool import
注意: cacheなしのため、importに時間がかかる。
$ sudo mkdir /mnt/rpool
$ sudo zpool import -R /mnt/rpool rpool
$ sudo zpool import -R /mnt/rpool bpool
cacheがある場合:
$ sudo zpool import -R /mnt/rpool -c /root/zpool.cache rpool
$ sudo zpool import -R /mnt/rpool -c /root/zpool.cache bpool
import時、"cannot import 'rpool': one or more devices is currently unavailable"のエラーでimport出来ないとき: device path が変わっているのでcacheを作り直す:
$ sudo zpool import -R /mnt/rpool rpool -o cachefile=/root/zpool.cache_saved
$ sudo zpool import -R /mnt/rpool bpool -o cachefile=/root/zpool.cache_saved
$ sudo cp /root/zpool.cache_saved /root/zpool.cache
$ sudo zpool set cachefile="" rpool
$ sudo zpool set cachefile="" bpool
$ sudo zpool export bpool
$ sudo zpool export rpool
$ sudo rm /root/zpool.cache_saved
poolの確認
poolが正しくimportできたか確認する。
$ sudo zpool status
pool: bpool
state: ONLINE
status: The pool is formatted using a legacy on-disk format. The pool can
still be used, but some features are unavailable.
action: Upgrade the pool using 'zpool upgrade'. Once this is done, the
pool will no longer be accessible on software that does not support
feature flags.
scan: scrub repaired 0B in 0 days 00:00:12 with 0 errors on Sun Nov 8 00:24:14 2020
config:
NAME STATE READ WRITE CKSUM
bpool ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
sdb4 ONLINE 0 0 0
sdc4 ONLINE 0 0 0
errors: No known data errors
pool: rpool
state: ONLINE
scan: scrub repaired 0B in 0 days 01:57:21 with 0 errors on Thu Dec 10 23:03:06 2020
config:
NAME STATE READ WRITE CKSUM
rpool ONLINE 0 0 0
mirror-0 ONLINE 0 0 0
sdb5 ONLINE 0 0 0
sdc5 ONLINE 0 0 0
errors: No known data errors
zpool.cacheの取得
$ sudo cp /mnt/rpool/etc/zfs/zpool.cache /root
chroot
ネットワークが使えるよう、/etc/resolv.confをコピーしておく。
$ sudo mv /mnt/rpool/etc/resolv.conf /mnt/rpool/etc/resolv.conf_
$ sudo cp /etc/resolv.conf /mnt/rpool/etc/resolv.conf
$ sudo mount -o bind /dev /mnt/rpool/dev
$ sudo mount -o bind /dev/pts /mnt/rpool/dev/pts
$ sudo mount -o bind /mnt/wslg/.X11-unix /mnt/rpool/tmp/.X11-unix
$ sudo mount -t proc proc /mnt/rpool/proc
$ sudo mount -t sysfs sys /mnt/rpool/sys
$ sudo mount /dev/sdb2 /mnt/rpool/boot/grub #device idがずれてる場合は、/dev/sdc2等に修正する
$ sudo chroot /mnt/rpool/ /bin/su - name_of_user_at_zpool
hostidの確認
.wslconfigで設定する値を調べておく。
$ hostid # ZFS HDD上のUbuntu
7a95e9bb
chrootから抜ける
$ exit # ZFS HDD上のUbuntu
$ sudo umount /mnt/rpool/boot/grub
$ sudo umount /mnt/rpool/sys
$ sudo umount /mnt/rpool/proc
$ sudo umount /mnt/rpool/tmp/.X11-unix
$ sudo umount /mnt/rpool/dev/pts
$ sudo umount /mnt/rpool/dev
$ sudo rm /mnt/rpool/etc/resolv.conf
$ sudo mv /mnt/rpool/etc/resolv.conf_ /mnt/rpool/etc/resolv.conf
zpool export
$ sudo zpool export bpool
$ sudo zpool export rpool
HDDのアンマウント
管理者権限でwsl.exeを実行, \\.\PHYSICALDRIVE1 と \\.\PHYSICALDRIVE2をアンマウントする。
$ /mnt/c/Windows/system32/WindowsPowerShell/v1.0/powershell.exe \
-NoProfile -ExecutionPolicy unrestricted \
-Command Start-Process powerShell.exe -Wait \
-ArgumentList \"-Command wsl --unmount \\\\.\\PHYSICALDRIVE2\; wsl --unmount \\\\.\\PHYSICALDRIVE1\" -Verb runas
.wslconfigの編集
インポートするシステムのhostidをコマンドライン引数spl.spl_hostidで設定する。
$ vi /mnt/c/Users/name_of_user/.wslconfig
$ cat /mnt/c/Users/name_of_user/.wslconfig
[wsl2]
kernelCommandLine=spl.spl_hostid=0x7a95e9bb # カーネルコマンド引数を指定する
memory=6GB # WSL2の軽量仮想マシンで使用する最大メモリサイズを指定する
processors=6 # WSL2の軽量仮想マシンで使用するCPU数を指定する
swap=0 # WSL2の軽量仮想マシンで使用するスワップファイルのサイズを指定する
# 0を指定した場合はスワップファイルを使用しない
#swapFile=<path> # スワップファイルに使用するVHDファイルの(Windows上の)パスを指定する
localhostForwarding=true # WSLのネットワークポート待ち受けを、ホストマシンにフォワーディングする
スクリプトfor Ubuntu on ZFS HDD
下記スクリプトを/root/ubuntu_hdd.shに保存。
ubuntu_hdd.sh
ubuntu_hdd.sh
#/bin/sh
ubuntu_hdd_import()
{
echo zpool import -R /mnt/rpool -c /root/zpool.cache rpool
zpool import -R /mnt/rpool -c /root/zpool.cache rpool
echo zpool import -R /mnt/rpool -c /root/zpool.cache bpool
zpool import -R /mnt/rpool -c /root/zpool.cache bpool
echo mv /mnt/rpool/etc/resolv.conf /mnt/rpool/etc/resolv.conf_
mv /mnt/rpool/etc/resolv.conf /mnt/rpool/etc/resolv.conf_
echo cp /etc/resolv.conf /mnt/rpool/etc/resolv.conf
cp /etc/resolv.conf /mnt/rpool/etc/resolv.conf
echo mount -o bind /dev /mnt/rpool/dev
mount -o bind /dev /mnt/rpool/dev
echo mount -o bind /dev/pts /mnt/rpool/dev/pts
mount -o bind /dev/pts /mnt/rpool/dev/pts
echo mount -o bind /mnt/wslg/.X11-unix /mnt/rpool/tmp/.X11-unix
mount -o bind /mnt/wslg/.X11-unix /mnt/rpool/tmp/.X11-unix
echo mount -t proc proc /mnt/rpool/proc
mount -t proc proc /mnt/rpool/proc
echo mount -t sysfs sys /mnt/rpool/sys
mount -t sysfs sys /mnt/rpool/sys
echo mount /dev/sdb2 /mnt/rpool/boot/grub
mount /dev/sdb2 /mnt/rpool/boot/grub
echo chroot /mnt/rpool/ /bin/su - $1
chroot /mnt/rpool/ /bin/su - $1
}
ubuntu_hdd_export()
{
echo umount /mnt/rpool/boot/grub
umount /mnt/rpool/boot/grub
echo umount /mnt/rpool/sys
umount /mnt/rpool/sys
echo umount /mnt/rpool/proc
umount /mnt/rpool/proc
echo umount /mnt/rpool/tmp/.X11-unix
umount /mnt/rpool/tmp/.X11-unix
echo umount /mnt/rpool/dev/pts
umount /mnt/rpool/dev/pts
echo umount /mnt/rpool/dev
umount /mnt/rpool/dev
echo rm /mnt/rpool/etc/resolv.conf
rm /mnt/rpool/etc/resolv.conf
echo mv /mnt/rpool/etc/resolv.conf_ /mnt/rpool/etc/resolv.conf
mv /mnt/rpool/etc/resolv.conf_ /mnt/rpool/etc/resolv.conf
echo zpool export bpool
zpool export bpool
echo zpool export rpool
zpool export rpool
}
/mnt/c/Windows/system32/WindowsPowerShell/v1.0/powershell.exe \
-NoProfile -ExecutionPolicy unrestricted \
-Command Start-Process powerShell.exe -Wait \
-ArgumentList \"-Command wsl --mount \\\\.\\PHYSICALDRIVE1 --bare\; wsl --mount \\\\.\\PHYSICALDRIVE2 --bare\" -Verb runas
ubuntu_hdd_import $1
ubuntu_hdd_export
/mnt/c/Windows/system32/WindowsPowerShell/v1.0/powershell.exe \
-NoProfile -ExecutionPolicy unrestricted \
-Command Start-Process powerShell.exe -Wait \
-ArgumentList \"-Command wsl --unmount \\\\.\\PHYSICALDRIVE2\; wsl --unmount \\\\.\\PHYSICALDRIVE1\" -Verb runas
ZFSなHDD上のUbuntuに入る
$ sudo sh /root/ubuntu_hdd.sh name_of_user_at_zpool
zpool import -R /mnt/rpool -c /root/zpool.cache rpool
zpool import -R /mnt/rpool -c /root/zpool.cache bpool
mv /mnt/rpool/etc/resolv.conf /mnt/rpool/etc/resolv.conf_
cp /etc/resolv.conf /mnt/rpool/etc/resolv.conf
mount -o bind /dev /mnt/rpool/dev
mount -o bind /dev/pts /mnt/rpool/dev/pts
mount -o bind /mnt/wslg/.X11-unix /mnt/rpool/tmp/.X11-unix
mount -t proc proc /mnt/rpool/proc
mount -t sysfs sys /mnt/rpool/sys
mount /dev/sdb2 /mnt/rpool/boot/grub
chroot /mnt/rpool/ /bin/su - name_of_user_at_zpool
$ # ZFS HDD上のUbuntu
ZFSなHDD上のUbuntuから出る
$ exit # ZFS HDD上のUbuntu
ログアウト
umount /mnt/rpool/boot/grub
umount /mnt/rpool/sys
umount /mnt/rpool/proc
umount /mnt/rpool/tmp/.X11-unix
umount /mnt/rpool/dev/pts
umount /mnt/rpool/dev
rm /mnt/rpool/etc/resolv.conf
mv /mnt/rpool/etc/resolv.conf_ /mnt/rpool/etc/resolv.conf
zpool export bpool
zpool export rpool