svn commit: r340592 - in head: lib/libbe sbin/bectl

Kyle Evans kevans at FreeBSD.org
Mon Nov 19 02:12:10 UTC 2018


Author: kevans
Date: Mon Nov 19 02:12:08 2018
New Revision: 340592
URL: https://svnweb.freebsd.org/changeset/base/340592

Log:
  bectl(3)/libbe(3): Allow BE root to be specified
  
  Add an undocumented -r option preceding the bectl subcommand to specify a BE
  root to operate out of. This will remain undocumented for now, as some
  caveats apply:
  
  - BEs cannot be activated in the pool that doesn't contain the rootfs
  - bectl create cannot work out of the box without the -e option right now,
    since it defaults to the rootfs and cross-pool cloning doesn't work like
    that (IIRC)
  
  Plumb the BE root through to libbe(3) so that some things -can- be done to
  it, e.g.
  
  bectl -r tank/ROOT create -e default upgrade
  bectl -r tank/ROOT mount upgrade /mnt
  
  this aides in some upgrade setups where rootfs is not necessarily ZFS, and
  also makes it easier/possible to regression-test bectl when combined with a
  file-backed zpool.
  
  MFC after:	3 days
  Differential Revision:	https://reviews.freebsd.org/D18029

Modified:
  head/lib/libbe/be.c
  head/lib/libbe/be.h
  head/lib/libbe/be_info.c
  head/lib/libbe/libbe.3
  head/sbin/bectl/bectl.c

Modified: head/lib/libbe/be.c
==============================================================================
--- head/lib/libbe/be.c	Mon Nov 19 00:54:31 2018	(r340591)
+++ head/lib/libbe/be.c	Mon Nov 19 02:12:08 2018	(r340592)
@@ -74,7 +74,7 @@ be_locate_rootfs(libbe_handle_t *lbh)
  * dataset, for example, zroot/ROOT.
  */
 libbe_handle_t *
-libbe_init(void)
+libbe_init(const char *root)
 {
 	libbe_handle_t *lbh;
 	char *poolname, *pos;
@@ -89,16 +89,21 @@ libbe_init(void)
 	if ((lbh->lzh = libzfs_init()) == NULL)
 		goto err;
 
-	/* Grab rootfs, we'll work backwards from there */
+	/*
+	 * Grab rootfs, we'll work backwards from there if an optional BE root
+	 * has not been passed in.
+	 */
 	if (be_locate_rootfs(lbh) != 0)
 		goto err;
-
-	/* Strip off the final slash from the rootfs to get the be root */
-	strlcpy(lbh->root, lbh->rootfs, sizeof(lbh->root));
-	pos = strrchr(lbh->root, '/');
-	if (pos == NULL)
-		goto err;
-	*pos = '\0';
+	if (root == NULL) {
+		/* Strip off the final slash from rootfs to get the be root */
+		strlcpy(lbh->root, lbh->rootfs, sizeof(lbh->root));
+		pos = strrchr(lbh->root, '/');
+		if (pos == NULL)
+			goto err;
+		*pos = '\0';
+	} else
+		strlcpy(lbh->root, root, sizeof(lbh->root));
 
 	if ((pos = strchr(lbh->root, '/')) == NULL)
 		goto err;

Modified: head/lib/libbe/be.h
==============================================================================
--- head/lib/libbe/be.h	Mon Nov 19 00:54:31 2018	(r340591)
+++ head/lib/libbe/be.h	Mon Nov 19 02:12:08 2018	(r340592)
@@ -63,7 +63,7 @@ typedef enum be_error {
 
 
 /* Library handling functions: be.c */
-libbe_handle_t *libbe_init(void);
+libbe_handle_t *libbe_init(const char *root);
 void libbe_close(libbe_handle_t *);
 
 /* Bootenv information functions: be_info.c */

Modified: head/lib/libbe/be_info.c
==============================================================================
--- head/lib/libbe/be_info.c	Mon Nov 19 00:54:31 2018	(r340591)
+++ head/lib/libbe/be_info.c	Mon Nov 19 02:12:08 2018	(r340592)
@@ -42,7 +42,10 @@ const char *
 be_active_name(libbe_handle_t *lbh)
 {
 
-	return (strrchr(lbh->rootfs, '/') + sizeof(char));
+	if (*lbh->rootfs != '\0')
+		return (strrchr(lbh->rootfs, '/') + sizeof(char));
+	else
+		return (lbh->rootfs);
 }
 
 
@@ -63,7 +66,10 @@ const char *
 be_nextboot_name(libbe_handle_t *lbh)
 {
 
-	return (strrchr(lbh->bootfs, '/') + sizeof(char));
+	if (*lbh->bootfs != '\0')
+		return (strrchr(lbh->bootfs, '/') + sizeof(char));
+	else
+		return (lbh->bootfs);
 }
 
 

Modified: head/lib/libbe/libbe.3
==============================================================================
--- head/lib/libbe/libbe.3	Mon Nov 19 00:54:31 2018	(r340591)
+++ head/lib/libbe/libbe.3	Mon Nov 19 02:12:08 2018	(r340592)
@@ -28,7 +28,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd August 31, 2018
+.Dd November 17, 2018
 .Dt LIBBE 3
 .Os
 .Sh NAME
@@ -39,7 +39,7 @@
 .Sh SYNOPSIS
 .In be.h
 .Ft "libbe_handle_t *hdl" Ns
-.Fn libbe_init void
+.Fn libbe_init "const char *be_root"
 .Pp
 .Ft void
 .Fn libbe_close "libbe_handle_t *hdl"
@@ -157,13 +157,16 @@ errno otherwise as described in
 .Pp
 The
 .Fn libbe_init
-function initializes
+function takes an optional BE root and initializes
 .Nm ,
 returning a
 .Vt "libbe_handle_t *"
 on success, or
 .Dv NULL
 on error.
+If a BE root is supplied,
+.Nm
+will only operate out of that pool and BE root.
 An error may occur if:
 .Bl -column
 .It /boot and / are not on the same filesystem and device,
@@ -184,11 +187,15 @@ invalidating the handle in the process.
 .Pp
 The
 .Fn be_active_name
-function returns the name of the currently booted boot environment,
+function returns the name of the currently booted boot environment.
+This boot environment may not belong to the same BE root as the root libbe
+is operating on!
 .Pp
 The
 .Fn be_active_path
 function returns the full path of the currently booted boot environment.
+This boot environment may not belong to the same BE root as the root libbe
+is operating on!
 .Pp
 The
 .Fn be_nextboot_name

Modified: head/sbin/bectl/bectl.c
==============================================================================
--- head/sbin/bectl/bectl.c	Mon Nov 19 00:54:31 2018	(r340591)
+++ head/sbin/bectl/bectl.c	Mon Nov 19 02:12:08 2018	(r340592)
@@ -489,12 +489,25 @@ int
 main(int argc, char *argv[])
 {
 	const char *command;
+	char *root;
 	int command_index, rc;
 
+	root = NULL;
 	if (argc < 2)
 		return (usage(false));
 
-	command = argv[1];
+	if (strcmp(argv[1], "-r") == 0) {
+		if (argc < 4)
+			return (usage(false));
+		root = strdup(argv[2]);
+		command = argv[3];
+		argc -= 3;
+		argv += 3;
+	} else {
+		command = argv[1];
+		argc -= 1;
+		argv += 1;
+	}
 
 	/* Handle command aliases */
 	if (strcmp(command, "umount") == 0)
@@ -512,13 +525,12 @@ main(int argc, char *argv[])
 	}
 
 
-	if ((be = libbe_init()) == NULL)
+	if ((be = libbe_init(root)) == NULL)
 		return (-1);
 
 	libbe_print_on_error(be, true);
 
-	/* XXX TODO: can be simplified if offset by 2 instead of one */
-	rc = command_map[command_index].fn(argc-1, argv+1);
+	rc = command_map[command_index].fn(argc, argv);
 
 	libbe_close(be);
 	return (rc);


More information about the svn-src-head mailing list