[lxc-devel] [lxc/master] conf.c: support mount propagation for lxc.mount.entry

tanyifeng on Github lxc-bot at linuxcontainers.org
Mon Feb 12 03:41:12 UTC 2018


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 350 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20180212/42a26a7e/attachment.bin>
-------------- next part --------------
From f16b1ab35f9f6aeb10d37ef46b95eff9afac44e2 Mon Sep 17 00:00:00 2001
From: Yifeng Tan <tanyifeng1 at huawei.com>
Date: Mon, 12 Feb 2018 20:01:32 +0800
Subject: [PATCH] conf.c: support mount propagation for lxc.mount.entry

Signed-off-by: Yifeng Tan <tanyifeng1 at huawei.com>
---
 doc/lxc.container.conf.sgml.in |  3 +-
 src/lxc/conf.c                 | 79 +++++++++++++++++++++++++++++++++++++++---
 2 files changed, 77 insertions(+), 5 deletions(-)

diff --git a/doc/lxc.container.conf.sgml.in b/doc/lxc.container.conf.sgml.in
index ccc6348c4..c76d71ebf 100644
--- a/doc/lxc.container.conf.sgml.in
+++ b/doc/lxc.container.conf.sgml.in
@@ -1062,7 +1062,8 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
               specify a mount point corresponding to a line in the
               fstab format.
 
-              Moreover lxc add two options to mount.
+              Moreover lxc add three options to mount, and support mount
+              propagations, such as rslave or rprivate.
               <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.
diff --git a/src/lxc/conf.c b/src/lxc/conf.c
index 05b17a499..a4863cce2 100644
--- a/src/lxc/conf.c
+++ b/src/lxc/conf.c
@@ -193,6 +193,18 @@ static struct mount_opt mount_opt[] = {
 	{ NULL,            0, 0              },
 };
 
+static struct mount_opt propagation_opt[] = {
+	{ "private",       0, MS_PRIVATE           },
+	{ "shared",        0, MS_SHARED            },
+	{ "slave",         0, MS_SLAVE             },
+	{ "unbindable",    0, MS_UNBINDABLE        },
+	{ "rprivate",      0, MS_PRIVATE|MS_REC    },
+	{ "rshared",       0, MS_SHARED|MS_REC     },
+	{ "rslave",        0, MS_SLAVE|MS_REC      },
+	{ "runbindable",   0, MS_UNBINDABLE|MS_REC },
+	{ NULL,            0, 0                    },
+};
+
 #if HAVE_LIBCAP
 static struct caps_opt caps_opt[] = {
 	{ "chown",             CAP_CHOWN             },
@@ -1773,6 +1785,46 @@ int parse_mntopts(const char *mntopts, unsigned long *mntflags,
 	return 0;
 }
 
+static void parse_propagationopt(char *opt, unsigned long *flags)
+{
+	struct mount_opt *mo;
+
+	/* If opt is found in propagation_opt, set or clear flags. */
+
+	for (mo = &propagation_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;
+		}
+	}
+}
+
+static int parse_propagationopts(const char *mntopts, unsigned long *pflags)
+{
+	char *s;
+	char *p, *saveptr = NULL;
+	*pflags = 0L;
+
+	if (!mntopts)
+		return 0;
+
+	s = strdup(mntopts);
+	if (!s) {
+		SYSERROR("failed to allocate memory");
+		return -1;
+	}
+
+	for (p = strtok_r(s, ",", &saveptr); p != NULL;
+		p = strtok_r(NULL, ",", &saveptr))
+		parse_propagationopt(p, pflags);;
+
+	free(s);
+	return 0;
+}
+
 static void null_endofword(char *word)
 {
 	while (*word && *word != ' ' && *word != '\t')
@@ -1800,8 +1852,8 @@ 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, bool optional, bool dev,
-		       bool relative, const char *rootfs)
+		       unsigned long pflags, const char *data, bool optional,
+		       bool dev, bool relative, const char *rootfs)
 {
 	int ret;
 	char srcbuf[MAXPATHLEN];
@@ -1893,6 +1945,22 @@ static int mount_entry(const char *fsname, const char *target,
 		}
 	}
 
+	if (pflags) {
+		DEBUG("mounting propagation on %s", target);
+		if (mount("", target, "", pflags, "") < 0) {
+			if (optional) {
+				INFO("failed to mount propagation on '%s' (optional): %s",
+					target, strerror(errno));
+				return 0;
+			} else {
+				SYSERROR("failed to mount propagation on '%s'",
+					target);
+				return -1;
+			}
+		}
+	}
+
+
 #ifdef HAVE_STATVFS
 skipremount:
 #endif
@@ -1984,7 +2052,7 @@ static inline int mount_entry_on_generic(struct mntent *mntent,
 					 const char *lxc_path)
 {
 	int ret;
-	unsigned long mntflags;
+	unsigned long mntflags, pflags;
 	char *mntdata;
 	bool dev, optional, relative;
 	char *rootfs_path = NULL;
@@ -2007,11 +2075,14 @@ static inline int mount_entry_on_generic(struct mntent *mntent,
 	cull_mntent_opt(mntent);
 
 	ret = parse_mntopts(mntent->mnt_opts, &mntflags, &mntdata);
+	if (ret < 0)
+		return -1;
+	ret = parse_propagationopts(mntent->mnt_opts, &pflags);
 	if (ret < 0)
 		return -1;
 
 	ret = mount_entry(mntent->mnt_fsname, path, mntent->mnt_type, mntflags,
-			  mntdata, optional, dev, relative, rootfs_path);
+			  pflags, mntdata, optional, dev, relative, rootfs_path);
 
 	free(mntdata);
 	return ret;


More information about the lxc-devel mailing list