[lxc-devel] [RFC] Fix for parsing various mount options

Ryousei Takano takano-ryousei at aist.go.jp
Fri Apr 3 03:25:38 UTC 2009


Hi Daniel and all,

I am trying a fast container cloning using aufs (advanced multi layered
unification filesystem). That means a container rootfs is overlaid on top of 
the template rootfs in a copy-on-write manner.

lxc-start setups the rootfs according to $LXCPATH/test/fstab:

	none /opt/lxc.root/rootfs.test aufs br=/opt/lxc.root/cowfs.test:/opt/lxc.root/rootfs.debian.tmpl=ro 0 0

	/opt/lxc.root/rootfs.test /usr/local/var/lib/lxc/test/rootfs none rbind 0 0

To do that, we need to pass the aufs specific mount option to mount(2).
But setup_mount() ignores this option.

This patch fixes setup_mount() for parsing these kind of options.  
As far as I know hasmntopt(3) cannot parse non literal options, so it adds
a new function called parse_mntopts() instead of using hasmntopt(3).

Any comments and suggestions will be appreciated.

Signed-off-by: Ryousei Takano <takano-ryousei at aist.go.jp>
---
 src/lxc/conf.c |   93 ++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 81 insertions(+), 12 deletions(-)

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 6c3476a..5da9660 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -1026,13 +1026,82 @@ static int setup_cgroup(const char *name)
 				      line, MAXPATHLEN, (void *)name);
 }
 
+static int parse_mntopts(struct mntent *mntent, unsigned long *mntflags,
+			 char **mntopts)
+{
+#if 1
+	char *s, *opts;
+	char *p, *saveptr = NULL;
+
+	if (!mntent->mnt_opts)
+		return 0;
+
+	s = strdup(mntent->mnt_opts);
+	if (!s) {
+		lxc_log_syserror("failed to allocate memory");
+		return -1;
+	}
+
+	opts = malloc(strlen(s) + 1);
+	if (!opts) {
+		lxc_log_syserror("failed to allocate memory");
+		free(s);
+		return -1;
+	}
+	*opts = 0;
+
+	for (p = strtok_r(s, ",", &saveptr); p != NULL;
+	     p = strtok_r(NULL, ",", &saveptr)) {
+		if (!strncmp(p, "bind", strlen("bind"))) {
+			*mntflags |= MS_BIND;
+			continue;
+		}
+		if (!strncmp(p, "rbind", strlen("rbind"))) {
+			*mntflags |= MS_BIND|MS_REC;
+			continue;
+		}
+		if (!strncmp(p, "ro", strlen("ro"))) {
+			*mntflags |= MS_RDONLY;
+			continue;
+		}
+		if (!strncmp(p, "noexec", strlen("noexec"))) {
+			*mntflags |= MS_NOEXEC;
+			continue;
+		}
+		
+		if (*opts == 0)
+			strcat(opts, p);
+		else {
+			strcat(opts, ",");
+			strcat(opts, p);
+		}
+	}
+
+	if (*opts)
+		*mntopts = opts;
+	free(s);
+#else
+	if (hasmntopt(mntent, "bind"))
+		*mntflags |= MS_BIND;
+	if (hasmntopt(mntent, "rbind"))
+		*mntflags |= MS_BIND|MS_REC;
+	if (hasmntopt(mntent, "ro"))
+		*mntflags |= MS_RDONLY;
+	if (hasmntopt(mntent, "noexec"))
+		*mntflags |= MS_NOEXEC;
+#endif
+
+	return 0;
+}
+
 static int setup_mount(const char *name)
 {
 	char path[MAXPATHLEN];
 	struct mntent *mntent;
 	FILE *file;
 	int ret = -1;
-	unsigned long mntflags = 0;
+	unsigned long mntflags;
+	char *mntopts;
 
 	snprintf(path, MAXPATHLEN, LXCPATH "/%s/fstab", name);
 
@@ -1044,23 +1113,23 @@ static int setup_mount(const char *name)
 		goto out;
 	}
 
-	while((mntent = getmntent(file))) {
-
-		if (hasmntopt(mntent, "bind"))
-			mntflags |= MS_BIND;
-		if (hasmntopt(mntent, "rbind"))
-			mntflags |= MS_BIND|MS_REC;
-		if (hasmntopt(mntent, "ro"))
-			mntflags |= MS_RDONLY;
-		if (hasmntopt(mntent, "noexec"))
-			mntflags |= MS_NOEXEC;
+	while ((mntent = getmntent(file))) {
+		mntflags = 0;
+		mntopts = NULL;
+		if (parse_mntopts(mntent, &mntflags, &mntopts) < 0) {
+			lxc_log_error("failed to parse mount option '%s'",
+				      mntent->mnt_opts);
+			goto out;
+		}
 
 		if (mount(mntent->mnt_fsname, mntent->mnt_dir,
-			  mntent->mnt_type, mntflags, NULL)) {
+			  mntent->mnt_type, mntflags, mntopts)) {
 			lxc_log_syserror("failed to mount '%s' on '%s'",
 					 mntent->mnt_fsname, mntent->mnt_dir);
 			goto out;
 		}
+
+		free(mntopts);
 	}
 	ret = 0;
 out:
-- 
1.5.6.3






More information about the lxc-devel mailing list