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));


_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to