[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