[lxc-devel] [PATCH] Add support for various mount options

Ryousei Takano takano-ryousei at aist.go.jp
Mon Apr 6 05:23:34 UTC 2009


This patch adds support for various mount options.  It is also able to pass extra 
mount option data to mount(2).  For example, it allows users to mount aufs file 
system at lxc_start time.

See the thread
	http://sourceforge.net/mailarchive/forum.php?thread_name=E6D98D6C-F633-419A-9424-F24EBB3E11D9%40aist.go.jp&forum_name=lxc-devel
for details.

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

diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 6c3476a..619d638 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -69,6 +69,12 @@ struct netdev_conf {
 	int count;
 };
 
+struct mount_opt {
+	char *name;
+	int clear;
+	int flag;
+};
+
 static int instanciate_veth(const char *, const char *, pid_t);
 static int instanciate_macvlan(const char *, const char *, pid_t);
 static int instanciate_phys(const char *, const char *, pid_t);
@@ -82,6 +88,30 @@ static struct netdev_conf netdev_conf[MAXCONFTYPE + 1] = {
 	[EMPTY]   = { "empty",   instanciate_empty,   0, },
 };
 
+static struct mount_opt mount_opt[] = {
+	{ "defaults",   0, 0              },
+	{ "ro",         0, MS_RDONLY      },
+	{ "rw",         1, MS_RDONLY      },
+	{ "suid",       1, MS_NOSUID      },
+	{ "nosuid",     0, MS_NOSUID      },
+	{ "dev",        1, MS_NODEV       },
+	{ "nodev",      0, MS_NODEV       },
+	{ "exec",       1, MS_NOEXEC      },
+	{ "noexec",     0, MS_NOEXEC      },
+	{ "sync",       0, MS_SYNCHRONOUS },
+	{ "async",      1, MS_SYNCHRONOUS },
+	{ "remount",    0, MS_REMOUNT     },
+	{ "mand",       0, MS_MANDLOCK    },
+	{ "nomand",     1, MS_MANDLOCK    },
+	{ "atime",      1, MS_NOATIME     },
+	{ "noatime",    0, MS_NOATIME     },
+	{ "diratime",   1, MS_NODIRATIME  },
+	{ "nodiratime", 0, MS_NODIRATIME  },
+	{ "bind",       0, MS_BIND        },
+	{ "rbind",      0, MS_BIND|MS_REC },
+	{ NULL,         0, 0              },
+};
+
 static int write_info(const char *path, const char *file, const char *info)
 {
 	int fd, err = -1;
@@ -1026,13 +1056,72 @@ static int setup_cgroup(const char *name)
 				      line, MAXPATHLEN, (void *)name);
 }
 
+static void parse_mntopt(char *opt, unsigned long *flags, char **data)
+{
+	struct mount_opt *mo;
+
+	/* If opt is found in mount_opt, set or clear flags.
+	 * Otherwise append it to data. */
+
+	for (mo = &mount_opt[0]; mo->name != NULL; mo++) {
+		if (!strncmp(opt, mo->name, strlen(mo->name))) {
+			if (mo->clear)
+				*flags &= ~mo->flag;
+			else
+				*flags |= mo->flag;
+			return;
+		}
+	}
+
+	if (strlen(*data))
+		strcat(*data, ",");
+	strcat(*data, opt);
+}
+
+static int parse_mntopts(struct mntent *mntent, unsigned long *mntflags,
+			 char **mntdata)
+{
+	char *s, *data;
+	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;
+	}
+
+	data = malloc(strlen(s) + 1);
+	if (!data) {
+		lxc_log_syserror("failed to allocate memory");
+		free(s);
+		return -1;
+	}
+	*data = 0;
+
+	for (p = strtok_r(s, ",", &saveptr); p != NULL;
+	     p = strtok_r(NULL, ",", &saveptr))
+		parse_mntopt(p, mntflags, &data);
+
+	if (*data)
+		*mntdata = data;
+	else
+		free(data);
+	free(s);
+
+	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 *mntdata;
 
 	snprintf(path, MAXPATHLEN, LXCPATH "/%s/fstab", name);
 
@@ -1044,23 +1133,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;
+		mntdata = NULL;
+		if (parse_mntopts(mntent, &mntflags, &mntdata) < 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, mntdata)) {
 			lxc_log_syserror("failed to mount '%s' on '%s'",
 					 mntent->mnt_fsname, mntent->mnt_dir);
 			goto out;
 		}
+
+		free(mntdata);
 	}
 	ret = 0;
 out:
-- 
1.5.6.3





More information about the lxc-devel mailing list