]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
encapsulate mount point code
authorDaniel Lezcano <daniel.lezcano@free.fr>
Thu, 13 Jan 2011 15:25:14 +0000 (16:25 +0100)
committerDaniel Lezcano <dlezcano@fr.ibm.com>
Thu, 13 Jan 2011 15:25:14 +0000 (16:25 +0100)
Change the code to encapsulate the different mounts point.

 * mount on the host fs
 * mount relatively to the rootfs
 * mount absolutely to the rootfs (broken)

That will make the code cleaner to fix the latter.

Signed-off-by: Daniel Lezcano <dlezcano@fr.ibm.com>
src/lxc/conf.c

index b07375f72d3724be81a6e122166f173a710b8eb1..345facda64d0fc28d98cfeaba4750bc3ac04a321 100644 (file)
@@ -874,16 +874,18 @@ static void parse_mntopt(char *opt, unsigned long *flags, char **data)
        strcat(*data, opt);
 }
 
-static int parse_mntopts(struct mntent *mntent, unsigned long *mntflags,
+static int parse_mntopts(const char *mntopts, unsigned long *mntflags,
                         char **mntdata)
 {
        char *s, *data;
        char *p, *saveptr = NULL;
 
-       if (!mntent->mnt_opts)
+       *mntdata = NULL;
+
+       if (!mntopts)
                return 0;
 
-       s = strdup(mntent->mnt_opts);
+       s = strdup(mntopts);
        if (!s) {
                SYSERROR("failed to allocate memory");
                return -1;
@@ -910,83 +912,126 @@ static int parse_mntopts(struct mntent *mntent, unsigned long *mntflags,
        return 0;
 }
 
-static int mount_file_entries(const struct lxc_rootfs *rootfs, FILE *file)
+static int mount_entry(const char *fsname, const char *target,
+                      const char *fstype, unsigned long mountflags,
+                      const char *data)
+{
+       if (mount(fsname, target, fstype, mountflags & ~MS_REMOUNT, data)) {
+               SYSERROR("failed to mount '%s' on '%s'", fsname, target);
+               return -1;
+       }
+
+       if ((mountflags & MS_REMOUNT) || (mountflags & MS_BIND)) {
+
+               DEBUG("remounting %s on %s to respect bind or remount options",
+                     fsname, target);
+
+               if (mount(fsname, target, fstype,
+                         mountflags | MS_REMOUNT, data)) {
+                       SYSERROR("failed to mount '%s' on '%s'",
+                                fsname, target);
+                       return -1;
+               }
+       }
+
+       DEBUG("mounted '%s' on '%s', type '%s'", fsname, target, fstype);
+
+       return 0;
+}
+
+static inline int mount_entry_on_systemfs(struct mntent *mntent)
 {
-       struct mntent *mntent;
-       int ret = -1;
        unsigned long mntflags;
        char *mntdata;
+       int ret;
+
+       if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
+               ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
+               return -1;
+       }
+
+       ret = mount_entry(mntent->mnt_fsname, mntent->mnt_dir,
+                         mntent->mnt_type, mntflags, mntdata);
+
+       free(mntdata);
+
+       return ret;
+}
+
+static int mount_entry_on_absolute_rootfs(struct mntent *mntent,
+                                         const char *rootfs)
+{
        char path[MAXPATHLEN];
-       const char *mntdir, *mntroot;
+       unsigned long mntflags;
+       char *mntdata;
+       int ret;
 
-       while ((mntent = getmntent(file))) {
+       if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
+               ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
+               return -1;
+       }
 
-               mntflags = 0;
-               mntdata = NULL;
+       if (strncmp(mntent->mnt_dir, rootfs, strlen(rootfs)))
+               WARN("mount target directory '%s' is outside "
+                    "container root", mntent->mnt_dir);
+       else
+               WARN("mount target directory '%s' is not "
+                    "relative to container root", mntent->mnt_dir);
 
-               if (parse_mntopts(mntent, &mntflags, &mntdata) < 0) {
-                       ERROR("failed to parse mount option '%s'",
-                             mntent->mnt_opts);
-                       goto out;
-               }
+       ret = mount_entry(mntent->mnt_fsname, mntent->mnt_dir, mntent->mnt_type,
+                         mntflags, mntdata);
 
-               /* now figure out where to mount it to. */
-               mntdir =  mntent->mnt_dir;
-               mntroot = NULL;
+       free(mntdata);
+       return ret;
+}
 
-               if (!rootfs->path) {
-                       /* if we use system root fs, the mount is relative to '/'
-                        * and can be absolute */
-                       if (mntdir[0] != '/')
-                               mntroot = ""; /* this is '/' */
-               } else {
-                       /* else we have a separate root, mounts are
-                        * relative to it, and absolute paths are risky */
-                       if (mntdir[0] != '/')
-                               /* relative to root mount point */
-                               mntroot = rootfs->mount;
-                       else if (strncmp(mntdir, rootfs->mount,
-                                        strlen(rootfs->mount)))
-                               WARN("mount target directory '%s' is outside "
-                                    "container root", mntdir);
-                       else
-                               WARN("mount target directory '%s' is not "
-                                    "relative to container root", mntdir);
-               }
+static int mount_entry_on_relative_rootfs(struct mntent *mntent,
+                                         const char *rootfs)
+{
+       char path[MAXPATHLEN];
+       unsigned long mntflags;
+       char *mntdata;
+       int ret;
 
-               if (mntroot) {
-                       /* make it relative to mntroot */
-                       snprintf(path, sizeof(path), "%s/%s", mntroot, mntdir);
-                       mntdir = path;
-               }
+       if (parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata) < 0) {
+               ERROR("failed to parse mount option '%s'", mntent->mnt_opts);
+               return -1;
+       }
 
-               if (mount(mntent->mnt_fsname, mntdir,
-                         mntent->mnt_type, mntflags & ~MS_REMOUNT, mntdata)) {
-                       SYSERROR("failed to mount '%s' on '%s'",
-                                        mntent->mnt_fsname, mntent->mnt_dir);
-                       goto out;
-               }
+        /* relative to root mount point */
+       snprintf(path, sizeof(path), "%s/%s", rootfs, mntent->mnt_dir);
+
+       ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type,
+                         mntflags, mntdata);
+
+       free(mntdata);
 
-               if ((mntflags & MS_REMOUNT) == MS_REMOUNT ||
-                   ((mntflags & MS_BIND) == MS_BIND)) {
+       return ret;
+}
+
+static int mount_file_entries(const struct lxc_rootfs *rootfs, FILE *file)
+{
+       struct mntent *mntent;
+       int ret = -1;
 
-                       DEBUG ("remounting %s on %s to respect bind " \
-                              "or remount options",
-                              mntent->mnt_fsname, mntent->mnt_dir);
+       while ((mntent = getmntent(file))) {
 
-                       if (mount(mntent->mnt_fsname, mntent->mnt_dir,
-                                 mntent->mnt_type,
-                                 mntflags | MS_REMOUNT, mntdata)) {
-                               SYSERROR("failed to mount '%s' on '%s'",
-                                        mntent->mnt_fsname, mntent->mnt_dir);
+               if (!rootfs->path) {
+                       if (mount_entry_on_systemfs(mntent))
                                goto out;
-                       }
+                       continue;
                }
 
-               DEBUG("mounted %s on %s, type %s", mntent->mnt_fsname,
-                     mntent->mnt_dir, mntent->mnt_type);
+               /* We have a separate root, mounts are relative to it */
+               if (mntent->mnt_dir[0] != '/') {
+                       if (mount_entry_on_relative_rootfs(mntent,
+                                                          rootfs->mount))
+                               goto out;
+                       continue;
+               }
 
-               free(mntdata);
+               if (mount_entry_on_absolute_rootfs(mntent, rootfs->path))
+                       goto out;
        }
 
        ret = 0;