[lxc-devel] [PATCH v5] Make overlayfs mounts work directly
Serge Hallyn
serge.hallyn at ubuntu.com
Wed Oct 7 13:20:35 UTC 2015
mount targets when relative are relative to the mounted rootfs dir
(with absolute paths under the *not-mounted* rootfs dir being auto-
translated to being under the mounted rootfs dir).
These paths would be relative to the containerdir. I think that's too
confusing.
Quoting Christian Brauner (christianvanbrauner at gmail.com):
> I now wonder if it wouldn't be smarter to force users to specify relative paths
> for upper and workdir
>
> lxc.mount.entry = /lower merged overlay lowerdir=/lower,upper=upper,workdir=workdir,create=dir
>
> and fill in the missing path in mount_entry_create_*_dirs(). Otherwise these
> mounts won't work out of the box when a clone of the container is made and
> started... Thoughts?
>
> On Tue, Oct 06, 2015 at 08:38:13PM +0200, Christian Brauner wrote:
> > When users wanted to mount overlay directories with lxc.mount.entry they had to
> > create upperdirs and workdirs beforehand in order to mount them. To create it
> > for them we add the functions mount_entry_create_overlay_dirs() and
> > mount_entry_create_aufs_dirs() which do this for them. User can now simply
> > specify e.g.:
> >
> > lxc.mount.entry = /lower merged overlay lowerdir=/lower,upper=/upper,workdir=/workdir,create=dir
> >
> > and /upper and /workdir will be created for them. /upper and /workdir need to
> > be absolute paths to directories which are created under the containerdir (e.g.
> > under $lxcpath/CONTAINERNAME/). Relative mountpoints, mountpoints outside the
> > containerdir, and mountpoints within the container's rootfs are ignored. (The
> > latter *might* change in the future should it be considered safe/useful.)
> >
> > Specifying
> >
> > lxc.mount.entry = /lower merged overlay lowerdir=/lower:/lower2,create=dir
> >
> > will lead to a read-only overlay mount in accordance with the
> > kernel-documentation.
> >
> > Specifying
> >
> > lxc.mount.entry = /lower merged overlay lowerdir=/lower,create=dir
> >
> > will fail when no upperdir and workdir options are given.
> >
> > Signed-off-by: Christian Brauner <christianvanbrauner at gmail.com>
> > Acked-by: Serge E. Hallyn <serge.hallyn at ubuntu.com>
> > ---
> > src/lxc/conf.c | 162 ++++++++++++++++++++++++++++++++++++++++++++++++++++-----
> > 1 file changed, 150 insertions(+), 12 deletions(-)
> >
> > diff --git a/src/lxc/conf.c b/src/lxc/conf.c
> > index 6728c78..5a3209a 100644
> > --- a/src/lxc/conf.c
> > +++ b/src/lxc/conf.c
> > @@ -1815,13 +1815,151 @@ static void cull_mntent_opt(struct mntent *mntent)
> > }
> > }
> >
> > +static int mount_entry_create_overlay_dirs(const struct mntent *mntent,
> > + const struct lxc_rootfs *rootfs)
> > +{
> > + char *del = NULL;
> > + char *lxcpath = NULL;
> > + char *upperdir = NULL;
> > + char *workdir = NULL;
> > + char **opts = NULL;
> > + size_t arrlen = 0;
> > + size_t dirlen = 0;
> > + size_t i;
> > + size_t len = 0;
> > + size_t rootfslen = 0;
> > +
> > + if (!rootfs->path)
> > + return -1;
> > +
> > + opts = lxc_string_split(mntent->mnt_opts, ',');
> > + if (opts)
> > + arrlen = lxc_array_len((void **)opts);
> > + else
> > + return -1;
> > +
> > + for (i = 0; i < arrlen; i++) {
> > + if (strstr(opts[i], "upperdir=") && (strlen(opts[i]) > (len = strlen("upperdir="))))
> > + upperdir = opts[i] + len;
> > + else if (strstr(opts[i], "workdir=") && (strlen(opts[i]) > (len = strlen("workdir="))))
> > + workdir = opts[i] + len;
> > + }
> > +
> > + lxcpath = strdup(rootfs->path);
> > + if (!lxcpath) {
> > + lxc_free_array((void **)opts, free);
> > + return -1;
> > + }
> > +
> > + del = strstr(lxcpath, "/rootfs");
> > + if (!del) {
> > + free(lxcpath);
> > + lxc_free_array((void **)opts, free);
> > + return -1;
> > + }
> > + *del = '\0';
> > +
> > + dirlen = strlen(lxcpath);
> > + rootfslen = strlen(rootfs->path);
> > +
> > + /* We neither allow users to create upperdirs and workdirs outside the
> > + * containerdir nor inside the rootfs. The latter might be debatable. */
> > + if (upperdir)
> > + if ((strncmp(upperdir, lxcpath, dirlen) == 0) && (strncmp(upperdir, rootfs->path, rootfslen) != 0))
> > + if (mkdir_p(upperdir, 0755) < 0) {
> > + WARN("Failed to create upperdir");
> > + }
> > +
> > +
> > + if (workdir)
> > + if ((strncmp(workdir, lxcpath, dirlen) == 0) && (strncmp(workdir, rootfs->path, rootfslen) != 0))
> > + if (mkdir_p(workdir, 0755) < 0) {
> > + WARN("Failed to create workdir");
> > + }
> > +
> > + free(lxcpath);
> > + lxc_free_array((void **)opts, free);
> > + return 0;
> > +}
> > +
> > +static int mount_entry_create_aufs_dirs(const struct mntent *mntent,
> > + const struct lxc_rootfs *rootfs)
> > +{
> > + char *del = NULL;
> > + char *lxcpath = NULL;
> > + char *scratch = NULL;
> > + char *tmp = NULL;
> > + char *upperdir = NULL;
> > + char **opts = NULL;
> > + size_t arrlen = 0;
> > + size_t i;
> > + size_t len = 0;
> > +
> > + if (!rootfs->path)
> > + return -1;
> > +
> > + opts = lxc_string_split(mntent->mnt_opts, ',');
> > + if (opts)
> > + arrlen = lxc_array_len((void **)opts);
> > + else
> > + return -1;
> > +
> > + for (i = 0; i < arrlen; i++) {
> > + if (strstr(opts[i], "br=") && (strlen(opts[i]) > (len = strlen("br="))))
> > + tmp = opts[i] + len;
> > + }
> > + if (!tmp) {
> > + lxc_free_array((void **)opts, free);
> > + return -1;
> > + }
> > +
> > + upperdir = strtok_r(tmp, ":=", &scratch);
> > + if (!upperdir) {
> > + lxc_free_array((void **)opts, free);
> > + return -1;
> > + }
> > +
> > + lxcpath = strdup(rootfs->path);
> > + if (!lxcpath) {
> > + lxc_free_array((void **)opts, free);
> > + return -1;
> > + }
> > +
> > + del = strstr(lxcpath, "/rootfs");
> > + if (!del) {
> > + free(lxcpath);
> > + lxc_free_array((void **)opts, free);
> > + return -1;
> > + }
> > + *del = '\0';
> > +
> > + /* We neither allow users to create upperdirs outside the containerdir
> > + * nor inside the rootfs. The latter might be debatable. */
> > + if ((strncmp(upperdir, lxcpath, strlen(lxcpath)) == 0) && (strncmp(upperdir, rootfs->path, strlen(rootfs->path)) != 0))
> > + if (mkdir_p(upperdir, 0755) < 0) {
> > + WARN("Failed to create upperdir");
> > + }
> > +
> > + free(lxcpath);
> > + lxc_free_array((void **)opts, free);
> > + return 0;
> > +}
> > +
> > static int mount_entry_create_dir_file(const struct mntent *mntent,
> > - const char* path)
> > + const char* path, const struct lxc_rootfs *rootfs)
> > {
> > char *pathdirname = NULL;
> > int ret = 0;
> > FILE *pathfile = NULL;
> >
> > + if (strncmp(mntent->mnt_type, "overlay", 7) == 0) {
> > + if (mount_entry_create_overlay_dirs(mntent, rootfs) < 0)
> > + return -1;
> > + } else if (strncmp(mntent->mnt_type, "aufs", 4) == 0) {
> > + if (mount_entry_create_aufs_dirs(mntent, rootfs) < 0)
> > + return -1;
> > + }
> > +
> > if (hasmntopt(mntent, "create=dir")) {
> > if (mkdir_p(path, 0755) < 0) {
> > WARN("Failed to create mount target '%s'", path);
> > @@ -1839,23 +1977,23 @@ static int mount_entry_create_dir_file(const struct mntent *mntent,
> > if (!pathfile) {
> > WARN("Failed to create mount target '%s'", path);
> > ret = -1;
> > - }
> > - else
> > + } else {
> > fclose(pathfile);
> > + }
> > }
> > free(pathdirname);
> > return ret;
> > }
> >
> > static inline int mount_entry_on_generic(struct mntent *mntent,
> > - const char* path, const char *rootfs)
> > + const char* path, const struct lxc_rootfs *rootfs)
> > {
> > unsigned long mntflags;
> > char *mntdata;
> > int ret;
> > bool optional = hasmntopt(mntent, "optional") != NULL;
> >
> > - ret = mount_entry_create_dir_file(mntent, path);
> > + ret = mount_entry_create_dir_file(mntent, path, rootfs);
> >
> > if (ret < 0)
> > return optional ? 0 : -1;
> > @@ -1867,11 +2005,11 @@ static inline int mount_entry_on_generic(struct mntent *mntent,
> > return -1;
> > }
> >
> > - ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
> > - mntflags, mntdata, optional, rootfs);
> > + ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type, mntflags,
> > + mntdata, optional,
> > + rootfs->path ? rootfs->mount : NULL);
> >
> > free(mntdata);
> > -
> > return ret;
> > }
> >
> > @@ -1924,17 +2062,17 @@ skipabs:
> > return -1;
> > }
> >
> > - return mount_entry_on_generic(mntent, path, rootfs->mount);
> > + return mount_entry_on_generic(mntent, path, rootfs);
> > }
> >
> > static int mount_entry_on_relative_rootfs(struct mntent *mntent,
> > - const char *rootfs)
> > + const struct lxc_rootfs *rootfs)
> > {
> > char path[MAXPATHLEN];
> > int ret;
> >
> > /* relative to root mount point */
> > - ret = snprintf(path, sizeof(path), "%s/%s", rootfs, mntent->mnt_dir);
> > + ret = snprintf(path, sizeof(path), "%s/%s", rootfs->mount, mntent->mnt_dir);
> > if (ret >= sizeof(path)) {
> > ERROR("path name too long");
> > return -1;
> > @@ -1961,7 +2099,7 @@ static int mount_file_entries(const struct lxc_rootfs *rootfs, FILE *file,
> > /* We have a separate root, mounts are relative to it */
> > if (mntent.mnt_dir[0] != '/') {
> > if (mount_entry_on_relative_rootfs(&mntent,
> > - rootfs->mount))
> > + rootfs))
> > goto out;
> > continue;
> > }
> > --
> > 2.6.1
> >
> _______________________________________________
> lxc-devel mailing list
> lxc-devel at lists.linuxcontainers.org
> http://lists.linuxcontainers.org/listinfo/lxc-devel
More information about the lxc-devel
mailing list