]> git.proxmox.com Git - mirror_lxc.git/commitdiff
overlay: correctly handle dependency tracking
authorChristian Brauner <christian.brauner@ubuntu.com>
Sat, 29 Jul 2017 21:10:28 +0000 (23:10 +0200)
committerChristian Brauner <christian.brauner@ubuntu.com>
Mon, 31 Jul 2017 21:34:19 +0000 (23:34 +0200)
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/storage/overlay.c
src/lxc/storage/storage.c

index 7a41c0b85e847c30b7588d877e53c5bc10919184..b8fe10bfe4473081dbdd8a5360213f7769fa18dc 100644 (file)
@@ -186,10 +186,11 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
                }
        } else if (!strcmp(orig->type, "overlayfs") ||
                   !strcmp(orig->type, "overlay")) {
-               char *osrc, *odelta, *nsrc, *ndelta, *work;
-               char *lastslash;
+               char *clean_old_path, *clean_new_path;
+               char *lastslash, *ndelta, *nsrc, *odelta, *osrc, *s1, *s2, *s3,
+                   *work;
                int ret, lastslashidx;
-               size_t len;
+               size_t len, name_len;
 
                osrc = strdup(orig->src);
                if (!osrc) {
@@ -298,7 +299,93 @@ int ovl_clonepaths(struct lxc_storage *orig, struct lxc_storage *new, const char
                        return -1;
                }
 
-               return ovl_do_rsync(orig, new, conf);
+               ret = ovl_do_rsync(orig, new, conf);
+               if (ret < 0)
+                       return -1;
+
+               /* When we create an overlay snapshot of an overlay container in
+                * the snapshot directory under "<lxcpath>/<name>/snaps/" we
+                * don't need to record a dependency. If we would restore would
+                * also fail.
+                */
+               clean_old_path = lxc_deslashify(oldpath);
+               if (!clean_old_path)
+                       return -1;
+
+               clean_new_path = lxc_deslashify(lxcpath);
+               if (!clean_new_path) {
+                       free(clean_old_path);
+                       return -1;
+               }
+
+               s1 = strrchr(clean_old_path, '/');
+               if (!s1) {
+                       ERROR("Failed to detect \"/\" in string \"%s\"", s1);
+                       free(clean_old_path);
+                       free(clean_new_path);
+                       return -1;
+               }
+
+               s2 = strrchr(clean_new_path, '/');
+               if (!s2) {
+                       ERROR("Failed to detect \"/\" in string \"%s\"", s2);
+                       free(clean_old_path);
+                       free(clean_new_path);
+                       return -1;
+               }
+
+               if (!strncmp(s1, "/snaps", sizeof("/snaps") - 1)) {
+                       s1 = clean_new_path;
+                       s2 = clean_old_path;
+                       s3 = (char *)cname;
+                       name_len = strlen(cname);
+                       len = strlen(clean_new_path);
+               } else if (!strncmp(s2, "/snaps", sizeof("/snaps") - 1)) {
+                       s1 = clean_old_path;
+                       s2 = clean_new_path;
+                       s3 = (char *)oldname;
+                       name_len = strlen(oldname);
+                       len = strlen(clean_old_path);
+               } else {
+                       free(clean_old_path);
+                       free(clean_new_path);
+                       return 0;
+               }
+
+               if (!strncmp(s1, s2, len)) {
+                       char *tmp;
+
+                       tmp = (char *)(s2 + len + 1);
+                       if (*tmp == '\0') {
+                               free(clean_old_path);
+                               free(clean_new_path);
+                               return 0;
+                       }
+
+                       name_len = strlen(s3);
+                       if (strncmp(s3, tmp, name_len)) {
+                               free(clean_old_path);
+                               free(clean_new_path);
+                               return 0;
+                       }
+
+                       tmp += name_len + 1;
+                       if (*tmp == '\0') {
+                               free(clean_old_path);
+                               free(clean_new_path);
+                               return 0;
+                       }
+
+                       if (!strncmp(tmp, "snaps", sizeof("snaps") - 1)) {
+                               free(clean_old_path);
+                               free(clean_new_path);
+                               return LXC_CLONE_SNAPSHOT;
+                       }
+               }
+
+               free(clean_old_path);
+               free(clean_new_path);
+               return 0;
        } else {
                ERROR("overlay clone of %s container is not yet supported",
                      orig->type);
index 7da87161b0b4753dbe99512c8e0c764337eb0ecb..468563b8ceebd8ec6976b5ba54c767deb4a20a9c 100644 (file)
@@ -386,7 +386,7 @@ struct lxc_storage *storage_copy(struct lxc_container *c, const char *cname,
                snap = false;
 
        /* If newtype is NULL and snapshot is set, then use overlay. */
-       if (!bdevtype && !keepbdevtype && snap && strcmp(orig->type, "dir") == 0)
+       if (!bdevtype && !keepbdevtype && snap && !strcmp(orig->type, "dir"))
                bdevtype = "overlay";
 
        if (am_unpriv() && !unpriv_snap_allowed(orig, bdevtype, snap, maybe_snap)) {
@@ -396,20 +396,23 @@ struct lxc_storage *storage_copy(struct lxc_container *c, const char *cname,
        }
 
        *needs_rdep = false;
-       if (bdevtype && !strcmp(orig->type, "dir") &&
-           (strcmp(bdevtype, "aufs") == 0 ||
-            strcmp(bdevtype, "overlayfs") == 0 ||
-            strcmp(bdevtype, "overlay") == 0)) {
-               *needs_rdep = true;
-       } else if (snap && !strcmp(orig->type, "lvm") &&
-                  !lvm_is_thin_volume(orig->src)) {
-               *needs_rdep = true;
-       }
+       if (bdevtype) {
+               if (snap && !strcmp(orig->type, "lvm") &&
+                   !lvm_is_thin_volume(orig->src))
+                       *needs_rdep = true;
+               else if (!strcmp(bdevtype, "overlay") ||
+                        !strcmp(bdevtype, "overlayfs"))
+                       *needs_rdep = true;
+       } else {
+               if (!snap && strcmp(oldpath, lxcpath))
+                       bdevtype = "dir";
+               else
+                       bdevtype = orig->type;
 
-       if (strcmp(oldpath, lxcpath) && !bdevtype && !snap)
-               bdevtype = "dir";
-       else if (!bdevtype)
-               bdevtype = orig->type;
+               if (!strcmp(bdevtype, "overlay") ||
+                   !strcmp(bdevtype, "overlayfs"))
+                       *needs_rdep = true;
+       }
 
        /* get new bdev type */
        new = storage_get(bdevtype);
@@ -428,6 +431,15 @@ struct lxc_storage *storage_copy(struct lxc_container *c, const char *cname,
                goto on_error_put_new;
        }
 
+       /* When we create an overlay snapshot of an overlay container in the
+        * snapshot directory under "<lxcpath>/<name>/snaps/" we don't need to
+        * record a dependency. If we would restore would also fail.
+        */
+       if ((!strcmp(new->type, "overlay") ||
+            !strcmp(new->type, "overlayfs")) &&
+           ret == LXC_CLONE_SNAPSHOT)
+               *needs_rdep = false;
+
        /* btrfs */
        if (!strcmp(orig->type, "btrfs") && !strcmp(new->type, "btrfs")) {
                bool bret = false;