git: 0df5f65908dd - main - reboot: Implement zfs support

From: Warner Losh <imp_at_FreeBSD.org>
Date: Mon, 12 Feb 2024 18:53:41 UTC
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=0df5f65908dd1913212535e6c4dd4c73ce19c305

commit 0df5f65908dd1913212535e6c4dd4c73ce19c305
Author:     Warner Losh <imp@FreeBSD.org>
AuthorDate: 2024-02-12 18:45:37 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2024-02-12 18:45:37 +0000

    reboot: Implement zfs support
    
    Implement full support for ZFS -k support. For ZFS, we have to set a
    property that gets cleared by the boot loaeder for whether or not to
    process nextboot.conf. Do this using system("zfsbootcfg..." rather than
    coding the small subset of that program inline to avoid CDDL
    contamination of reboot and the complications of disabling CDDL and/or
    ZFS. The few bytes needed to implement reboot for systems with zfs is
    not worth saving for systems w/o ZFS.
    
    Only set nextboot_enable=YES for UFS filesystems. They are the only one
    that need that as the first line. Its presence on ZFS can cause the
    kernel to not be oneshot.
    
    Sponsored by:           Netflix
    Reviewed by:            kevans, kib
    Differential Revision:  https://reviews.freebsd.org/D43824
---
 sbin/reboot/reboot.c | 58 ++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 49 insertions(+), 9 deletions(-)

diff --git a/sbin/reboot/reboot.c b/sbin/reboot/reboot.c
index d91fc6c97b0f..d598c857d255 100644
--- a/sbin/reboot/reboot.c
+++ b/sbin/reboot/reboot.c
@@ -31,6 +31,7 @@
 
 #include <sys/types.h>
 #include <sys/boottrace.h>
+#include <sys/mount.h>
 #include <sys/reboot.h>
 #include <sys/stat.h>
 #include <sys/sysctl.h>
@@ -56,11 +57,6 @@ static uint64_t get_pageins(void);
 
 static bool dohalt;
 
-static void
-write_nextboot(const char *fn, const char *kernel, bool force)
-{
-	FILE *fp;
-
 #define E(...) do {				\
 		if (force) {			\
 			warn( __VA_ARGS__ );	\
@@ -69,13 +65,58 @@ write_nextboot(const char *fn, const char *kernel, bool force)
 		err(1, __VA_ARGS__);		\
 	} while (0)				\
 
+static void
+zfsbootcfg(const char *pool, bool force)
+{
+	char *k;
+	int rv;
+
+	asprintf(&k,
+	    "zfsbootcfg -z %s -n freebsd:nvstore -k nextboot_enable -v YES",
+	    pool);
+	if (k == NULL)
+		E("No memory for zfsbootcfg");
+
+	rv = system(k);
+	if (rv == 0)
+		return;
+	if (rv == -1)
+		E("system zfsbootcfg");
+	if (rv == 127)
+		E("zfsbootcfg not found in path");
+	E("zfsbootcfg returned %d", rv);
+}
+
+static void
+write_nextboot(const char *fn, const char *kernel, bool force)
+{
+	FILE *fp;
+	struct statfs sfs;
+	bool supported = false;
+	bool zfs = false;
+
+	if (statfs("/boot", &sfs) != 0)
+		err(1, "statfs /boot");
+	if (strcmp(sfs.f_fstypename, "ufs") == 0) {
+		/*
+		 * Only UFS supports the full nextboot protocol.
+		 */
+		supported = true;
+	} else if (strcmp(sfs.f_fstypename, "zfs") == 0) {
+		zfs = true;
+	}
+
+	if (zfs) {
+		zfsbootcfg(sfs.f_mntfromname, force);
+	}
+
 	fp = fopen(fn, "w");
 	if (fp == NULL)
 		E("Can't create %s to boot %s", fn, kernel);
 
-	if (fprintf(fp,
-	    "nextboot_enable=\"YES\"\n"
-	    "kernel=\"%s\"\n", kernel) < 0) {
+	if (fprintf(fp,"%skernel=\"%s\"\n",
+	    supported ? "nextboot_enable=\"YES\"\n" : "",
+	    kernel) < 0) {
 		int e;
 
 		e = errno;
@@ -86,7 +127,6 @@ write_nextboot(const char *fn, const char *kernel, bool force)
 		E("Can't write %s", fn);
 	}
 	fclose(fp);
-#undef E
 }
 
 int