[lxc-devel] [PATCH] mod_rdep(): Write path and name of clone to file

Christian Brauner christianvanbrauner at gmail.com
Thu Aug 27 16:47:55 UTC 2015


Hi,

this is actually the old version. I implemented it differently using mmap() +
+ memmem() + memmove() + munmap() + ftruncate() to avoid using a temporary file.
It's present as a PR on Github. Would be nice if you could say something about
it too:

https://github.com/lxc/lxc/pull/641

Christian

On Thu, Aug 27, 2015 at 04:17:28PM +0000, Serge Hallyn wrote:
> Quoting Christian Brauner (christianvanbrauner at gmail.com):
> > 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
> 
> Hi,
> 
> this seems like a good idea to me.  Thanks for working on it.  A few notes
> below, but overall +1.
> 
> >   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;
> 
> please initialize buf to NULL.
> 
> > +	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)
> 
> close f1
> 
> > +			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);
> 
> close f1
> 
> > +					remove(path2);
> > +					goto out;
> > +				}
> > +			}
> > +		}
> > +		free(buf);
> > +		fclose(f1);
> > +		fclose(f2);
> > +		rename(path2, path1);
> 
> I htink it's best to check for failures in these fclose
> and renames.  If either fclose fails, you can salvage
> the old snapshots file.  If rename fails, well you can at
> least tell the user he's hosed.
> 
> >  	}
> >  
> >  	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);
> 
> Check for stat failure here.
> 
> > +	v = fbuf.st_size;
> >  	bret = v != 0;
> >  
> >  out:
> > -- 
> > 2.5.0
> > 
> > _______________________________________________
> > lxc-devel mailing list
> > lxc-devel at lists.linuxcontainers.org
> > http://lists.linuxcontainers.org/listinfo/lxc-devel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20150827/4890e5f9/attachment.sig>


More information about the lxc-devel mailing list