overlay: correctly handle dependency tracking

parent 31b204e4
......@@ -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);
......
......@@ -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;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment