[lxc-devel] [PATCH] mod_rdep(): Write path and name of clone to file
Christian Brauner
christianvanbrauner at gmail.com
Thu Aug 13 16:05:46 UTC 2015
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 <christianvanbrauner at 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
More information about the lxc-devel
mailing list