[lxc-devel] [PATCH v2] Update absolute paths for overlay and aufs mounts

Christian Brauner christianvanbrauner at gmail.com
Fri Oct 23 14:02:28 UTC 2015


On Thu, Oct 22, 2015 at 02:15:18PM +0000, Serge Hallyn wrote:
> Quoting Christian Brauner (christianvanbrauner at gmail.com):
> > On Thu, Oct 22, 2015 at 01:13:35PM +0000, Serge Hallyn wrote:
> > > Quoting Christian Brauner (christianvanbrauner at gmail.com):
> > > > On Tue, Oct 20, 2015 at 04:17:18PM +0000, Serge Hallyn wrote:
> > > > > Quoting Christian Brauner (christianvanbrauner at gmail.com):
<snip>
> > > > > 
> > > > > Alternate suggestion.  How about using clear_unexp_config_line() to remove all
> > > > > lxc.mount.entry lines from unexpanded config first, then run through this loop
> > > > > and simply add the new ones?
> > > > > 
> > > > > The lxc_string_replace approach feels problematic.
> > > > 
> > > > I thought so too, but clear_unexp_config_line() will not just clear mount
> > > > entries from the containers config but also entries from files like common.conf
> > > > which are also present in lxc_conf->mount_list e.g.:
> > > 
> > > Hm, might be the other way around, but yeah we can't do that.
> > > 
> > > But if the config file has say a commented version of the line before
> > > the real line, you'll update only the comment right?
> > > 
> > > So can you do lik eclear_unexp_config_line() does and make sure you
> > > are looking for only lines beginning with "lxc.mount.entry += +"
> > > and then have the mnt_entry?  I guess that should do.
> > > 
> > 
> > I'll test that and get back with an updated patch. I *try* to think of something
> > smarter... Do you want me to avoid lxc_string_replace()?
> 
> Not because of lxc_string_replace itself, but because it won't confine
> itself to one ^.*$ line.  So if you cna make it work, that's fine with me,
> but it feels like a wrecking ball in our unexpanded_config china shop.

Ok, we are clear that we need to update both, the lxc_conf->mount_list and the
lxc_conf->unexpanded_config. I suggest we split this into separate functions.
For updating lxc_conf->unexpanded_config we could add a function to confile.c
which is similar to clone_update_unexp_hooks(). It would look like this:

bool clone_update_unexp_ovl_dir(struct lxc_conf *conf, const char *oldpath,
				const char *newpath, const char *oldname,
				const char *newname, const char *ovldir)
{
	const char *key = "lxc.mount.entry";
	int ret;
	char *lstart = conf->unexpanded_config;
	char *lend;
	char *p;
	char *q;
	size_t newdirlen = strlen(ovldir) + strlen(newpath) + strlen(newname) + 1 + 1;
	size_t olddirlen = strlen(ovldir) + strlen(oldpath) + strlen(oldname) + 1 + 1;
	char *olddir = alloca(olddirlen + 1);
	char *newdir = alloca(newdirlen + 1);

	ret = snprintf(olddir, olddirlen+1, "%s=%s/%s", ovldir, oldpath, oldname);
	if (ret < 0 || ret >= olddirlen+1) {
		ERROR("Bug in %s", __func__);
		return false;
	}
	ret = snprintf(newdir, newdirlen+1, "%s=%s/%s", ovldir, newpath, newname);
	if (ret < 0 || ret >= newdirlen+1) {
		ERROR("Bug in %s", __func__);
		return false;
	}
	if (!conf->unexpanded_config)
		return true;
	while (*lstart) {
		lend = strchr(lstart, '\n');
		if (!lend)
			lend = lstart + strlen(lstart);
		else
			lend++;
		if (strncmp(lstart, key, strlen(key)) != 0) {
			lstart = lend;
			continue;
		}
		p = strchr(lstart+strlen(key), '=');
		if (!p) {
			lstart = lend;
			continue;
		}
		p++;
		while (isblank(*p))
			p++;
		if (!*p)
			return true;
		/* Should we check that when an lxc.mount.entry is found the
		 * substrings "overlay" or "aufs" are actually present before we
		 * try to update the line? This seems like a bit more safety. We
		 * can check for " overlay " and " aufs " since both substrings
		 * need to have at least one space before and after them. When
		 * the space before or after is missing it is very likely that
		 * these substrings are part of a path or something else. So we
		 * shouldn't bother to do any further work...
		 */
		if (!strstr(p, " overlay ") && !strstr(p, " aufs "))
			continue;
		if (!(q = strstr(p, olddir))) {
			lstart = lend;
			continue;
		}
		/* replace the olddir with newdir */
		if (olddirlen >= newdirlen) {
			size_t diff = olddirlen - newdirlen;
			memcpy(q, newdir, newdirlen);
			if (olddirlen != newdirlen) {
				memmove(lend-diff, lend, strlen(lend)+1);
				lend -= diff;
				conf->unexpanded_len -= diff;
			}
			lstart = lend;
		} else {
			char *new;
			size_t diff = newdirlen - olddirlen;
			size_t oldlen = conf->unexpanded_len;
			size_t newlen = oldlen + diff;
			size_t poffset = q - conf->unexpanded_config;
			new = realloc(conf->unexpanded_config, newlen);
			if (!new) {
				ERROR("Out of memory");
				return false;
			}
			conf->unexpanded_len = newlen;
			new[newlen-1] = '\0';
			lend = new + (lend - conf->unexpanded_config);
			/* move over the remainder, /$hookname\n$rest */
			memmove(new+poffset+newdirlen,
					new+poffset+olddirlen,
					oldlen-poffset-olddirlen);
			conf->unexpanded_config = new;
			memcpy(new+poffset, newdir, newdirlen);
			lstart = lend + diff;
		}
	}
	return true;
}

If you agree with this approach we can put another function in lxccontainer.c
which updates lxc_conf->mount_list and which calls clone_update_unexp_ovl_dir().
-------------- 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/20151023/9c64e53e/attachment.sig>


More information about the lxc-devel mailing list