Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 8 Apr 2019 17:36:24 +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-12@freebsd.org
Subject:   svn commit: r346033 - stable/12/lib/libbe
Message-ID:  <201904081736.x38HaORe027098@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: kevans
Date: Mon Apr  8 17:36:24 2019
New Revision: 346033
URL: https://svnweb.freebsd.org/changeset/base/346033

Log:
  MFC r345848: 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.

Modified:
  stable/12/lib/libbe/be.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/lib/libbe/be.c
==============================================================================
--- stable/12/lib/libbe/be.c	Mon Apr  8 15:52:13 2019	(r346032)
+++ stable/12/lib/libbe/be.c	Mon Apr  8 17:36:24 2019	(r346033)
@@ -51,6 +51,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 *.
@@ -252,13 +255,32 @@ be_destroy(libbe_handle_t *lbh, const char *name, int 
 }
 
 
+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);
 
@@ -276,10 +298,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));



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