This is rather a first-pass suggestion than a full commit to discuss: The idea: ---------
- If a container has clone-snapshots created by lxc-clone -n NAME -N NEWNAME -s then even the new version lxc-destroy (see patch on github) cannot remove the container because the original container only stores the number of clone-snapshotted containers in the file "lxc_snapshots". Hence, it has no way of looking up the copy-snapshots containers that belong to the container to delete them and then delete the original container. I suggest modifying mod_rdep() so it will store not the plain number in the file but rather the paths and names to the containers that are a clone-snapshots (similar to the "lxc_rdepends" file for the clones). An example how the file "lxc_snapshots" of the original container could look like would be: /var/lib/lxc:bb /var/lib/lxc:cc /opt:dd This would be an example of a container that provides the base for three clone-snapshots bb, cc, and dd. Where bb and cc both are placed in the usual path for privileged containers and dd is placed in a custom path. I could then go on to modify lxc-destroy to actually not just remove the original container including all snapshots but also with all its clone-snapshots. Following is a first idea for rewriting mod_rdep(). If you think its generally not something you want just leave a short reply. If you would like to have this feature but rather implement it in a different way it would be nice if you could leave some more feedback and suggestions and then I'll rewrite the patch. Thanks! Summary: -------- - Add additional argument to function that takes in the clone-snapshotted lxc_container. - Have mod_rdep() write the path and name of the clone-snapshotted container the file lxc_snapshots of the original container. - If a clone-snapshot gets deleted the corresponding line in the file lxc_snapshot of the original container will be deleted and the file updated. - Change has_fs_snapshots() to check if the file is empty. If it is it is safe to delete the original container if the file is not empty then it is not safe. Signed-off-by: Christian Brauner <christianvanbrau...@gmail.com> --- src/lxc/lxccontainer.c | 98 +++++++++++++++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 37 deletions(-) diff --git a/src/lxc/lxccontainer.c b/src/lxc/lxccontainer.c index 1c103e8..e10ccc7 100644 --- a/src/lxc/lxccontainer.c +++ b/src/lxc/lxccontainer.c @@ -1970,47 +1970,76 @@ out: WRAP_API_1(bool, lxcapi_save_config, const char *) -static bool mod_rdep(struct lxc_container *c, bool inc) +static bool mod_rdep(struct lxc_container *c0, struct lxc_container *c, bool inc) { - char path[MAXPATHLEN]; - int ret, v = 0; - FILE *f; + char *buf; + size_t len = 0; + FILE *f1, *f2; + char path1[MAXPATHLEN]; + char path2[MAXPATHLEN]; + int ret; bool bret = false; - if (container_disk_lock(c)) + if (container_disk_lock(c0)) return false; - ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, - c->name); + + ret = snprintf(path1, MAXPATHLEN, "%s/%s/lxc_snapshots", c0->config_path, + c0->name); if (ret < 0 || ret > MAXPATHLEN) goto out; - f = fopen(path, "r"); - if (f) { - ret = fscanf(f, "%d", &v); - fclose(f); - if (ret != 1) { - ERROR("Corrupted file %s", path); + + if (inc) { + f1 = fopen(path1, "a"); + if (!f1) + goto out; + + if (fprintf(f1, "%s:%s\n", c->config_path, c->name) < 0) { + ERROR("Error writing new snapshots value"); + fclose(f1); goto out; } - } - v += inc ? 1 : -1; - f = fopen(path, "w"); - if (!f) - goto out; - if (fprintf(f, "%d\n", v) < 0) { - ERROR("Error writing new snapshots value"); - fclose(f); - goto out; - } - ret = fclose(f); - if (ret != 0) { - SYSERROR("Error writing to or closing snapshots file"); - goto out; + + ret = fclose(f1); + if (ret != 0) { + SYSERROR("Error writing to or closing snapshots file"); + goto out; + } + } else if (!inc) { + ret = snprintf(path1, MAXPATHLEN, "%s/%s/lxc_snapshots", + c0->config_path, c0->name); + if (ret < 0 || ret > MAXPATHLEN) + goto out; + ret = snprintf(path2, MAXPATHLEN, "%s/%s/lxc_snapshots_tmp", + c0->config_path, c0->name); + if (ret < 0 || ret > MAXPATHLEN) + goto out; + f1 = fopen(path1, "r"); + if (!f1) + goto out; + f2 = fopen(path2, "w"); + if (!f2) + goto out; + while (getline(&buf, &len, f1) != -1) { + if (!strstr(strstr(buf, c->config_path), c->name)) { + if (fprintf(f2, "%s", buf) < 0) { + ERROR("Error writing new snapshots " + "value"); + fclose(f2); + remove(path2); + goto out; + } + } + } + free(buf); + fclose(f1); + fclose(f2); + rename(path2, path1); } bret = true; out: - container_disk_unlock(c); + container_disk_unlock(c0); return bret; } @@ -2052,7 +2081,7 @@ static void mod_all_rdeps(struct lxc_container *c, bool inc) lxcpath, lxcname); continue; } - if (!mod_rdep(p, inc)) + if (!mod_rdep(p, c, inc)) ERROR("Failed to increase numsnapshots for %s:%s", lxcpath, lxcname); lxc_container_put(p); @@ -2067,20 +2096,15 @@ static bool has_fs_snapshots(struct lxc_container *c) { char path[MAXPATHLEN]; int ret, v; - FILE *f; + struct stat fbuf; bool bret = false; ret = snprintf(path, MAXPATHLEN, "%s/%s/lxc_snapshots", c->config_path, c->name); if (ret < 0 || ret > MAXPATHLEN) goto out; - f = fopen(path, "r"); - if (!f) - goto out; - ret = fscanf(f, "%d", &v); - fclose(f); - if (ret != 1) - goto out; + stat(path, &fbuf); + v = fbuf.st_size; bret = v != 0; out: -- 2.5.0 _______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel