使用zfs-dkms在arch linux(X86)编译安装ZFS

警告

本文正在根据自己近期 MacBook Air上运行Arch Linux 之后的ZFS实践重写,和以前 使用zfs-dkms在arch linux(ARM)编译安装ZFS 有所不同。部分内容参考和基于以前的 使用zfs-dkms在arch linux(ARM)编译安装ZFS (可能有重复)

zfs-dkms 软件包提供了 动态内核模块支持(DKMS) 支持,可以自动为兼容内核编译ZFS内核模块

优点:

  • 可以定制自己的内核

  • 可以不必等待内核发行版更新

缺点:

  • 编译比较缓慢(对于现代超强CPU可以忽略)

  • 如果DKMS编译失败很少有告警(需要仔细关注)

需要自己按照内核来编译,也就是采用 动态内核模块支持(DKMS) 安装对应的 zfs-dkms

安装

  • 检查内核variant(变种):

检查当前内核variant
INST_LINVAR=$(sed 's|.*linux|linux|' /proc/cmdline | sed 's|.img||g' | awk '{ print $1 }')

验证:

echo $INST_LINVAR

输出是:

linux
  • 检查内核版本:

检查当前内核版本
INST_LINVER=$(pacman -Qi ${INST_LINVAR} | grep Version | awk '{ print $3 }')

可以验证一下:

echo $INST_LINVER

输出是:

6.11.3.arch1-1
  • 安装内核头文件:

安装当前内核版本对应头文件
if [ "${INST_LINVER}" = \
"$(pacman -Si ${INST_LINVAR}-headers | grep Version | awk '{ print $3 }')" ]; then
 pacman -S --noconfirm --needed ${INST_LINVAR}-headers
else
 pacman -U --noconfirm --needed \
 https://archive.archlinux.org/packages/l/${INST_LINVAR}-headers/${INST_LINVAR}-headers-${INST_LINVER}-x86_64.pkg.tar.zst
fi

可以看到对应安装的是:

linux-headers-6.11.3.arch1-1
  • 安装zfs-dkms:

安装zfs-dkms
yay -S zfs-dkms

备注

安装过程需要从 github 下载 zfs-2.2.6.tar.gz ,这个过程会被GFW阻塞,所以需要设置 Linux代理环境变量

  • 加载内核模块:

加载zfs内核模块
modprobe zfs

我这里遇到报错显示zfs内核模块不存在:

加载zfs内核模块显示模块没有存在于当前内核目录
modprobe: FATAL: Module zfs not found in directory /lib/modules/6.11.3-arch1-1

仔细检查 yay 安装 zfs-dkms 安装输出信息,可以看到在内核模块 动态内核模块支持(DKMS) 安装时会提示信息显示不支持过高内核:

由于内核版本只支持 6.10 以下导致无法编译
(2/3) Install DKMS modules
==> dkms install --no-depmod zfs/2.2.6 -k 6.11.3-arch1-1
configure: error: 
	*** Cannot build against kernel version 6.11.3-arch1-1.
	*** The maximum supported kernel version is 6.10.
			
Error! Bad return status for module build on kernel: 6.11.3-arch1-1 (x86_64)
Consult /var/lib/dkms/zfs/2.2.6/build/make.log for more information.
==> WARNING: `dkms install --no-depmod zfs/2.2.6 -k 6.11.3-arch1-1' exited 10

这个问题在 使用zfs-dkms在arch linux(ARM)编译安装ZFS 也遇到过,但是当时我采用了 Btrfs 来替换ZFS绕开这个问题。不过,这个问题毕竟需要解决

参考 archlinux wiki: ZFS#DKMS 可以看到有如下 DKMS 解决方法:

  • zfs-dkms 是面向稳定版本的动态内核模块支持,也就意味着它可能不能支持最新内核

  • zfs-dkms-staging-compat-git 从ZFS最新补丁加上backport来支持最新内核

  • zfs-dkms-staging-git 跟踪最新发布候选版本(release candidate, RC)以及最新ZFS分支(如果还没有RC)

  • zfs-dkms-git DKMS的开发者版本

我决定回退到特定内核版本(6.1),然后重新安装 zfs-dkms 。需要注意 Arch Linux 内核 安装 6.1 LTS内核是通过 Arch Linux AUR 实现的,所以执行:

通过:ref:archlinux_aur 安装指定的 Kernel 6.1
yay -S linux-lts61

备注

没有使用安装 linux-lts 是因为当前 长期稳定支持 内核已经滚动升级到 6.5 系列,已经超出了zfs支持范围。

警告

编译安装最新的内核非常消耗计算资源,所以务必先在系统激活 makepkg并行任务 ( 不是配置 并行make )以充分利用CPU的多核心,否则效率会低到无法忍受的程度。我曾经在 MacBook Air 11" Late 2010 单CPU核心编译超过16小时依然失败,实在非常低效。

内核编译错误处理

内核编译oom

内核编译 BTF 相关报错
  BTF     .btf.vmlinux.bin.o
scripts/link-vmlinux.sh: line 111: 498795 Killed                  LLVM_OBJCOPY="${OBJCOPY}" ${PAHOLE} -J ${PAHOLE_FLAGS} ${1}
  LD      .tmp_vmlinux.kallsyms1
  NM      .tmp_vmlinux.kallsyms1.syms
  KSYMS   .tmp_vmlinux.kallsyms1.S
  AS      .tmp_vmlinux.kallsyms1.o
  LD      .tmp_vmlinux.kallsyms2
  NM      .tmp_vmlinux.kallsyms2.syms
  KSYMS   .tmp_vmlinux.kallsyms2.S
  AS      .tmp_vmlinux.kallsyms2.o
  LD      vmlinux
  BTFIDS  vmlinux
FAILED: load BTF from vmlinux: No such file or directory
make[1]: *** [scripts/Makefile.vmlinux:34: vmlinux] Error 255
make[1]: *** Deleting file 'vmlinux'
make: *** [Makefile:1250: vmlinux] Error 2
==> ERROR: A failure occurred in build().
    Aborting...
 -> error making: linux-lts61-exit status 4
 -> Failed to install the following packages. Manual intervention is required:
linux-lts61 - exit status 4

可以看到编译进程被突然杀死,检查系统 dmesg -T 日志查找可能OOM的killer日志

再次编译时,我关闭所有图形程序,退出 sway - i3兼容Wayland compositor 桌面,采用 tmux多会话终端管理 运行编译,以节约内存使用。

内核编译需要大量空间

编译完成,但是安装时空间不足
==> Starting package_linux-lts61-headers()...
Installing build files...
install: error copying 'vmlinux' to '/home/admin/.cache/yay/linux-lts61/pkg/linux-lts61-headers/usr/lib/modules/6.1.113-1-lts61/build/vmlinux': No space left on device
==> ERROR: A failure occurred in package_linux-lts61-headers().
    Aborting...
 -> error making: linux-lts61-exit status 4
 -> Failed to install the following packages. Manual intervention is required:
linux-lts61 - exit status 4

real    1561m40.335s
user    929m55.798s
sys     84m58.420s

检查可以看到 Arch Linux AUR 使用了用户目录下 $HOME/.cache/ 目录来保存编译过程数据,而编译内核达到了惊人的 21GB 空间占用。也就是说,要完整编译 linux-lts61 需要 至少21GB磁盘空间

检查zfs内核:

检查zfs内核模块
lsmod | grep zfs

此时可以看到zfs相关内核模块已经加载:

检查zfs内核模块输出显示模块加载
zfs                  3096576  0
zunicode              360448  1 zfs
zzstd                 491520  1 zfs
zlua                  196608  1 zfs
zcommon               114688  1 zfs
znvpair               131072  2 zfs,zcommon
zavl                   65536  1 zfs
icp                   278528  1 zfs
spl                   147456  6 zfs,icp,zzstd,znvpair,zcommon,zavl

参考