[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