On Thu, Oct 22, 2015 at 02:15:18PM +0000, Serge Hallyn wrote:
> Quoting Christian Brauner (christianvanbrau...@gmail.com):
> > On Thu, Oct 22, 2015 at 01:13:35PM +0000, Serge Hallyn wrote:
> > > Quoting Christian Brauner (christianvanbrau...@gmail.com):
> > > > On Tue, Oct 20, 2015 at 04:17:18PM +0000, Serge Hallyn wrote:
> > > > > Quoting Christian Brauner (christianvanbrau...@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().

Attachment: signature.asc
Description: PGP signature

_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to