From: Christian Brauner Date: Sat, 29 Jul 2017 21:10:28 +0000 (+0200) Subject: overlay: correctly handle dependency tracking X-Git-Tag: lxc-2.1.0~32^2~3 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=70e95c8d73384f3afdb569435ab09e6179063a4e;p=thirdparty%2Flxc.git overlay: correctly handle dependency tracking Signed-off-by: Christian Brauner --- diff --git a/src/lxc/storage/overlay.c b/src/lxc/storage/overlay.c index 7a41c0b85..b8fe10bfe 100644 --- a/src/lxc/storage/overlay.c +++ b/src/lxc/storage/overlay.c @@ -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 "//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); diff --git a/src/lxc/storage/storage.c b/src/lxc/storage/storage.c index 7da87161b..468563b8c 100644 --- a/src/lxc/storage/storage.c +++ b/src/lxc/storage/storage.c @@ -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 "//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;