From: Daniel Lezcano Date: Thu, 13 Jan 2011 15:25:14 +0000 (+0100) Subject: encapsulate mount point code X-Git-Tag: lxc-0.7.4-rc1~18 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=911324ef257216f6f80796313d949117863d46c3;p=thirdparty%2Flxc.git encapsulate mount point code 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 --- diff --git a/src/lxc/conf.c b/src/lxc/conf.c index b07375f72..345facda6 100644 --- a/src/lxc/conf.c +++ b/src/lxc/conf.c @@ -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;