Commit 1174a2ad authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

mount: handle mnt_flags and sb_flags separatly (v4)

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: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent b7d393ff
...@@ -47,6 +47,7 @@ struct mount_info { ...@@ -47,6 +47,7 @@ struct mount_info {
char *mountpoint; char *mountpoint;
char *ns_mountpoint; char *ns_mountpoint;
unsigned flags; unsigned flags;
unsigned sb_flags;
int master_id; int master_id;
int shared_id; int shared_id;
struct fstype *fstype; struct fstype *fstype;
......
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include "protobuf/mnt.pb-c.h" #include "protobuf/mnt.pb-c.h"
#define AUTODETECTED_MOUNT "CRIU:AUTOGENERATED" #define AUTODETECTED_MOUNT "CRIU:AUTOGENERATED"
#define MS_PROPAGATE (MS_SHARED | MS_PRIVATE | MS_UNBINDABLE | MS_SLAVE)
#undef LOG_PREFIX #undef LOG_PREFIX
#define LOG_PREFIX "mnt: " #define LOG_PREFIX "mnt: "
...@@ -1596,6 +1597,8 @@ static int dump_one_mountpoint(struct mount_info *pm, struct cr_img *img) ...@@ -1596,6 +1597,8 @@ static int dump_one_mountpoint(struct mount_info *pm, struct cr_img *img)
me.root_dev = pm->s_dev; me.root_dev = pm->s_dev;
me.parent_mnt_id = pm->parent_mnt_id; me.parent_mnt_id = pm->parent_mnt_id;
me.flags = pm->flags; me.flags = pm->flags;
me.sb_flags = pm->sb_flags;
me.has_sb_flags = true;
me.mountpoint = pm->mountpoint + 1; me.mountpoint = pm->mountpoint + 1;
me.source = pm->source; me.source = pm->source;
me.options = pm->options; me.options = pm->options;
...@@ -1936,26 +1939,53 @@ skip_parent: ...@@ -1936,26 +1939,53 @@ skip_parent:
return 0; 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) 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; char *src;
struct fstype *tp = mi->fstype; 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); src = resolve_source(mi);
if (!src) if (!src)
return -1; return -1;
if (remount_ro) 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, if (mount(src, mi->mountpoint, tp->name, sflags, mi->options) < 0) {
mi->flags & ~mflags, mi->options) < 0) {
pr_perror("Can't mount at %s", mi->mountpoint); pr_perror("Can't mount at %s", mi->mountpoint);
return -1; 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, if (restore_shared_options(mi, !mi->shared_id && !mi->master_id,
mi->shared_id, mi->shared_id,
mi->master_id)) mi->master_id))
...@@ -1963,12 +1993,6 @@ static int do_new_mount(struct mount_info *mi) ...@@ -1963,12 +1993,6 @@ static int do_new_mount(struct mount_info *mi)
mi->mounted = true; 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; return 0;
} }
...@@ -1991,6 +2015,7 @@ static int do_bind_mount(struct mount_info *mi) ...@@ -1991,6 +2015,7 @@ static int do_bind_mount(struct mount_info *mi)
if (!mi->need_plugin) { if (!mi->need_plugin) {
char *root, *cut_root, rpath[PATH_MAX]; char *root, *cut_root, rpath[PATH_MAX];
unsigned long mflags;
if (mi->external) { if (mi->external) {
/* /*
...@@ -2044,6 +2069,13 @@ do_bind: ...@@ -2044,6 +2069,13 @@ do_bind:
return -1; 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 (unlikely(mi->deleted)) {
if (S_ISDIR(st.st_mode)) { if (S_ISDIR(st.st_mode)) {
if (rmdir(root)) { if (rmdir(root)) {
...@@ -2367,6 +2399,7 @@ static int collect_mnt_from_image(struct mount_info **pms, struct ns_id *nsid) ...@@ -2367,6 +2399,7 @@ static int collect_mnt_from_image(struct mount_info **pms, struct ns_id *nsid)
pm->parent_mnt_id = me->parent_mnt_id; pm->parent_mnt_id = me->parent_mnt_id;
pm->s_dev = me->root_dev; pm->s_dev = me->root_dev;
pm->flags = me->flags; pm->flags = me->flags;
pm->sb_flags = me->sb_flags;
pm->shared_id = me->shared_id; pm->shared_id = me->shared_id;
pm->master_id = me->master_id; pm->master_id = me->master_id;
pm->need_plugin = me->with_plugin; pm->need_plugin = me->with_plugin;
......
...@@ -1089,7 +1089,7 @@ static int parse_mountinfo_ent(char *str, struct mount_info *new, char **fsname) ...@@ -1089,7 +1089,7 @@ static int parse_mountinfo_ent(char *str, struct mount_info *new, char **fsname)
if (!new->options) if (!new->options)
goto err; goto err;
if (parse_sb_opt(opt, &new->flags, new->options)) if (parse_sb_opt(opt, &new->sb_flags, new->options))
goto err; goto err;
ret = 0; ret = 0;
......
...@@ -43,4 +43,5 @@ message mnt_entry { ...@@ -43,4 +43,5 @@ message mnt_entry {
optional bool internal_sharing = 15; optional bool internal_sharing = 15;
optional bool deleted = 16; optional bool deleted = 16;
optional uint32 sb_flags = 17 [(criu).hex = true];
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment