[CRIU] [PATCH 3/4] mount: handle mnt_flags and sb_flags separatly (v3)

Andrey Vagin avagin at openvz.org
Mon Sep 7 13:12: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
Signed-off-by: Andrey Vagin <avagin at openvz.org>
---
 include/mount.h    |  1 +
 mount.c            | 49 ++++++++++++++++++++++++++++++++++++++-----------
 proc_parse.c       |  2 +-
 protobuf/mnt.proto |  1 +
 4 files changed, 41 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 29d8405..fc32f20 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)
 {
@@ -1583,6 +1584,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;
@@ -1925,24 +1928,45 @@ skip_parent:
 
 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;
 
-	if (mount(src, mi->mountpoint, tp->name,
-			mi->flags & ~mflags, mi->options) < 0) {
+	/* Merge superblock and mount flags if it's posiable */
+	if ((mflags & ~(MS_NOSUID | MS_NOEXEC | MS_NODEV | MS_NOATIME |
+				MS_NODIRATIME | MS_RELATIME | MS_RDONLY)) &&
+	    ((sflags & mflags) ^ MS_RDONLY)) {
+		sflags |= mflags;
+		mflags = 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))
@@ -1950,12 +1974,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;
 }
 
@@ -1978,6 +1996,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) {
 			/*
@@ -2031,6 +2050,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)) {
@@ -2354,6 +2380,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 f305f59..fad6bae 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