Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 6 Jan 2019 02:13:17 +0000 (UTC)
From:      Kyle Evans <kevans@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r342807 - in stable/11: . contrib/mdocml lib lib/libbe sbin sbin/bectl share/mk sys/amd64/conf tools/build/mk usr.sbin/config
Message-ID:  <201901060213.x062DHNS081954@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Sun Jan  6 02:13:16 2019
New Revision: 342807
URL: https://svnweb.freebsd.org/changeset/base/342807

Log:
  MFC r342362-r342363: config(8) duplicate option handling
  
  r342362:
  config(8): Allow duplicate options to be specified
  
  config(8)'s option handling has been written to allow duplicate options; if
  the value changes, then the latest value is used and an informative message
  is printed to stderr like so:
  
  /usr/src/sys/amd64/conf/TEST: option "VERBOSE_SYSINIT" redefined from 0 to 1
  
  Currently, this is only a possibility for cpu types, MAXUSERS, and
  MACHINE_ARCH. Anything else duplicated in a config file will use the first
  value set and error about duplicated options on subsequent appearances,
  which is arguably unfriendly since one could specify:
  
  include GENERIC
  nooptions VERBOSE_SYSINIT
  options VERBOSE_SYSINIT
  
  to redefine the value later anyways.
  
  Reported by:	mmacy
  
  r342363:
  config(8): Remove all instances of an option when opting out
  
  Quick follow-up to r342362: options can appear multiple times now, so
  clean up all of them as needed. For non-OPTIONS options, this has no effect
  since they're already de-duplicated.

Added:
  stable/11/lib/libbe/
     - copied from r337664, head/lib/libbe/
  stable/11/lib/libbe/Makefile
     - copied, changed from r337995, head/lib/libbe/Makefile
  stable/11/sbin/bectl/
     - copied from r337664, head/sbin/bectl/
Modified:
  stable/11/Makefile.inc1
  stable/11/ObsoleteFiles.inc
  stable/11/contrib/mdocml/lib.in
  stable/11/lib/Makefile
  stable/11/lib/libbe/be.c
  stable/11/lib/libbe/be.h
  stable/11/lib/libbe/be_access.c
  stable/11/lib/libbe/be_error.c
  stable/11/lib/libbe/be_info.c
  stable/11/lib/libbe/libbe.3
  stable/11/sbin/Makefile
  stable/11/sbin/bectl/Makefile
  stable/11/sbin/bectl/bectl.8
  stable/11/sbin/bectl/bectl.c
  stable/11/sbin/bectl/bectl_jail.c
  stable/11/sbin/bectl/bectl_list.c
  stable/11/share/mk/bsd.libnames.mk
  stable/11/share/mk/src.libnames.mk
  stable/11/sys/amd64/conf/GENERIC
  stable/11/sys/amd64/conf/MINIMAL
  stable/11/tools/build/mk/OptionalObsoleteFiles.inc
  stable/11/usr.sbin/config/config.y
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/Makefile.inc1
==============================================================================
--- stable/11/Makefile.inc1	Sun Jan  6 02:12:55 2019	(r342806)
+++ stable/11/Makefile.inc1	Sun Jan  6 02:13:16 2019	(r342807)
@@ -2144,7 +2144,7 @@ _prebuild_libs=	${_kerberos5_lib_libasn1} \
 		${_cddl_lib_libumem} ${_cddl_lib_libnvpair} \
 		${_cddl_lib_libuutil} \
 		${_cddl_lib_libavl} \
-		${_cddl_lib_libzfs_core} \
+		${_cddl_lib_libzfs_core} ${_cddl_lib_libzfs} \
 		${_cddl_lib_libctf} \
 		lib/libutil lib/libpjdlog ${_lib_libypclnt} lib/libz lib/msun \
 		${_secure_lib_libcrypto} ${_lib_libldns} \
@@ -2213,7 +2213,15 @@ _cddl_lib_libavl= cddl/lib/libavl
 _cddl_lib_libuutil= cddl/lib/libuutil
 .if ${MK_ZFS} != "no"
 _cddl_lib_libzfs_core= cddl/lib/libzfs_core
+_cddl_lib_libzfs= cddl/lib/libzfs
+
 cddl/lib/libzfs_core__L: cddl/lib/libnvpair__L
+
+cddl/lib/libzfs__L: cddl/lib/libzfs_core__L lib/msun__L lib/libutil__L
+cddl/lib/libzfs__L: lib/libthr__L lib/libmd__L lib/libz__L cddl/lib/libumem__L
+cddl/lib/libzfs__L: cddl/lib/libuutil__L cddl/lib/libavl__L lib/libgeom__L
+
+lib/libbe__L: cddl/lib/libzfs__L
 .endif
 _cddl_lib_libctf= cddl/lib/libctf
 _cddl_lib= cddl/lib

Modified: stable/11/ObsoleteFiles.inc
==============================================================================
--- stable/11/ObsoleteFiles.inc	Sun Jan  6 02:12:55 2019	(r342806)
+++ stable/11/ObsoleteFiles.inc	Sun Jan  6 02:13:16 2019	(r342807)
@@ -38,6 +38,8 @@
 #   xargs -n1 | sort | uniq -d;
 # done
 
+# 20181115: libbe(3) SHLIBDIR fixed to reflect correct location
+OLD_LIBS+=usr/lib/libbe.so.1
 # 20180812: move of libmlx5.so.1 and libibverbs.so.1
 OLD_LIBS+=usr/lib/libmlx5.so.1
 OLD_LIBS+=usr/lib/libibverbs.so.1

Modified: stable/11/contrib/mdocml/lib.in
==============================================================================
--- stable/11/contrib/mdocml/lib.in	Sun Jan  6 02:12:55 2019	(r342806)
+++ stable/11/contrib/mdocml/lib.in	Sun Jan  6 02:13:16 2019	(r342807)
@@ -28,6 +28,7 @@ LINE("lib80211",	"802.11 Wireless Network Management L
 LINE("libarchive",	"Streaming Archive Library (libarchive, \\-larchive)")
 LINE("libarm",		"ARM Architecture Library (libarm, \\-larm)")
 LINE("libarm32",	"ARM32 Architecture Library (libarm32, \\-larm32)")
+LINE("libbe",		"Boot Environment Library (libbe, \\-lbe)")
 LINE("libbluetooth",	"Bluetooth Library (libbluetooth, \\-lbluetooth)")
 LINE("libbsm",		"Basic Security Module Library (libbsm, \\-lbsm)")
 LINE("libc",		"Standard C\\~Library (libc, \\-lc)")

Modified: stable/11/lib/Makefile
==============================================================================
--- stable/11/lib/Makefile	Sun Jan  6 02:12:55 2019	(r342806)
+++ stable/11/lib/Makefile	Sun Jan  6 02:13:16 2019	(r342807)
@@ -289,6 +289,7 @@ _libproc=	libproc
 _librtld_db=	librtld_db
 .endif
 SUBDIR.${MK_OFED}+=	ofed
+SUBDIR.${MK_ZFS}+=	libbe
 
 .if ${MK_OPENSSL} != "no"
 _libmp=		libmp

Copied and modified: stable/11/lib/libbe/Makefile (from r337995, head/lib/libbe/Makefile)
==============================================================================
--- head/lib/libbe/Makefile	Sat Aug 18 03:20:59 2018	(r337995, copy source)
+++ stable/11/lib/libbe/Makefile	Sun Jan  6 02:13:16 2019	(r342807)
@@ -2,6 +2,7 @@
 
 PACKAGE=	lib${LIB}
 LIB=		be
+SHLIBDIR?= /lib
 SHLIB_MAJOR=	1
 SHLIB_MINOR=	0
 

Modified: stable/11/lib/libbe/be.c
==============================================================================
--- head/lib/libbe/be.c	Sun Aug 12 00:00:13 2018	(r337664)
+++ stable/11/lib/libbe/be.c	Sun Jan  6 02:13:16 2019	(r342807)
@@ -64,10 +64,13 @@ be_locate_rootfs(zfs_handle_t *chkds, void *data)
 	if (lbh == NULL)
 		return (1);
 
+	mntpoint = NULL;
 	if (zfs_is_mounted(chkds, &mntpoint) && strcmp(mntpoint, "/") == 0) {
-		strncpy(lbh->rootfs, zfs_get_name(chkds), BE_MAXPATHLEN);
+		strlcpy(lbh->rootfs, zfs_get_name(chkds), sizeof(lbh->rootfs));
+		free(mntpoint);
 		return (1);
-	}
+	} else if(mntpoint != NULL)
+		free(mntpoint);
 
 	return (0);
 }
@@ -88,7 +91,6 @@ libbe_init(void)
 
 	lbh = NULL;
 	poolname = pos = NULL;
-	pnamelen = 0;
 	rootds = NULL;
 
 	/* Verify that /boot and / are mounted on the same filesystem */
@@ -115,13 +117,14 @@ libbe_init(void)
 		goto err;
 
 	/* Obtain path to boot environment root */
-	if ((kenv(KENV_GET, "zfs_be_root", lbh->root, BE_MAXPATHLEN)) == -1)
+	if ((kenv(KENV_GET, "zfs_be_root", lbh->root,
+	    sizeof(lbh->root))) == -1)
 		goto err;
 
 	/* Remove leading 'zfs:' if present, otherwise use value as-is */
 	if (strcmp(lbh->root, "zfs:") == 0)
-		strncpy(lbh->root, strchr(lbh->root, ':') + sizeof(char),
-		    BE_MAXPATHLEN);
+		strlcpy(lbh->root, strchr(lbh->root, ':') + sizeof(char),
+		    sizeof(lbh->root));
 
 	if ((pos = strchr(lbh->root, '/')) == NULL)
 		goto err;
@@ -131,13 +134,14 @@ libbe_init(void)
 	if (poolname == NULL)
 		goto err;
 
-	strncpy(poolname, lbh->root, pnamelen);
-	poolname[pnamelen] = '\0';
+	strlcpy(poolname, lbh->root, pnamelen + 1);
 	if ((lbh->active_phandle = zpool_open(lbh->lzh, poolname)) == NULL)
 		goto err;
+	free(poolname);
+	poolname = NULL;
 
 	if (zpool_get_prop(lbh->active_phandle, ZPOOL_PROP_BOOTFS, lbh->bootfs,
-	    BE_MAXPATHLEN, NULL, true) != 0)
+	    sizeof(lbh->bootfs), NULL, true) != 0)
 		goto err;
 
 	/* Obtain path to boot environment rootfs (currently booted) */
@@ -160,8 +164,6 @@ err:
 			libzfs_fini(lbh->lzh);
 		free(lbh);
 	}
-	if (rootds != NULL)
-		zfs_close(rootds);
 	free(poolname);
 	return (NULL);
 }
@@ -217,7 +219,6 @@ be_destroy(libbe_handle_t *lbh, const char *name, int 
 
 	p = path;
 	force = options & BE_DESTROY_FORCE;
-	err = BE_ERR_SUCCESS;
 
 	be_root_concat(lbh, name, path);
 
@@ -269,22 +270,27 @@ be_snapshot(libbe_handle_t *lbh, const char *source, c
 
 	be_root_concat(lbh, source, buf);
 
-	if (!be_exists(lbh, buf))
-		return (BE_ERR_NOENT);
+	if ((err = be_exists(lbh, buf)) != 0)
+		return (set_error(lbh, err));
 
 	if (snap_name != NULL) {
-		strcat(buf, "@");
-		strcat(buf, snap_name);
+		if (strlcat(buf, "@", sizeof(buf)) >= sizeof(buf))
+			return (set_error(lbh, BE_ERR_INVALIDNAME));
+
+		if (strlcat(buf, snap_name, sizeof(buf)) >= sizeof(buf))
+			return (set_error(lbh, BE_ERR_INVALIDNAME));
+
 		if (result != NULL)
 			snprintf(result, BE_MAXPATHLEN, "%s@%s", source,
 			    snap_name);
 	} else {
 		time(&rawtime);
 		len = strlen(buf);
-		strftime(buf + len, BE_MAXPATHLEN - len,
+		strftime(buf + len, sizeof(buf) - len,
 		    "@%F-%T", localtime(&rawtime));
-		if (result != NULL)
-			strcpy(result, strrchr(buf, '/') + 1);
+		if (result != NULL && strlcpy(result, strrchr(buf, '/') + 1,
+		    sizeof(buf)) >= sizeof(buf))
+			return (set_error(lbh, BE_ERR_INVALIDNAME));
 	}
 
 	if ((err = zfs_snapshot(lbh->lzh, buf, recursive, NULL)) != 0) {
@@ -397,20 +403,16 @@ be_deep_clone(zfs_handle_t *ds, void *data)
 	    ZFS_TYPE_FILESYSTEM) == ZPROP_INVAL)
 		return (-1);
 
-	if ((err = zfs_clone(snap_hdl, be_path, props)) != 0) {
-		switch (err) {
-		case EZFS_SUCCESS:
-			err = BE_ERR_SUCCESS;
-			break;
-		default:
-			err = BE_ERR_ZFSCLONE;
-			break;
-		}
-	}
+	if ((err = zfs_clone(snap_hdl, be_path, props)) != 0)
+		err = BE_ERR_ZFSCLONE;
 
 	nvlist_free(props);
 	zfs_close(snap_hdl);
 
+	/* Failed to clone */
+	if (err != BE_ERR_SUCCESS)
+		return (set_error(isdc->lbh, err));
+
 	sdc.lbh = isdc->lbh;
 	sdc.bename = NULL;
 	sdc.snapname = isdc->snapname;
@@ -451,14 +453,13 @@ be_create_from_existing_snap(libbe_handle_t *lbh, cons
 	else
 		bename++;
 
-	if ((parentname = strdup(snap_path)) == NULL) {
-		err = BE_ERR_UNKNOWN;
-		return (set_error(lbh, err));
-	}
+	if ((parentname = strdup(snap_path)) == NULL)
+		return (set_error(lbh, BE_ERR_UNKNOWN));
+
 	snapname = strchr(parentname, '@');
 	if (snapname == NULL) {
-		err = BE_ERR_UNKNOWN;
-		return (set_error(lbh, err));
+		free(parentname);
+		return (set_error(lbh, BE_ERR_UNKNOWN));
 	}
 	*snapname = '\0';
 	snapname++;
@@ -471,6 +472,7 @@ be_create_from_existing_snap(libbe_handle_t *lbh, cons
 	parent_hdl = zfs_open(lbh->lzh, parentname, ZFS_TYPE_DATASET);
 	err = be_deep_clone(parent_hdl, &sdc);
 
+	free(parentname);
 	return (set_error(lbh, err));
 }
 
@@ -484,7 +486,7 @@ be_create_from_existing(libbe_handle_t *lbh, const cha
 	int err;
 	char buf[BE_MAXPATHLEN];
 
-	if ((err = be_snapshot(lbh, old, NULL, true, (char *)&buf)))
+	if ((err = be_snapshot(lbh, old, NULL, true, (char *)&buf)) != 0)
 		return (set_error(lbh, err));
 
 	err = be_create_from_existing_snap(lbh, name, (char *)buf);
@@ -513,7 +515,7 @@ be_validate_snap(libbe_handle_t *lbh, const char *snap
 	    ZFS_TYPE_SNAPSHOT))
 		return (BE_ERR_NOENT);
 
-	strncpy(buf, snap_name, BE_MAXPATHLEN);
+	strlcpy(buf, snap_name, sizeof(buf));
 
 	/* Find the base filesystem of the snapshot */
 	if ((delim_pos = strchr(buf, '@')) == NULL)
@@ -524,12 +526,12 @@ be_validate_snap(libbe_handle_t *lbh, const char *snap
 	    zfs_open(lbh->lzh, buf, ZFS_TYPE_DATASET)) == NULL)
 		return (BE_ERR_NOORIGIN);
 
-	if ((err = zfs_prop_get(zfs_hdl, ZFS_PROP_MOUNTPOINT, buf, BE_MAXPATHLEN,
-	    NULL, NULL, 0, 1)) != 0)
-		err = BE_ERR_INVORIGIN;
+	if ((err = zfs_prop_get(zfs_hdl, ZFS_PROP_MOUNTPOINT, buf,
+	    sizeof(buf), NULL, NULL, 0, 1)) != 0)
+		err = BE_ERR_BADMOUNT;
 
-	if ((err != 0) && (strncmp(buf, "/", BE_MAXPATHLEN) != 0))
-		err = BE_ERR_INVORIGIN;
+	if ((err != 0) && (strncmp(buf, "/", sizeof(buf)) != 0))
+		err = BE_ERR_BADMOUNT;
 
 	zfs_close(zfs_hdl);
 
@@ -561,7 +563,7 @@ be_root_concat(libbe_handle_t *lbh, const char *name, 
 		if (name_len >= BE_MAXPATHLEN)
 			return (BE_ERR_PATHLEN);
 
-		strncpy(result, name, BE_MAXPATHLEN);
+		strlcpy(result, name, BE_MAXPATHLEN);
 		return (BE_ERR_SUCCESS);
 	} else if (name_len + root_len + 1 < BE_MAXPATHLEN) {
 		snprintf(result, BE_MAXPATHLEN, "%s/%s", lbh->root,
@@ -575,11 +577,12 @@ be_root_concat(libbe_handle_t *lbh, const char *name, 
 
 /*
  * Verifies the validity of a boot environment name (A-Za-z0-9-_.). Returns
- * BE_ERR_SUCCESS (0) if name is valid, otherwise returns BE_ERR_INVALIDNAME.
+ * BE_ERR_SUCCESS (0) if name is valid, otherwise returns BE_ERR_INVALIDNAME
+ * or BE_ERR_PATHLEN.
  * Does not set internal library error state.
  */
 int
-be_validate_name(libbe_handle_t *lbh __unused, const char *name)
+be_validate_name(libbe_handle_t *lbh, const char *name)
 {
 	for (int i = 0; *name; i++) {
 		char c = *(name++);
@@ -588,6 +591,12 @@ be_validate_name(libbe_handle_t *lbh __unused, const c
 		return (BE_ERR_INVALIDNAME);
 	}
 
+	/*
+	 * Impose the additional restriction that the entire dataset name must
+	 * not exceed the maximum length of a dataset, i.e. MAXNAMELEN.
+	 */
+	if (strlen(lbh->root) + 1 + strlen(name) > MAXNAMELEN)
+		return (BE_ERR_PATHLEN);
 	return (BE_ERR_SUCCESS);
 }
 
@@ -603,18 +612,17 @@ be_rename(libbe_handle_t *lbh, const char *old, const 
 	zfs_handle_t *zfs_hdl;
 	int err;
 
+	/*
+	 * be_validate_name is documented not to set error state, so we should
+	 * do so here.
+	 */
+	if ((err = be_validate_name(lbh, new)) != 0)
+		return (set_error(lbh, err));
 	if ((err = be_root_concat(lbh, old, full_old)) != 0)
 		return (set_error(lbh, err));
 	if ((err = be_root_concat(lbh, new, full_new)) != 0)
 		return (set_error(lbh, err));
 
-	if ((err = be_validate_name(lbh, new)) != 0)
-		return (err);
-
-	/* Check if old is active BE */
-	if (strcmp(full_old, be_active_path(lbh)) == 0)
-		return (set_error(lbh, BE_ERR_MOUNTED));
-
 	if (!zfs_dataset_exists(lbh->lzh, full_old, ZFS_TYPE_DATASET))
 		return (set_error(lbh, BE_ERR_NOENT));
 
@@ -625,20 +633,17 @@ be_rename(libbe_handle_t *lbh, const char *old, const 
 	    ZFS_TYPE_FILESYSTEM)) == NULL)
 		return (set_error(lbh, BE_ERR_ZFSOPEN));
 
-	/* XXX TODO: Allow a force flag */
-	if (zfs_is_mounted(zfs_hdl, NULL)) {
-		zfs_close(zfs_hdl);
-		return (set_error(lbh, BE_ERR_MOUNTED));
-	}
-
 	/* recurse, nounmount, forceunmount */
-	struct renameflags flags = { 0, 0, 0 };
+	struct renameflags flags = {
+		.nounmount = 1,
+	};
 
 	err = zfs_rename(zfs_hdl, NULL, full_new, flags);
 
 	zfs_close(zfs_hdl);
-
-	return (set_error(lbh, err));
+	if (err != 0)
+		return (set_error(lbh, BE_ERR_UNKNOWN));
+	return (0);
 }
 
 
@@ -693,8 +698,7 @@ be_import(libbe_handle_t *lbh, const char *bootenv, in
 
 	time(&rawtime);
 	len = strlen(buf);
-	strftime(buf + len, BE_MAXPATHLEN - len,
-	    "@%F-%T", localtime(&rawtime));
+	strftime(buf + len, sizeof(buf) - len, "@%F-%T", localtime(&rawtime));
 
 	if ((err = lzc_receive(buf, NULL, NULL, false, fd)) != 0) {
 		switch (err) {
@@ -720,11 +724,28 @@ be_import(libbe_handle_t *lbh, const char *bootenv, in
 
 	err = zfs_clone(zfs, buf, props);
 	zfs_close(zfs);
-
 	nvlist_free(props);
 
-	/* XXX TODO: Figure out how to destroy the ghost... */
-	return (BE_ERR_SUCCESS);
+	if (err != 0)
+		return (set_error(lbh, BE_ERR_UNKNOWN));
+
+	/*
+	 * Finally, we open up the dataset we just cloned the snapshot so that
+	 * we may promote it.  This is necessary in order to clean up the ghost
+	 * snapshot that doesn't need to be seen after the operation is
+	 * complete.
+	 */
+	if ((zfs = zfs_open(lbh->lzh, buf, ZFS_TYPE_DATASET)) == NULL)
+		return (set_error(lbh, BE_ERR_ZFSOPEN));
+
+	err = zfs_promote(zfs);
+	zfs_close(zfs);
+
+	if (err != 0)
+		return (set_error(lbh, BE_ERR_UNKNOWN));
+
+	/* Clean up the temporary snapshot */
+	return (be_destroy(lbh, nbuf, 0));
 }
 
 #if SOON
@@ -901,21 +922,38 @@ be_set_nextboot(libbe_handle_t *lbh, nvlist_t *config,
 	return (0);
 }
 
+/*
+ * Deactivate old BE dataset; currently just sets canmount=noauto
+ */
+static int
+be_deactivate(libbe_handle_t *lbh, const char *ds)
+{
+	zfs_handle_t *zfs;
 
+	if ((zfs = zfs_open(lbh->lzh, ds, ZFS_TYPE_DATASET)) == NULL)
+		return (1);
+	if (zfs_prop_set(zfs, "canmount", "noauto") != 0)
+		return (1);
+	zfs_close(zfs);
+	return (0);
+}
+
 int
 be_activate(libbe_handle_t *lbh, const char *bootenv, bool temporary)
 {
 	char be_path[BE_MAXPATHLEN];
 	char buf[BE_MAXPATHLEN];
+	nvlist_t *config, *dsprops, *vdevs;
+	char *origin;
 	uint64_t pool_guid;
-	nvlist_t *config, *vdevs;
+	zfs_handle_t *zhp;
 	int err;
 
 	be_root_concat(lbh, bootenv, be_path);
 
 	/* Note: be_exists fails if mountpoint is not / */
-	if (!be_exists(lbh, be_path))
-		return (BE_ERR_NOENT);
+	if ((err = be_exists(lbh, be_path)) != 0)
+		return (set_error(lbh, err));
 
 	if (temporary) {
 		config = zpool_get_config(lbh->active_phandle, NULL);
@@ -929,9 +967,7 @@ be_activate(libbe_handle_t *lbh, const char *bootenv, 
 			return (set_error(lbh, BE_ERR_UNKNOWN));
 
 		/* Expected format according to zfsbootcfg(8) man */
-		strcpy(buf, "zfs:");
-		strcat(buf, be_path);
-		strcat(buf, ":");
+		snprintf(buf, sizeof(buf), "zfs:%s:", be_path);
 
 		/* We have no config tree */
 		if (nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE,
@@ -940,16 +976,35 @@ be_activate(libbe_handle_t *lbh, const char *bootenv, 
 
 		return (be_set_nextboot(lbh, vdevs, pool_guid, buf));
 	} else {
+		if (be_deactivate(lbh, lbh->bootfs) != 0)
+			return (-1);
+
 		/* Obtain bootenv zpool */
 		err = zpool_set_prop(lbh->active_phandle, "bootfs", be_path);
+		if (err)
+			return (-1);
 
-		switch (err) {
-		case 0:
-			return (BE_ERR_SUCCESS);
+		zhp = zfs_open(lbh->lzh, be_path, ZFS_TYPE_FILESYSTEM);
+		if (zhp == NULL)
+			return (-1);
 
-		default:
-			/* XXX TODO correct errors */
+		if (be_prop_list_alloc(&dsprops) != 0)
 			return (-1);
+
+		if (be_get_dataset_props(lbh, be_path, dsprops) != 0) {
+			nvlist_free(dsprops);
+			return (-1);
 		}
+
+		if (nvlist_lookup_string(dsprops, "origin", &origin) == 0)
+			err = zfs_promote(zhp);
+		nvlist_free(dsprops);
+
+		zfs_close(zhp);
+
+		if (err)
+			return (-1);
 	}
+
+	return (BE_ERR_SUCCESS);
 }

Modified: stable/11/lib/libbe/be.h
==============================================================================
--- head/lib/libbe/be.h	Sun Aug 12 00:00:13 2018	(r337664)
+++ stable/11/lib/libbe/be.h	Sun Jan  6 02:13:16 2019	(r342807)
@@ -49,7 +49,7 @@ typedef enum be_error {
 	BE_ERR_BADPATH,		/* path not suitable for operation */
 	BE_ERR_PATHBUSY,	/* requested path is busy */
 	BE_ERR_PATHLEN,         /* provided name exceeds maximum length limit */
-	BE_ERR_INVORIGIN,       /* snapshot origin's mountpoint is not '/' */
+	BE_ERR_BADMOUNT,        /* mountpoint is not '/' */
 	BE_ERR_NOORIGIN,        /* could not open snapshot's origin */
 	BE_ERR_MOUNTED,         /* boot environment is already mounted */
 	BE_ERR_NOMOUNT,         /* boot environment is not mounted */
@@ -118,7 +118,7 @@ void libbe_print_on_error(libbe_handle_t *, bool);
 int be_root_concat(libbe_handle_t *, const char *, char *);
 int be_validate_name(libbe_handle_t * __unused, const char *);
 int be_validate_snap(libbe_handle_t *, const char *);
-bool be_exists(libbe_handle_t *, char *);
+int be_exists(libbe_handle_t *, char *);
 
 int be_export(libbe_handle_t *, const char *, int fd);
 int be_import(libbe_handle_t *, const char *, int fd);

Modified: stable/11/lib/libbe/be_access.c
==============================================================================
--- head/lib/libbe/be_access.c	Sun Aug 12 00:00:13 2018	(r337664)
+++ stable/11/lib/libbe/be_access.c	Sun Jan  6 02:13:16 2019	(r342807)
@@ -51,8 +51,10 @@ be_mountcheck_cb(zfs_handle_t *zfs_hdl, void *data)
 		return (0);
 	if (strcmp(mountpoint, info->path) == 0) {
 		info->name = strdup(zfs_get_name(zfs_hdl));
+		free(mountpoint);
 		return (1);
 	}
+	free(mountpoint);
 	return (0);
 }
 
@@ -62,12 +64,12 @@ be_mountcheck_cb(zfs_handle_t *zfs_hdl, void *data)
 int
 be_mounted_at(libbe_handle_t *lbh, const char *path, nvlist_t *details)
 {
-	char be[BE_MAXPATHLEN + 1];
+	char be[BE_MAXPATHLEN];
 	zfs_handle_t *root_hdl;
 	struct be_mountcheck_info info;
 	prop_data_t propinfo;
 
-	bzero(&be, BE_MAXPATHLEN + 1);
+	bzero(&be, BE_MAXPATHLEN);
 	if ((root_hdl = zfs_open(lbh->lzh, lbh->root,
 	    ZFS_TYPE_FILESYSTEM)) == NULL)
 		return (BE_ERR_ZFSOPEN);
@@ -106,24 +108,23 @@ be_mount(libbe_handle_t *lbh, char *bootenv, char *mou
 {
 	char be[BE_MAXPATHLEN];
 	char mnt_temp[BE_MAXPATHLEN];
-	char *path;
 	int mntflags;
 	int err;
 
 	if ((err = be_root_concat(lbh, bootenv, be)) != 0)
 		return (set_error(lbh, err));
 
-	if (!be_exists(lbh, bootenv))
-		return (set_error(lbh, BE_ERR_NOENT));
+	if ((err = be_exists(lbh, bootenv)) != 0)
+		return (set_error(lbh, err));
 
-	if (is_mounted(lbh->lzh, be, &path))
+	if (is_mounted(lbh->lzh, be, NULL))
 		return (set_error(lbh, BE_ERR_MOUNTED));
 
 	mntflags = (flags & BE_MNT_FORCE) ? MNT_FORCE : 0;
 
 	/* Create mountpoint if it is not specified */
 	if (mountpoint == NULL) {
-		strcpy(mnt_temp, "/tmp/be_mount.XXXX");
+		strlcpy(mnt_temp, "/tmp/be_mount.XXXX", sizeof(mnt_temp));
 		if (mkdtemp(mnt_temp) == NULL)
 			return (set_error(lbh, BE_ERR_IO));
 	}
@@ -148,7 +149,8 @@ be_mount(libbe_handle_t *lbh, char *bootenv, char *mou
 	}
 
 	if (result_loc != NULL)
-		strcpy(result_loc, mountpoint == NULL ? mnt_temp : mountpoint);
+		strlcpy(result_loc, mountpoint == NULL ? mnt_temp : mountpoint,
+		    BE_MAXPATHLEN);
 
 	return (BE_ERR_SUCCESS);
 }

Modified: stable/11/lib/libbe/be_error.c
==============================================================================
--- head/lib/libbe/be_error.c	Sun Aug 12 00:00:13 2018	(r337664)
+++ stable/11/lib/libbe/be_error.c	Sun Jan  6 02:13:16 2019	(r342807)
@@ -75,8 +75,8 @@ libbe_error_description(libbe_handle_t *lbh)
 	case BE_ERR_PATHLEN:
 		return ("provided path name exceeds maximum length limit");
 
-	case BE_ERR_INVORIGIN:
-		return ("snapshot origin's mountpoint is not \"/\"");
+	case BE_ERR_BADMOUNT:
+		return ("mountpoint is not \"/\"");
 
 	case BE_ERR_NOORIGIN:
 		return ("could not open snapshot's origin");

Modified: stable/11/lib/libbe/be_info.c
==============================================================================
--- head/lib/libbe/be_info.c	Sun Aug 12 00:00:13 2018	(r337664)
+++ stable/11/lib/libbe/be_info.c	Sun Jan  6 02:13:16 2019	(r342807)
@@ -285,7 +285,7 @@ be_prop_list_free(nvlist_t *be_list)
 /*
  * Usage
  */
-bool
+int
 be_exists(libbe_handle_t *lbh, char *be)
 {
 	char buf[BE_MAXPATHLEN];
@@ -296,25 +296,23 @@ be_exists(libbe_handle_t *lbh, char *be)
 	be_root_concat(lbh, be, buf);
 
 	if (!zfs_dataset_exists(lbh->lzh, buf, ZFS_TYPE_DATASET))
-		return (false);
+		return (BE_ERR_NOENT);
 
 	/* Also check if it's mounted at / */
-	if (be_prop_list_alloc(&dsprops) != 0) {
-		set_error(lbh, BE_ERR_UNKNOWN);
-		return (false);
-	}
+	if (be_prop_list_alloc(&dsprops) != 0)
+		return (BE_ERR_UNKNOWN);
 
 	if (be_get_dataset_props(lbh, buf, dsprops) != 0) {
 		nvlist_free(dsprops);
-		return (false);
+		return (BE_ERR_UNKNOWN);
 	}
 
 	if (nvlist_lookup_string(dsprops, "mountpoint", &mntpoint) == 0) {
 		valid = (strcmp(mntpoint, "/") == 0);
 		nvlist_free(dsprops);
-		return (valid);
+		return (valid ? BE_ERR_SUCCESS : BE_ERR_BADMOUNT);
 	}
 
 	nvlist_free(dsprops);
-	return (false);
+	return (BE_ERR_BADMOUNT);
 }

Modified: stable/11/lib/libbe/libbe.3
==============================================================================
--- head/lib/libbe/libbe.3	Sun Aug 12 00:00:13 2018	(r337664)
+++ stable/11/lib/libbe/libbe.3	Sun Jan  6 02:13:16 2019	(r342807)
@@ -28,7 +28,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd August 10, 2018
+.Dd August 31, 2018
 .Dt LIBBE 3
 .Os
 .Sh NAME
@@ -111,7 +111,7 @@
 .Ft int
 .Fn be_validate_snap "libbe_handle_t *hdl" "const char *snap"
 .Pp
-.Ft bool
+.Ft int
 .Fn be_exists "libbe_handle_t *hdl" "char *be_name"
 .Pp
 .Ft int
@@ -222,7 +222,12 @@ snapshot.
 .Pp
 The
 .Fn be_rename
-function renames a boot environment.
+function renames a boot environment without unmounting it, as if renamed with
+the
+.Fl u
+argument were passed to
+.Nm zfs
+.Cm rename
 .Pp
 The
 .Fn be_activate
@@ -267,6 +272,9 @@ If
 .Fa result
 is not
 .Dv NULL ,
+it should be large enough to accommodate
+.Dv BE_MAXPATHLEN
+including the null terminator.
 the final mount point will be copied into it.
 Setting the
 .Dv BE_MNT_FORCE
@@ -328,7 +336,9 @@ environment name into
 .Pp
 The
 .Fn be_validate_name
-function will validate the given boot environment name.
+function will validate the given boot environment name for both length
+restrictions as well as valid character restrictions.
+This function does not set the internal library error state.
 .Pp
 The
 .Fn be_validate_snap
@@ -342,6 +352,8 @@ The
 function will check whether the given boot environment exists and has a
 mountpoint of
 .Pa / .
+This function does not set the internal library error state, but will return
+the appropriate error.
 .Pp
 The
 .Fn be_export
@@ -434,7 +446,7 @@ BE_ERR_DESTROYMNT,
 BE_ERR_BADPATH,
 BE_ERR_PATHBUSY,
 BE_ERR_PATHLEN,
-BE_ERR_INVORIGIN,
+BE_ERR_BADMOUNT,
 BE_ERR_NOORIGIN,
 BE_ERR_MOUNTED,
 BE_ERR_NOMOUNT,
@@ -455,9 +467,3 @@ were written as a 2017 Google Summer of Code project w
 as a mentor.
 Later work was done by
 .An Kyle Evans Aq Mt kevans@FreeBSD.org .
-.Sh BUGS
-The
-.Fn be_import
-function does not destroy the temporary boot environment it creates for import,
-because the snapshot created to do the import may not be deleted since it is the
-origin of the new boot environment.

Modified: stable/11/sbin/Makefile
==============================================================================
--- stable/11/sbin/Makefile	Sun Jan  6 02:12:55 2019	(r342806)
+++ stable/11/sbin/Makefile	Sun Jan  6 02:13:16 2019	(r342807)
@@ -87,6 +87,7 @@ SUBDIR.${MK_PF}+=	pfctl
 SUBDIR.${MK_PF}+=	pflogd
 SUBDIR.${MK_QUOTAS}+=	quotacheck
 SUBDIR.${MK_ROUTED}+=	routed
+SUBDIR.${MK_ZFS}+=	bectl
 SUBDIR.${MK_ZFS}+=	zfsbootcfg
 
 SUBDIR.${MK_TESTS}+=	tests

Modified: stable/11/sbin/bectl/Makefile
==============================================================================
--- head/sbin/bectl/Makefile	Sun Aug 12 00:00:13 2018	(r337664)
+++ stable/11/sbin/bectl/Makefile	Sun Jan  6 02:13:16 2019	(r342807)
@@ -13,7 +13,6 @@ LIBADD+= util
 CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libzfs/common
 CFLAGS+= -I${SRCTOP}/sys/cddl/compat/opensolaris
 CFLAGS+= -I${SRCTOP}/sys/cddl/contrib/opensolaris/uts/common
-CFLAGS+= -I${SRCTOP}/cddl/contrib/opensolaris/lib/libnvpair
 
 CFLAGS+= -DNEED_SOLARIS_BOOLEAN
 

Modified: stable/11/sbin/bectl/bectl.8
==============================================================================
--- head/sbin/bectl/bectl.8	Sun Aug 12 00:00:13 2018	(r337664)
+++ stable/11/sbin/bectl/bectl.8	Sun Jan  6 02:13:16 2019	(r342807)
@@ -18,7 +18,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd August 10, 2018
+.Dd August 24, 2018
 .Dt BECTL 8
 .Os
 .Sh NAME
@@ -26,130 +26,137 @@
 .Nd Utility to manage Boot Environments on ZFS
 .Sh SYNOPSIS
 .Nm
-activate
+.Cm activate
 .Op Fl t
-.Ao Ar beName Ac
+.Ar beName
 .Nm
-create
+.Cm create
 .Op Fl r
-.Op Fl e Ar nonActiveBe | Fl e Ar beName@snapshot
-.Ao Ar beName Ac
+.Op Fl e Brq Ar nonActiveBe | beName@snapshot
+.Ar beName
 .Nm
-create
+.Cm create
 .Op Fl r
-.Ao Ar beName@snapshot Ac
+.Ar beName@snapshot
 .Nm
-destroy
+.Cm destroy
 .Op Fl F
-.Ao Ar beName | beName@snapshot Ac
+.Brq Ar beName | beName@snapshot
 .Nm
-export
-.Ao Ar sourceBe Ac
+.Cm export
+.Ar sourceBe
 .Nm
-import
-.Ao Ar targetBe Ac
+.Cm import
+.Ar targetBe
 .Nm
-jail
-.Oo Fl o Ar key Ns = Ns Ar value | Fl u Ar key Oc Ns ...
-.Ao Ar jailID | jailName Ac
-.Ao Ar bootenv Ac
+.Cm jail
+.Brq Fl b | Fl U
+.Oo Bro Fl o Ar key Ns = Ns Ar value | Fl u Ar key Brc Oc Ns ...
+.Brq Ar jailID | jailName
+.Ar bootenv
+.Op Ar utility Op Ar argument ...
 .Nm
-list
-.Op Fl a
-.Op Fl D
-.Op Fl H
-.Op Fl s
+.Cm list
+.Op Fl DHas
 .Nm
-mount
-.Ao Ar beName Ac
+.Cm mount
+.Ar beName
 .Op mountpoint
 .Nm
-rename
-.Ao Ar origBeName Ac
-.Ao Ar newBeName Ac
+.Cm rename
+.Ar origBeName
+.Ar newBeName
 .Nm
-{ ujail | unjail }
-.Ao Ar jailID | jailName Ac
-.Ao Ar bootenv Ac
+.Brq Cm ujail | unjail
+.Brq Ar jailID | jailName
+.Ar bootenv
 .Nm
-{ umount | unmount }
+.Brq Cm umount | unmount
 .Op Fl f
-.Ao Ar beName Ac
+.Ar beName
 .Sh DESCRIPTION
 The
 .Nm
-command is used to setup and interact with ZFS boot environments, which are bootable clones of datasets.
+command is used to setup and interact with ZFS boot environments, which are
+bootable clones of datasets.
 .Pp
 .Em Boot Environments
-allows the system to be upgraded, while preserving the old system environment in a separate ZFS dataset.
+allows the system to be upgraded, while preserving the old system environment in
+a separate ZFS dataset.
 .Sh COMMANDS
 The following commands are supported by
 .Nm :
 .Bl -tag -width activate
-.It Ic activate
+.It Xo
+.Cm activate
 .Op Fl t
-.Ar <beName>
-.Pp
+.Ar beName
+.Xc
 Activate the given
 .Ar beName
 as the default boot filesystem.
 If the
 .Op Fl t
 flag is given, this takes effect only for the next boot.
-.It Ic create
+.It Xo
+.Cm create
 .Op Fl r
-.Op Fl e Ar nonActiveBe | Fl e Ar beName@snapshot
-.Ao Ar beName Ac
-.Pp
+.Op Fl e Brq Ar nonActiveBe | beName@snapshot
+.Ar beName
+.Xc
 Creates a new boot environment named
 .Ar beName .
-If the -e param is specified, the new environment will be cloned from the given
-.Ar nonActiveBe | Ar beName@snapshot .
 If the
-.Op Fl r
+.Fl e
+argument is specified, the new environment will be cloned from the given
+.Brq Ar nonActiveBe | Ar beName@snapshot .
+If the
+.Fl r
 flag is given, a recursive boot environment will be made.
-.It Ic create
+.It Xo
+.Cm create
 .Op Fl r
-.Ao Ar beName@snapshot Ac
-.Pp
+.Ar beName@snapshot
+.Xc
 Creates a snapshot of the existing boot environment named
 .Ar beName .
 If the
-.Op Fl r
+.Fl r
 flag is given, a recursive boot environment will be made.
-.It Ic destroy
+.It Xo
+.Cm destroy
 .Op Fl F
-.Ao Ar beName | beName@snapshot Ac
-.Pp
+.Brq Ar beName | beName@snapshot
+.Xc
 Destroys the given
 .Ar beName
 boot environment or
 .Ar beName@snapshot
-snapshot.
+snapshot without confirmation, unlike in
+.Nm beadm .
 Specifying
 .Fl F
 will automatically unmount without confirmation.
-.It Ic export
-.Ao Ar sourceBe Ac
-.Pp
+.It Cm export Ar sourceBe
 Export
 .Ar sourceBe
 to
 .Dv stdout .
 .Dv stdout
 must be piped or redirected to a file.
-.It Ic import
-.Ao Ar targetBe Ac
-.Pp
+.It Cm import Ar targetBe
 Import
 .Ar targetBe
 from
 .Dv stdin .
-.It Ic jail
-.Oo Fl o Ar key Ns = Ns Ar value | Fl u Ar key Oc Ns ...
-.Ao Ar jailID | jailName Ac
+.It Xo
+.Cm jail
+.Brq Fl b | Fl U
+.Oo Bro Fl o Ar key Ns = Ns Ar value | Fl u Ar key Brc Oc Ns ...
+.Brq Ar jailID | jailName
 .Ao Ar bootenv Ac
-.Pp
+.Op Ar utility Op Ar argument ...
+.Xc
 Creates a jail of the given boot environment.
 Multiple
 .Fl o
@@ -161,7 +168,27 @@ will set a jail parameter, and
 .Fl u
 will unset a jail parameter.
 .Pp
+By default, jails are created in interactive mode and
+.Pa /bin/sh
+is
+executed within the jail.
+If
+.Ar utility
+is specified, it will be executed instead of
+.Pa /bin/sh .
+The jail will be destroyed and the boot environment unmounted when the command
+finishes executing, unless the
+.Fl U
+argument is specified.
+.Pp
 The
+.Fl b
+argument enables batch mode, thereby disabling interactive mode.
+The
+.Fl U
+argument will be ignored in batch mode.
+.Pp
+The
 .Va name ,
 .Va host.hostname ,
 and
@@ -172,66 +199,59 @@ below, if they have been overwritten by
 .Fl o .
 .Pp
 All
-.Ar key ,
-.Ar value
+.Ar key Ns = Ns Ar value
 pairs are interpreted as jail parameters as described in
 .Xr jail 8 .
 The following default parameters are provided:
-.Bl -tag -width -indent
-.It Va allow.mount Ns = Ns Ar true
-.It Va allow.mount.devfs Ns = Ns Ar true
-.It Va enforce_statfs Ns = Ns Ar 1
-.It Va name Ns = Ns Ar bootenv
-.It Va host.hostname Ns = Ns Ar bootenv
-.It Va path

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***



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