ramdisk-zfsroot: pool detection and configurable boot fs

[email protected]
Newsgroups gmane.os.netbsd.current
Message-ID <[email protected]>
I just tried installing NetBSD 11.0 with Root on ZFS using the guide on 
the wiki[1].  It worked like a charm.  I diverted a little bit from the 
guide, which didn't seem a problem, specifically I used a different disk 
for ZFS.

A problem I ran into though, was that the zfsroot.rc script has not been 
updated for a while, and it requires hardcoded values for the ZFS pool 
and the rootfs (rpool/ROOT).  I made some changes to this script, so 
that it will probe for ZFS pools and check if they have a rootfs 
property set.  I kept it backwards compatible with the current script, 
by always attempting if a ROOT filesystem is available.

Unfortunately, I was unable to build the ramdisk myself.  The guide [1] 
speaks of a program called nbmake-amd64, which I wasn't able to find any 
reference to online.  When trying my best with normal make it stopped 
right away on missing ../../compat/exec.mk, I didn't pursue a fix here.

Instead, I downloaded the current ramdisk, mounted it using vndconfig 
and replaced the etc/rc script in it and *renamed* altroot to zfsroot. 
After that, I was able to reboot into my differently-named ZFS pool, 
setting the filesystem marked as bootfs as the root filesystem.

I've attached the updated rc script, as well as a proposed patch, even 
though I was not able to test the patch due to not being able to build 
the ramdisk.

[1] https://wiki.netbsd.org/root_on_zfs/

-- 
Jørn Åne
zfsroot.rc (text/plain, 1.8 KB)
#/bin/sh
#
#       $NetBSD: zfsroot.rc,v 2.0 2026/08/17 05:43:18 jordej Exp $

# Assumption - boot.cfg loads this ramdisk.
# Assumption - The needed kernel modules: solaris and zfs; are either on this
#              ramdisk OR loaded by boot.cfg.
#              Finding the correct dev node to mount to get them is too magic.
# Assumption - NetBSD cannot build and distribute a kernel with ZFS builtin.
# Assumption - One of the available ZFS filesystems has a bootfs property set.
# Assumption - If none of the ZFS filesystems has a bootfs property set,
#              it's because version 1.5 of this rc script assumed rpool/ROOT
#              as root filesystem so we'll try using ROOT as the bootfs.

# Setup some stuff in case things go south and we drop to the shell
export HOME=/
export PATH=/sbin:/bin:/usr/sbin:/usr/bin
umask 022

bootfs=
pools="$(/sbin/zpool list -Honame)
$(/sbin/zpool import | /usr/bin/sed -ne'/^ *pool: / s/^.*: //p')"
echo "zfsroot: Pools found: " $pools >&2
for pool in $pools
do
	echo "zfsroot: $pool: Importing readonly" >&2
	/sbin/zpool export "$pool" 2>/dev/null >&2
	/sbin/zpool import -o readonly -o cachefile=none -f -N "$pool"
	bootfs="$(/sbin/zpool get -Hovalue bootfs "$pool")"
	[ '-' = "$bootfs" ] && bootfs="$(/sbin/zfs get -Hovalue name "$pool/ROOT")"
	[ -n "$bootfs" ] && break

	echo "zfsroot: $pool: missing bootfs property" >&2
	/sbin/zpool export "$pool"
done

if [ -z "$bootfs" ]
then
	echo "zfsroot: No suitable ZFS pool found" >&2
	exit 2
fi

echo "zfsroot: $pool: Found bootfs: $bootfs" >&2
echo "zfsroot: $pool: Importing read/write" >&2
/sbin/zpool export "$pool"
/sbin/zpool import -f -N -o cachefile=none "$pool"

echo "zfsroot: $pool: Mounting $bootfs to /zfsroot" >&2
/sbin/zfs set mountpoint=legacy "$bootfs"
/bin/mkdir -p /zfsroot
/sbin/mount -t zfs "$bootfs" /zfsroot

/sbin/sysctl -w init.root=/zfsroot
0001-zfsroot-ZFS-pool-detection-and-configurable-boot-fs.patch (text/plain, 4.5 KB)
From fd8c43822f710bda0f310a66f191a8fdd2fe7d4d Mon Sep 17 00:00:00 2001
From: jornane <[email protected]>
Date: Mon, 17 Aug 2026 07:43:18 +0200
Subject: [PATCH] zfsroot: ZFS pool detection and configurable boot fs

Iterate over all available ZFS pools and choose the first that has set a
bootfs property on the pool.  This allows users to set which filesystem
they want to use as their root filesystem, in a similar fashin that
other operating systems use for ZFS.  A fallback still explicitly checks
for a filesystem named ROOT, and will use that if no bootfs was set.
Any ZFS pool that contains neither the bootfs property, nor a filesystem
with the name ROOT, is considered unbootable, and is skipped over.
---
 distrib/common/list.zfsroot  |  6 ++--
 distrib/common/mtree.zfsroot |  3 +-
 distrib/common/zfsroot.rc    | 53 ++++++++++++++++++++++++++----------
 3 files changed, 43 insertions(+), 19 deletions(-)

diff --git a/distrib/common/list.zfsroot b/distrib/common/list.zfsroot
index 9b6fb81b7b64..b6f583509f9c 100644
--- a/distrib/common/list.zfsroot
+++ b/distrib/common/list.zfsroot
@@ -9,7 +9,7 @@ PROG	sbin/zpool
 LINK	sbin/zfs sbin/mount_zfs
 ARGVLN	zfs mount_zfs
 
-# We need sysctl to set init.root=/altroot
+# We need sysctl to set init.root=/zfsroot
 PROG	sbin/sysctl
 
 # We need modload as we cannot build CDDL modules in the kernel
@@ -31,5 +31,5 @@ LIBS	-lzfs_core
 COPY	${NETBSDSRCDIR}/distrib/common/zfsroot.rc etc/rc
 
 # Make modules and firmware images available
-SYMLINK	altroot/stand stand
-SYMLINK	altroot/libdata libdata
+SYMLINK	zfsroot/stand stand
+SYMLINK	zfsroot/libdata libdata
diff --git a/distrib/common/mtree.zfsroot b/distrib/common/mtree.zfsroot
index be040287c1e4..2d1412628661 100644
--- a/distrib/common/mtree.zfsroot
+++ b/distrib/common/mtree.zfsroot
@@ -1,5 +1,4 @@
 #	$NetBSD: mtree.zfsroot,v 1.3 2020/02/23 10:51:12 roy Exp $
 
 .
-./altroot
-./rpool
+./zfsroot
diff --git a/distrib/common/zfsroot.rc b/distrib/common/zfsroot.rc
index 03183464e75f..9427b1de0761 100644
--- a/distrib/common/zfsroot.rc
+++ b/distrib/common/zfsroot.rc
@@ -1,28 +1,53 @@
 #/bin/sh
 #
-#	$NetBSD: zfsroot.rc,v 1.5 2020/04/14 12:14:59 roy Exp $
+#       $NetBSD: zfsroot.rc,v 2.0 2026/08/17 05:43:18 jordej Exp $
 
 # Assumption - boot.cfg loads this ramdisk.
 # Assumption - The needed kernel modules: solaris and zfs; are either on this
 #              ramdisk OR loaded by boot.cfg.
 #              Finding the correct dev node to mount to get them is too magic.
-#              NetBSD cannot build and distribute a kernel with ZFS builtin.
-# Assumption - the root pool is set to legacy mount.
+# Assumption - NetBSD cannot build and distribute a kernel with ZFS builtin.
+# Assumption - One of the available ZFS filesystems has a bootfs property set.
+# Assumption - If none of the ZFS filesystems has a bootfs property set,
+#              it's because version 1.5 of this rc script assumed rpool/ROOT
+#              as root filesystem so we'll try using ROOT as the bootfs.
 
-# Configurable - define the ZFS root pool and ROOT.
-# XXX Can these be set in boot.cfg?
-rpool=rpool
-rroot=ROOT
-
-# Setup some stuff incase things go south and we drop to the shell
+# Setup some stuff in case things go south and we drop to the shell
 export HOME=/
 export PATH=/sbin:/bin:/usr/sbin:/usr/bin
 umask 022
 
-echo "Importing $rpool"
-/sbin/zpool import -f -N "$rpool"
+bootfs=
+pools="$(/sbin/zpool list -Honame)
+$(/sbin/zpool import | /usr/bin/sed -ne'/^ *pool: / s/^.*: //p')"
+echo "zfsroot: Pools found: " $pools >&2
+for pool in $pools
+do
+	echo "zfsroot: $pool: Importing readonly" >&2
+	/sbin/zpool export "$pool" 2>/dev/null >&2
+	/sbin/zpool import -o readonly -o cachefile=none -f -N "$pool"
+	bootfs="$(/sbin/zpool get -Hovalue bootfs "$pool")"
+	[ '-' = "$bootfs" ] && bootfs="$(/sbin/zfs get -Hovalue name "$pool/ROOT")"
+	[ -n "$bootfs" ] && break
+
+	echo "zfsroot: $pool: missing bootfs property" >&2
+	/sbin/zpool export "$pool"
+done
+
+if [ -z "$bootfs" ]
+then
+	echo "zfsroot: No suitable ZFS pool found" >&2
+	exit 2
+fi
+
+echo "zfsroot: $pool: Found bootfs: $bootfs" >&2
+echo "zfsroot: $pool: Importing read/write" >&2
+/sbin/zpool export "$pool"
+/sbin/zpool import -f -N -o cachefile=none "$pool"
 
-echo "Mounting $rpool/$rroot to /altroot"
-/sbin/mount -t zfs "$rpool/$rroot" /altroot;
+echo "zfsroot: $pool: Mounting $bootfs to /zfsroot" >&2
+/sbin/zfs set mountpoint=legacy "$bootfs"
+/bin/mkdir -p /zfsroot
+/sbin/mount -t zfs "$bootfs" /zfsroot
 
-/sbin/sysctl -w init.root=/altroot
+/sbin/sysctl -w init.root=/zfsroot
-- 
2.55.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.