svn commit: r345848 - head/lib/libbe

Kyle Evans kevans at FreeBSD.org
Wed Apr 3 17:04:39 UTC 2019


Author: kevans
Date: Wed Apr  3 17:04:38 2019
New Revision: 345848
URL: https://svnweb.freebsd.org/changeset/base/345848

Log:
  libbe(3): Add a serial to the generated snapshot names
  
  To use bectl in an example, when one creates a new boot environment with
  either `bectl create <be>` or `bectl create -e <otherbe> <be>`, libbe will
  take a snapshot of the original boot environment to clone. Previously, this
  used %F-%T date format as the snapshot name, but this has some limitations-
  attempting to create multiple boot environments in quick succession may
  collide if done within the same second.
  
  Tack a serial onto it to reduce the chances of a collision... we could still
  collide if multiple processes/threads are creating boot environments at the
  same time, but this is likely not a big concern as this has only been
  reported as occurring in freebsd-ci setup.
  
  MFC after:	3 days

Modified:
  head/lib/libbe/be.c

Modified: head/lib/libbe/be.c
==============================================================================
--- head/lib/libbe/be.c	Wed Apr  3 17:02:18 2019	(r345847)
+++ head/lib/libbe/be.c	Wed Apr  3 17:04:38 2019	(r345848)
@@ -56,6 +56,9 @@ static int be_create_child_noent(libbe_handle_t *lbh, 
 static int be_create_child_cloned(libbe_handle_t *lbh, const char *active);
 #endif
 
+/* Arbitrary... should tune */
+#define	BE_SNAP_SERIAL_MAX	1024
+
 /*
  * 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 *.
@@ -320,13 +323,32 @@ be_destroy(libbe_handle_t *lbh, const char *name, int 
 	    options & ~BE_DESTROY_ORIGIN));
 }
 
+static void
+be_setup_snapshot_name(libbe_handle_t *lbh, char *buf, size_t buflen)
+{
+	time_t rawtime;
+	int len, serial;
+
+	time(&rawtime);
+	len = strlen(buf);
+	len += strftime(buf + len, buflen - len, "@%F-%T", localtime(&rawtime));
+	/* No room for serial... caller will do its best */
+	if (buflen - len < 2)
+		return;
+
+	for (serial = 0; serial < BE_SNAP_SERIAL_MAX; ++serial) {
+		snprintf(buf + len, buflen - len, "-%d", serial);
+		if (!zfs_dataset_exists(lbh->lzh, buf, ZFS_TYPE_SNAPSHOT))
+			return;
+	}
+}
+
 int
 be_snapshot(libbe_handle_t *lbh, const char *source, const char *snap_name,
     bool recursive, char *result)
 {
 	char buf[BE_MAXPATHLEN];
-	time_t rawtime;
-	int len, err;
+	int err;
 
 	be_root_concat(lbh, source, buf);
 
@@ -344,10 +366,8 @@ be_snapshot(libbe_handle_t *lbh, const char *source, c
 			snprintf(result, BE_MAXPATHLEN, "%s@%s", source,
 			    snap_name);
 	} else {
-		time(&rawtime);
-		len = strlen(buf);
-		strftime(buf + len, sizeof(buf) - len,
-		    "@%F-%T", localtime(&rawtime));
+		be_setup_snapshot_name(lbh, buf, sizeof(buf));
+
 		if (result != NULL && strlcpy(result, strrchr(buf, '/') + 1,
 		    sizeof(buf)) >= sizeof(buf))
 			return (set_error(lbh, BE_ERR_INVALIDNAME));


More information about the svn-src-head mailing list