[CRIU] [PATCH] mount: handle mnt_flags and sb_flags separatly (v4)

Andrey Vagin avagin at openvz.org
Fri Sep 11 06:55:55 PDT 2015


They both can container the MS_READONLY flag. And in one case it will be
read-only bind-mount and in another case it will be read-only
super-block.

v2: set mnt and sb for one call of mount() when it's posiable
v3: return a comment which was deleted by mistake
v4: Fix the sentense about restoring mnt flags
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 include/mount.h    |  1 +
 mount.c            | 55 +++++++++++++++++++++++++++++++++++++++++++-----------
 proc_parse.c       |  2 +-
 protobuf/mnt.proto |  1 +
 4 files changed, 47 insertions(+), 12 deletions(-)

diff --git a/include/mount.h b/include/mount.h
index d0a28d8..76a8e24 100644
--- a/include/mount.h
+++ b/include/mount.h
@@ -47,6 +47,7 @@ struct mount_info {
 	char			*mountpoint;
 	char			*ns_mountpoint;
 	unsigned		flags;
+	unsigned		sb_flags;
 	int			master_id;
 	int			shared_id;
 	struct fstype		*fstype;
diff --git a/mount.c b/mount.c
index 36b4278..ae98eb1 100644
--- a/mount.c
+++ b/mount.c
@@ -31,6 +31,7 @@
 #include "protobuf/mnt.pb-c.h"
 
 #define AUTODETECTED_MOUNT "CRIU:AUTOGENERATED"
+#define MS_PROPAGATE (MS_SHARED | MS_PRIVATE | MS_UNBINDABLE | MS_SLAVE)
 
 int ext_mount_add(char *key, char *val)
 {
@@ -1593,6 +1594,8 @@ static int dump_one_mountpoint(struct mount_info *pm, struct cr_img *img)
 	me.root_dev		= pm->s_dev;
 	me.parent_mnt_id	= pm->parent_mnt_id;
 	me.flags		= pm->flags;
+	me.sb_flags		= pm->sb_flags;
+	me.has_sb_flags		= true;
 	me.mountpoint		= pm->mountpoint + 1;
 	me.source		= pm->source;
 	me.options		= pm->options;
@@ -1933,26 +1936,53 @@ skip_parent:
 	return 0;
 }
 
+/*
+ * Here are a set of flags which we know how to handle for the one mount call.
+ * All of them except MS_RDONLY are set only as mnt flags.
+ * MS_RDONLY is set for both mnt ans sb flags, so we can restore it for one
+ * mount call only if it set for both masks.
+ */
+#define MS_MNT_KNOWN_FLAGS (MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_NOATIME | \
+				MS_NODIRATIME | MS_RELATIME | MS_RDONLY)
 static int do_new_mount(struct mount_info *mi)
 {
-	unsigned long mflags = MS_SHARED | MS_PRIVATE | MS_SLAVE | MS_UNBINDABLE;
+	unsigned long sflags = mi->sb_flags;
+	unsigned long mflags = mi->flags & (~MS_PROPAGATE);
 	char *src;
 	struct fstype *tp = mi->fstype;
-	bool remount_ro = (tp->restore && mi->flags & MS_RDONLY);
+	bool remount_ro = (tp->restore && mi->sb_flags & MS_RDONLY);
 
 	src = resolve_source(mi);
 	if (!src)
 		return -1;
 
 	if (remount_ro)
-		mflags |= MS_RDONLY;
+		sflags &= ~MS_RDONLY;
+
+	/* Merge superblock and mount flags if it's posiable */
+	if (!(mflags & ~MS_MNT_KNOWN_FLAGS) && ((sflags ^ mflags) & MS_RDONLY)) {
+		sflags |= mflags;
+		mflags = 0;
+	}
 
-	if (mount(src, mi->mountpoint, tp->name,
-			mi->flags & ~mflags, mi->options) < 0) {
+	if (mount(src, mi->mountpoint, tp->name, sflags, mi->options) < 0) {
 		pr_perror("Can't mount at %s", mi->mountpoint);
 		return -1;
 	}
 
+	if (tp->restore && tp->restore(mi))
+		return -1;
+
+	if (remount_ro)
+		return mount(NULL, mi->mountpoint, tp->name,
+			     MS_REMOUNT | MS_RDONLY, NULL);
+
+	if (mflags && mount(NULL, mi->mountpoint, NULL,
+				MS_REMOUNT | MS_BIND | mflags, NULL)) {
+		pr_perror("Unable to apply bind-mount options\n");
+		return -1;
+	}
+
 	if (restore_shared_options(mi, !mi->shared_id && !mi->master_id,
 					mi->shared_id,
 					mi->master_id))
@@ -1960,12 +1990,6 @@ static int do_new_mount(struct mount_info *mi)
 
 	mi->mounted = true;
 
-	if (tp->restore && tp->restore(mi))
-		return -1;
-
-	if (remount_ro)
-		return mount(NULL, mi->mountpoint, tp->name,
-			     MS_REMOUNT | MS_RDONLY, NULL);
 	return 0;
 }
 
@@ -1988,6 +2012,7 @@ static int do_bind_mount(struct mount_info *mi)
 
 	if (!mi->need_plugin) {
 		char *root, *cut_root, rpath[PATH_MAX];
+		unsigned long mflags;
 
 		if (mi->external) {
 			/*
@@ -2041,6 +2066,13 @@ do_bind:
 			return -1;
 		}
 
+		mflags = mi->flags & (~MS_PROPAGATE);
+		if (!mi->bind || mflags != (mi->bind->flags & (~MS_PROPAGATE)))
+			if (mount(NULL, mi->mountpoint, NULL, MS_BIND | MS_REMOUNT | mflags, NULL)) {
+				pr_perror("Can't mount at %s", mi->mountpoint);
+				return -1;
+			}
+
 		if (unlikely(mi->deleted)) {
 			if (S_ISDIR(st.st_mode)) {
 				if (rmdir(root)) {
@@ -2364,6 +2396,7 @@ static int collect_mnt_from_image(struct mount_info **pms, struct ns_id *nsid)
 		pm->parent_mnt_id	= me->parent_mnt_id;
 		pm->s_dev		= me->root_dev;
 		pm->flags		= me->flags;
+		pm->sb_flags		= me->sb_flags;
 		pm->shared_id		= me->shared_id;
 		pm->master_id		= me->master_id;
 		pm->need_plugin		= me->with_plugin;
diff --git a/proc_parse.c b/proc_parse.c
index 3feaa44..82ce102 100644
--- a/proc_parse.c
+++ b/proc_parse.c
@@ -1089,7 +1089,7 @@ static int parse_mountinfo_ent(char *str, struct mount_info *new, char **fsname)
 	if (!new->options)
 		goto err;
 
-	if (parse_sb_opt(opt, &new->flags, new->options))
+	if (parse_sb_opt(opt, &new->sb_flags, new->options))
 		goto err;
 
 	ret = 0;
diff --git a/protobuf/mnt.proto b/protobuf/mnt.proto
index f79ae46..12582e9 100644
--- a/protobuf/mnt.proto
+++ b/protobuf/mnt.proto
@@ -43,4 +43,5 @@ message mnt_entry {
 	optional bool		internal_sharing	= 15;
 
 	optional bool		deleted			= 16;
+	optional uint32		sb_flags		= 17 [(criu).hex = true];
 }
-- 
2.4.3



More information about the CRIU mailing list