30.4 更新 ZFS 存储池
ZFS 存储池的可用功能由功能标志(feature flags)控制。FreeBSD 大版本升级后,需手动执行 zpool upgrade 启用新功能集——该操作不可逆,升级后旧版系统将无法识别新功能集,升级前应评估旧系统后续是否会再次导入该池。
警告
由于旧版本系统内置的 ZFS 无法兼容新版 ZFS 文件系统的功能集,请准备好备份和应急 CD 以应对意外情况。
30.4.1 验证 ZFS 版本
首先验证当前系统与 ZFS 版本:
- 查看当前系统版本
# freebsd-version -kru
15.0-RELEASE
15.0-RELEASE
15.0-RELEASE- 查看 ZFS/zpool 相关版本
# zpool version
2.4.0-rc4-FreeBSD_g099f69ff5
zfs-kmod-2.4.0-rc4-FreeBSD_g099f69ff5警告
这意味着任何 ZFS 版本低于 2.4.0-rc4 的操作系统在升级后可能无法启动。
30.4.2 执行更新
FreeBSD 升级后,ZFS 新功能标志在 zpool upgrade 执行完成之前不可用。执行升级操作:
# zpool status # 显示所有 ZFS 池的状态及详细信息
pool: zroot
state: ONLINE
status: Some supported and requested features are not enabled on the pool.
The pool can still be used, but some features are unavailable.
action: Enable all features using 'zpool upgrade'. Once this is done,
the pool may no longer be accessible by software that does not support
the features. See zpool-features(7) for details.
scan: scrub repaired 0B in 00:01:08 with 0 errors on Sun Dec 7 20:34:48 2025
config:
NAME STATE READ WRITE CKSUM
zroot ONLINE 0 0 0
nda0p4 ONLINE 0 0 0
errors: No known data errors状态:存储池上有一些支持且被请求的功能尚未启用。存储池仍然可以使用,但部分功能不可用。
操作:使用‘zpool upgrade’启用所有功能。在完成后,未支持这些功能的软件可能无法再访问该存储池。
警告
zpool upgrade启用新功能集的操作不可逆,升级后旧版系统将无法识别新功能集。执行前请确认所有需要访问该池的系统均已升级至兼容版本。
根据系统提示信息:系统提示需要更新,但更新后旧系统可能无法启动。先预览即将更新的功能:
# zpool upgrade # 查看所有 ZFS 池可升级的功能标志
This system supports ZFS pool feature flags.
All pools are formatted using feature flags.
Some supported features are not enabled on the following pools. Once a
feature is enabled the pool may become incompatible with software
that does not support the feature. See zpool-features(7) for details.
Note that the pool 'compatibility' feature can be used to inhibit
feature upgrades.
Features marked with (*) are not applied automatically on upgrade, and
must be applied explicitly with zpool-set(7).
POOL FEATURE
---------------
zroot
redaction_list_spill
raidz_expansion
fast_dedup
longname
large_microzap
dynamic_gang_header(*)
block_cloning_endian
physical_rewrite除了带有 * 的功能需要手动启用外,其余功能在升级后将默认启用。
注意
zpool upgrade并不能实际启用这些功能标志,仅用于预览可启用的功能。要执行更新,必须同时指定存储池名称,例如zpool upgrade zroot。参见:'zpool status' gives confusing suggestion with 'zpool upgrade'[EB/OL]. [2026-03-26]. https://github.com/openzfs/zfs/issues/17910. OpenZFS 项目关于 zpool upgrade 命令的问题讨论。
思考题
有贡献者认为上述 issue 关联的修补 PR 琐碎、无关紧要,并以每行不得超过 80 字符的理由予以拒绝。然而,无数用户都因这类“小事”耗费了大量时间。对文字力量的忽视,代价究竟是什么?
现在执行实际升级操作:
# zpool upgrade zroot # 将 ZFS 池 zroot 升级至当前系统支持的最新功能标志版本
This system supports ZFS pool feature flags.
Enabled the following features on 'zroot':
redaction_list_spill
raidz_expansion
fast_dedup
longname
large_microzap
block_cloning_endian
physical_rewrite
Pool 'zroot' has the bootfs property set, you might need to update
the boot code. See gptzfsboot(8) and loader.efi(8) for details.- 显示所有 ZFS 池的当前状态及健康信息:
# zpool status
pool: zroot
state: ONLINE
scan: scrub repaired 0B in 00:01:08 with 0 errors on Sun Dec 7 20:34:48 2025
config:
NAME STATE READ WRITE CKSUM
zroot ONLINE 0 0 0
nda0p4 ONLINE 0 0 0
errors: No known data errors升级成功完成,ZFS 池状态正常。
30.4.2.1 附录:需要手动启用的功能标志
本附录介绍需要手动启用的 ZFS 功能标志及其启用方法:
查看当前有哪些需要手动启用的功能标志(带 * 标记):
# zpool upgrade # 查看可升级的 ZFS 池及其支持的功能标志
This system supports ZFS pool feature flags.
All pools are formatted using feature flags.
Some supported features are not enabled on the following pools. Once a
feature is enabled the pool may become incompatible with software
that does not support the feature. See zpool-features(7) for details.
Note that the pool 'compatibility' feature can be used to inhibit
feature upgrades.
Features marked with (*) are not applied automatically on upgrade, and
must be applied explicitly with zpool-set(7).
POOL FEATURE
---------------
zroot
dynamic_gang_header(*)可见,可以手动启用 dynamic_gang_header,接下来查询 ZFS 池中该功能标志的状态:
# zpool get feature@dynamic_gang_header
NAME PROPERTY VALUE SOURCE
zroot feature@dynamic_gang_header disabled local该功能标志未启用,下面在 zroot 池上启用 dynamic_gang_header 功能标志:
# zpool set feature@dynamic_gang_header=enabled zroot再检查 zroot 池中 dynamic_gang_header 功能标志的当前状态:
# zpool get feature@dynamic_gang_header
NAME PROPERTY VALUE SOURCE
zroot feature@dynamic_gang_header enabled local检查当前可升级的 ZFS 池及其支持的功能标志:
# zpool upgrade
This system supports ZFS pool feature flags.
All pools are formatted using feature flags.
Every feature flags pool has all supported and requested features enabled.30.4.3 更新 boot loader 引导(UEFI 引导)
警告
请先更新 loader.efi,再更新 ZFS 版本!
使用 EFI 引导的系统,EFI 系统分区(ESP)上有引导加载程序的副本,用于固件引导内核。如果根文件系统是 ZFS,则引导加载程序必须能读取 ZFS 引导文件系统。系统升级后、执行 zpool upgrade 前,必须先更新 ESP 上的引导加载程序,否则系统可能无法引导。虽然不是强制性的,但在 UFS 作为根文件系统时也应如此。
可以使用命令 efibootmgr -v 来确定当前引导加载程序的位置。BootCurrent 的值是当前引导系统所用的引导项编号。输出的相应条目以 + 开头,如下所示:
# efibootmgr -v
Boot to FW : false
BootCurrent: 0004
BootOrder : 0004, 0000, 0001, 0002, 0003
+Boot0004* FreeBSD HD(1,GPT,f83a9e2f-bd87-11ef-95b7-000c29761cd2,0x28,0x82000)/File(\efi\freebsd\loader.efi) # 注意此行
nda0p1:/efi/freebsd/loader.efi (null)
Boot0000* EFI VMware Virtual NVME Namespace (NSID 1) PciRoot(0x0)/Pci(0x15,0x0)/Pci(0x0,0x0)/NVMe(0x1,00-00-00-00-00-00-00-00)
Boot0001* EFI VMware Virtual IDE CDROM Drive (IDE 1:0) PciRoot(0x0)/Pci(0x7,0x1)/Ata(Secondary,Master,0x0)
Boot0002* EFI Network PciRoot(0x0)/Pci(0x11,0x0)/Pci(0x1,0x0)/MAC(000c29761cd2,0x0)
Boot0003* EFI Internal Shell (Unsupported option) MemoryMapped(0xb,0xbeb4d018,0xbf07e017)/FvFile(c57ad6b7-0515-40a8-9d21-551652854e37)
Unreferenced Variables:ESP 通常已挂载到 /boot/efi。如果没有,可手动挂载,使用 efibootmgr 输出中列出的分区(本例为 nda0p1):mount_msdosfs /dev/nda0p1 /boot/efi。另一示例请参阅 loader.efi(8)。
efibootmgr -v 输出中 File 字段的值,如 \efi\freebsd\loader.efi,即 EFI 系统分区中当前使用的引导加载程序路径。若挂载点是 /boot/efi,则此文件为 /boot/efi/efi/freebsd/loader.efi。(在 FAT32 文件系统上大小写不敏感;FreeBSD 使用小写)File 的另一个常见值可能是 \EFI\boot\bootXXX.efi,其中 XXX 是 amd64(即 x64)、aarch64(即 aa64)或 riscv64(即 riscv64);如未配置,则为默认引导加载程序。应将 /boot/loader.efi 复制到 /boot/efi 中的正确路径以更新已配置及默认的引导加载程序。
30.4.3.1 执行更新
在版本更新后,系统启动时可能会出现引导加载程序版本过旧的提示,将显示如下类似提示。
注意
该界面出现的时间较短,在快速启动的系统中可能一闪而过。可使用相机拍摄后观察。
**************************************************************
**************************************************************
***** *****
***** BOOT LOADER IS TOO OLD, PLEASE UPGRADE. *****
***** *****
**************************************************************
**************************************************************提示需要更新 loader。还可以通过以下命令验证版本:
# strings /boot/efi/efi/freebsd/loader.efi | grep FreeBSD | grep EFI # 查看 EFI 引导加载程序版本
FreeBSD/amd64 EFI loader, Revision 1.1
# strings /boot/loader.efi | grep FreeBSD | grep EFI # 查看 /boot/loader.efi 的 EFI 引导加载程序版本
FreeBSD/amd64 EFI loader, Revision 3.0/boot/efi/efi/freebsd/loader.efi 为当前正在使用的 loader(版本确实较旧)。
将 /boot/loader.efi 复制到 EFI 系统分区的 FreeBSD 目录下进行更新:
# cp /boot/loader.efi /boot/efi/efi/freebsd/loader.efi30.4.4 重写引导代码(BIOS 传统引导)
BIOS 传统引导模式下,存储池升级后,可能需要手动重写引导代码,否则系统可能无法正常启动。
警告
bootfs属性是 ZFS 引导 FreeBSD 的关键标志。忽略此提示可能不会立即引发问题,但潜在风险一旦暴露,将导致系统无法启动,因此建议按照提示重写boot code。实践经验表明,未及时更新引导代码可能在后续系统更新中引发启动故障。若系统中不存在 freebsd-boot 分区,则无需执行以下操作。
列出系统中所有磁盘及其分区表信息:
# gpart show
=> 40 33554352 ada0 GPT (16G)
40 1024 1 freebsd-boot (512K)
1064 984 - free - (492K)
2048 4194304 2 freebsd-swap (2.0G)
4196352 29356032 3 freebsd-zfs (14G)
33552384 2008 - free - (1.0M)找到类型为 freebsd-boot 的分区,此处分区序号为 1,对应以下命令中的 -i 选项,而后重写 bootcode:
警告
gpart bootcode将写入引导代码到指定分区,操作不当可能导致系统无法启动。请确认分区序号(-i参数)与freebsd-boot分区对应。
# gpart bootcode -p /boot/gptzfsboot -i 1 ada0 # 为 ada0 磁盘的第 1 个分区写入 GPT ZFS 引导代码
partcode written to ada0p1再次列出所有 ZFS 池的状态及详细信息:
# zpool status
pool: zroot
state: ONLINE
config:
NAME STATE READ WRITE CKSUM
zroot ONLINE 0 0 0
ada0p3 ONLINE 0 0 0
errors: No known data errors