]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
conf.c: add relative option for lxc.mount.entry 2031/head
authorYifeng Tan <tanyifeng1@huawei.com>
Mon, 18 Dec 2017 16:50:58 +0000 (00:50 +0800)
committerYifeng Tan <tanyifeng1@huawei.com>
Mon, 18 Dec 2017 17:07:46 +0000 (01:07 +0800)
Signed-off-by: Yifeng Tan <tanyifeng1@huawei.com>
doc/lxc.container.conf.sgml.in
src/lxc/conf.c

index 4b97de611cfe4f46455b8b96020750fe27b24f1f..f777ac35fe19ab25e7cfa4485b130a268dd72c0a 100644 (file)
@@ -1066,6 +1066,17 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
               <option>optional</option> don't fail if mount does not work.
               <option>create=dir</option> or <option>create=file</option>
               to create dir (or file) when the point will be mounted.
+              <option>relative</option> source path is taken to be relative to
+              the mounted container root. For instance,
+             </para>
+<screen>
+dev/null proc/kcore none bind,relative 0 0
+</screen>
+             <para>
+              Will expand dev/null to ${<option>LXC_ROOTFS_MOUNT</option>}/dev/null,
+              and mount it to proc/kcore inside the container.
+             </para>
+             <para>
             </para>
           </listitem>
         </varlistentry>
index 93d4d09f59c0b4e48fcda007f411e0c07d727caf..fb02e3e78fe1176fdfd494c32366247a27720abb 100644 (file)
@@ -1814,24 +1814,35 @@ static char *get_field(char *src, int nfields)
 static int mount_entry(const char *fsname, const char *target,
                       const char *fstype, unsigned long mountflags,
                       const char *data, int optional, int dev,
-                      const char *rootfs)
+                      int relative, const char *rootfs)
 {
        int ret;
+       char srcbuf[MAXPATHLEN];
+       const char *srcpath = fsname;
 #ifdef HAVE_STATVFS
        struct statvfs sb;
 #endif
 
-       ret = safe_mount(fsname, target, fstype, mountflags & ~MS_REMOUNT, data,
+       if (relative) {
+               ret = snprintf(srcbuf, MAXPATHLEN, "%s/%s", rootfs ? rootfs : "/", fsname ? fsname : "");
+               if (ret < 0 || ret >= MAXPATHLEN) {
+                       ERROR("source path is too long");
+                       return -1;
+               }
+               srcpath = srcbuf;
+       }
+
+       ret = safe_mount(srcpath, target, fstype, mountflags & ~MS_REMOUNT, data,
                         rootfs);
        if (ret < 0) {
                if (optional) {
                        INFO("Failed to mount \"%s\" on \"%s\" (optional): %s",
-                            fsname ? fsname : "(null)", target, strerror(errno));
+                            srcpath ? srcpath : "(null)", target, strerror(errno));
                        return 0;
                }
 
                SYSERROR("Failed to mount \"%s\" on \"%s\"",
-                        fsname ? fsname : "(null)", target);
+                        srcpath ? srcpath : "(null)", target);
                return -1;
        }
 
@@ -1839,12 +1850,12 @@ static int mount_entry(const char *fsname, const char *target,
                unsigned long rqd_flags = 0;
 
                DEBUG("Remounting \"%s\" on \"%s\" to respect bind or remount "
-                     "options", fsname ? fsname : "(none)", target ? target : "(none)");
+                     "options", srcpath ? srcpath : "(none)", target ? target : "(none)");
 
                if (mountflags & MS_RDONLY)
                        rqd_flags |= MS_RDONLY;
 #ifdef HAVE_STATVFS
-               if (fsname && statvfs(fsname, &sb) == 0) {
+               if (srcpath && statvfs(srcpath, &sb) == 0) {
                        unsigned long required_flags = rqd_flags;
 
                        if (sb.f_flag & MS_NOSUID)
@@ -1860,7 +1871,7 @@ static int mount_entry(const char *fsname, const char *target,
                                required_flags |= MS_NOEXEC;
 
                        DEBUG("Flags for \"%s\" were %lu, required extra flags "
-                             "are %lu", fsname, sb.f_flag, required_flags);
+                             "are %lu", srcpath, sb.f_flag, required_flags);
 
                        /* If this was a bind mount request, and required_flags
                         * does not have any flags which are not already in
@@ -1879,18 +1890,18 @@ static int mount_entry(const char *fsname, const char *target,
                }
 #endif
 
-               ret = mount(fsname, target, fstype, mountflags | MS_REMOUNT, data);
+               ret = mount(srcpath, target, fstype, mountflags | MS_REMOUNT, data);
                if (ret < 0) {
                        if (optional) {
                                INFO("Failed to mount \"%s\" on \"%s\" "
                                     "(optional): %s",
-                                    fsname ? fsname : "(null)", target,
+                                    srcpath ? srcpath : "(null)", target,
                                     strerror(errno));
                                return 0;
                        }
 
                        SYSERROR("Failed to mount \"%s\" on \"%s\"",
-                                fsname ? fsname : "(null)", target);
+                                srcpath ? srcpath : "(null)", target);
                        return -1;
                }
        }
@@ -1899,7 +1910,7 @@ static int mount_entry(const char *fsname, const char *target,
 skipremount:
 #endif
        DEBUG("Mounted \"%s\" on \"%s\" with filesystem type \"%s\"",
-             fsname ? fsname : "(null)", target, fstype);
+             srcpath ? srcpath : "(null)", target, fstype);
 
        return 0;
 }
@@ -1908,7 +1919,7 @@ skipremount:
 static void cull_mntent_opt(struct mntent *mntent)
 {
        int i;
-       char *list[] = {"create=dir", "create=file", "optional", NULL};
+       char *list[] = {"create=dir", "create=file", "optional", "relative", NULL};
 
        for (i = 0; list[i]; i++) {
                char *p, *p2;
@@ -1988,11 +1999,12 @@ static inline int mount_entry_on_generic(struct mntent *mntent,
        int ret;
        unsigned long mntflags;
        char *mntdata;
-       bool dev, optional;
+       bool dev, optional, relative;
        char *rootfs_path = NULL;
 
        optional = hasmntopt(mntent, "optional") != NULL;
        dev = hasmntopt(mntent, "dev") != NULL;
+       relative = hasmntopt(mntent, "relative") != NULL;
 
        if (rootfs && rootfs->path)
                rootfs_path = rootfs->mount;
@@ -2012,7 +2024,7 @@ 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, dev, rootfs_path);
+                         mntdata, optional, dev, relative, rootfs_path);
 
        free(mntdata);
        return ret;
@@ -3240,11 +3252,6 @@ int lxc_setup(struct lxc_handler *handler)
                return -1;
        }
 
-       if (!lxc_list_empty(&lxc_conf->mount_list) && setup_mount_entries(lxc_conf, &lxc_conf->rootfs, &lxc_conf->mount_list, name, lxcpath)) {
-               ERROR("failed to setup the mount entries for '%s'", name);
-               return -1;
-       }
-
        /* Make sure any start hooks are in the container */
        if (!verify_start_hooks(lxc_conf))
                return -1;
@@ -3278,6 +3285,11 @@ int lxc_setup(struct lxc_handler *handler)
                }
        }
 
+       if (!lxc_list_empty(&lxc_conf->mount_list) && setup_mount_entries(lxc_conf, &lxc_conf->rootfs, &lxc_conf->mount_list, name, lxcpath)) {
+               ERROR("failed to setup the mount entries for '%s'", name);
+               return -1;
+       }
+
        ret = lxc_setup_console(&lxc_conf->rootfs, &lxc_conf->console,
                                lxc_conf->ttydir);
        if (ret < 0) {