Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 25 Jul 2018 03:30:01 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r336699 - projects/bectl/lib/libbe
Message-ID:  <201807250330.w6P3U1Wi074116@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Wed Jul 25 03:30:01 2018
New Revision: 336699
URL: https://svnweb.freebsd.org/changeset/base/336699

Log:
  libbe(3): Find rootfs instead by enumerating child datasets of BE root
  
  This makes us more resilient to a rename of the bootfs, but still wouldn't
  withstand pool renames or guid renames. More importantly, this allows `bectl
  create <foo>` work out of the box to create a boot environment based on the
  currently booted one.

Modified:
  projects/bectl/lib/libbe/be.c

Modified: projects/bectl/lib/libbe/be.c
==============================================================================
--- projects/bectl/lib/libbe/be.c	Wed Jul 25 03:29:29 2018	(r336698)
+++ projects/bectl/lib/libbe/be.c	Wed Jul 25 03:30:01 2018	(r336699)
@@ -42,22 +42,46 @@
 #include "be_impl.h"
 
 /*
+ * Iterator function for locating the rootfs amongst the children of the
+ * zfs_be_root set by loader(8).  data is expected to be a libbe_handle_t *.
+ */
+static int
+be_locate_rootfs(zfs_handle_t *chkds, void *data)
+{
+	libbe_handle_t *lbh;
+	char *mntpoint;
+
+	lbh = (libbe_handle_t *)data;
+	if (lbh == NULL)
+		return (1);
+
+	if (zfs_is_mounted(chkds, &mntpoint) && strcmp(mntpoint, "/") == 0) {
+		strncpy(lbh->rootfs, zfs_get_name(chkds), BE_MAXPATHLEN);
+		return (1);
+	}
+
+	return (0);
+}
+
+/*
  * Initializes the libbe context to operate in the root boot environment
  * dataset, for example, zroot/ROOT.
  */
 libbe_handle_t *
 libbe_init(void)
 {
-	char buf[BE_MAXPATHLEN];
 	struct stat sb;
 	dev_t root_dev, boot_dev;
 	libbe_handle_t *lbh;
+	zfs_handle_t *rootds;
 	char *poolname, *pos;
 	int pnamelen;
 
 	lbh = NULL;
 	poolname = pos = NULL;
 	pnamelen = 0;
+	rootds = NULL;
+
 	/* Verify that /boot and / are mounted on the same filesystem */
 	/* TODO: use errno here?? */
 	if (stat("/", &sb) != 0)
@@ -109,13 +133,11 @@ libbe_init(void)
 
 	/* Obtain path to boot environment rootfs (currently booted) */
 	/* XXX Get dataset mounted at / by kenv/GUID from mountroot? */
-	if ((kenv(KENV_GET, "zfs_be_active", lbh->rootfs, BE_MAXPATHLEN)) == -1)
+	if ((rootds = zfs_open(lbh->lzh, lbh->root, ZFS_TYPE_DATASET)) == NULL)
 		goto err;
 
-	/* Remove leading 'zfs:' if present, otherwise use value as-is */
-	if (strcmp(lbh->rootfs, "zfs:") == 0)
-		strncpy(lbh->rootfs, strchr(lbh->rootfs, ':') + sizeof(char),
-		    BE_MAXPATHLEN);
+	zfs_iter_filesystems(rootds, be_locate_rootfs, lbh);
+	zfs_close(rootds);
 
 	return (lbh);
 err:
@@ -126,6 +148,8 @@ err:
 			libzfs_fini(lbh->lzh);
 		free(lbh);
 	}
+	if (rootds != NULL)
+		zfs_close(rootds);
 	free(poolname);
 	return (NULL);
 }



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