Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 24 Jul 2013 13:54:12 +0300
From:      Andriy Gapon <avg@FreeBSD.org>
To:        freebsd-fs@FreeBSD.org, freebsd-rc@FreeBSD.org
Subject:   rc.d support for zfs boot environments
Message-ID:  <51EFB254.8070807@FreeBSD.org>

next in thread | raw e-mail | index | archive | help

I would like to add another rc.d script or extend the current rc.d/zfs script
for enhanced support of ZFS boot environments.

To be short, a ZFS boot environment is a filesystem that typically has loader,
kernel and can be mounted as a root filesystem.  By having multiple filesystems
of this kind a user can easily select which one to boot to.  This allows for
things like having known good configurations, easily recovering from failed
upgrades, experimenting with new code, etc.

One of the features of boot environments is support for subordinate filesystems.
For example:
NAME                             MOUNTPOINT          CANMOUNT
pond/ROOT/20130331               /pond/ROOT/20130331   noauto
pond/ROOT/20130331/usr           /usr                     off
pond/ROOT/20130331/usr/local     /usr/local            noauto
pond/ROOT/20130331/usr/local/etc /usr/local/etc        noauto
pond/ROOT/kms                    /pond/ROOT/kms        noauto
pond/ROOT/kms/usr                /usr                     off
pond/ROOT/kms/usr/local          /usr/local            noauto
pond/ROOT/kms/usr/local/etc      /usr/local/etc        noauto

20130331 and kms are two boot environments here.
.../usr, .../usr/local, .../usr/local/etc are their subordinate datasets /
filesystems.
The idea is that one can have filesystems that are tied to a boot environment.
These filesystems hold files that must be in the boot environment but they are
better to be stored in a different filesystem than the main one.  There can be
different reasons for this like a need for different ZFS properties or
convenience of separate management (snapshots, cloning, etc).

Because these filesystems should not be automatically mounted during boot they
are configured with canmount=noauto.  The root filesystem is mounted
automatically by the kernel.  But the subordinate filesystems are not mounted by
rc.d/zfs -> zfs mount -a because of the canmount property.  So they need to be
mounted explicitly.

Below is a patch that I have for this case.
I would like to ask both fs@ and rc@ communities to review the patch for
correctness, soundness and style.  I will appreciate any suggestions and comments.
If you are already using boot environments and think that you may need to use
subordinate datasets, then testing is most welcome too.

commit df1df94f75a13f611a8234b01bfb9d6b43172c45
Author: Andriy Gapon <avg@icyb.net.ua>
Date:   Sun Jul 7 21:01:27 2013 +0300

    rc.d/zfsbe: a new script designed for boot environment support

    currently it ensures that subordinate datasets are mounted at the
    right points.

diff --git a/etc/rc.d/zfs b/etc/rc.d/zfs
index 598723a..3c40043 100755
--- a/etc/rc.d/zfs
+++ b/etc/rc.d/zfs
@@ -4,7 +4,7 @@
 #

 # PROVIDE: zfs
-# REQUIRE: mountcritlocal
+# REQUIRE: zfsbe

 . /etc/rc.subr

diff --git a/etc/rc.d/zfsbe b/etc/rc.d/zfsbe
new file mode 100755
index 0000000..9e4c50e
--- /dev/null
+++ b/etc/rc.d/zfsbe
@@ -0,0 +1,70 @@
+#!/bin/sh
+#
+# $FreeBSD$
+#
+
+# PROVIDE: zfsbe
+# REQUIRE: mountcritlocal
+
+# Handle boot environment subordinate filesystems
+# that may have canmount property set to noauto.
+# For these filesystems mountpoint relative to /
+# must be the same as their dataset name relative
+# to BE root dataset.
+
+. /etc/rc.subr
+
+name="zfsbe"
+rcvar="zfs_enable"
+start_cmd="be_start"
+stop_cmd="be_stop"
+required_modules="zfs"
+
+mount_subordinate()
+{
+	local _be
+
+	_be=$1
+	zfs list -rH -o mountpoint,name,canmount -s mountpoint -t filesystem $_be | \
+	while read _mp _name _canmount ; do
+		[ "$_canmount" = "off" ] && continue
+		case "$_mp" in
+		"")
+			;;
+		"legacy")
+			;;
+		"/")
+			;;
+		"/$_be")
+			;;
+		"/$_be/"*)
+			mount -t zfs $_name ${_mp#/$_be}
+			;;
+		*)
+			zfs mount $_name
+			;;
+		esac
+	done
+}
+
+be_start()
+{
+	if [ `$SYSCTL_N security.jail.jailed` -eq 1 ]; then
+		:
+	else
+		mount -p | while read _dev _mp _type _rest; do
+			[ $_mp  = "/" ] || continue
+			if [ $_type = "zfs" ] ; then
+				mount_subordinate $_dev
+			fi
+			break
+		done
+	fi
+}
+
+be_stop()
+{
+}
+
+load_rc_config $name
+run_rc_command "$1"

-- 
Andriy Gapon



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?51EFB254.8070807>