Skip to content

Commit

Permalink
overlay: correctly handle dependency tracking
Browse files Browse the repository at this point in the history
Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
  • Loading branch information
Christian Brauner committed Jul 31, 2017
1 parent 31b204e commit 70e95c8
Show file tree
Hide file tree
Showing 2 changed files with 117 additions and 18 deletions.
95 changes: 91 additions & 4 deletions src/lxc/storage/overlay.c
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down
40 changes: 26 additions & 14 deletions src/lxc/storage/storage.c
Expand Up @@ -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)) {
Expand All @@ -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);
Expand All @@ -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;
Expand Down

0 comments on commit 70e95c8

Please sign in to comment.