Commit 6949a848 authored by Andrey Vagin's avatar Andrey Vagin Committed by Pavel Emelyanov

mount: Add abstraction layer for dumping file systems (v2)

We need to dump content of some fs like binfmt_misc, tmpfs, ... To facilitate
this the existing list of filesystems is turned into an array of structures
with dump and restore callbacks. Each FS may declare them they need.

v2: rework encode/decode_fstype not to do it twice.
Signed-off-by: 's avatarAndrey Vagin <avagin@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 0b5425b6
...@@ -8,6 +8,7 @@ struct proc_mountinfo; ...@@ -8,6 +8,7 @@ struct proc_mountinfo;
extern int open_mount(unsigned int s_dev); extern int open_mount(unsigned int s_dev);
extern int collect_mount_info(void); extern int collect_mount_info(void);
extern struct fstype *find_fstype_by_name(char *fst);
struct cr_fdset; struct cr_fdset;
extern int dump_mnt_ns(int pid, struct cr_fdset *); extern int dump_mnt_ns(int pid, struct cr_fdset *);
......
...@@ -90,6 +90,13 @@ struct proc_status_creds { ...@@ -90,6 +90,13 @@ struct proc_status_creds {
uint32_t cap_bnd[PROC_CAP_SIZE]; uint32_t cap_bnd[PROC_CAP_SIZE];
}; };
struct mount_info;
struct fstype {
char *name;
int (*dump)(struct mount_info *pm);
int (*restore)(struct mount_info *pm);
};
struct mount_info { struct mount_info {
int mnt_id; int mnt_id;
int parent_mnt_id; int parent_mnt_id;
...@@ -99,7 +106,7 @@ struct mount_info { ...@@ -99,7 +106,7 @@ struct mount_info {
unsigned flags; unsigned flags;
int master_id; int master_id;
int shared_id; int shared_id;
char *fstype; struct fstype *fstype;
char *source; char *source;
char *options; char *options;
struct mount_info *next; struct mount_info *next;
......
...@@ -179,14 +179,14 @@ static struct mount_info *mnt_build_tree(struct mount_info *list) ...@@ -179,14 +179,14 @@ static struct mount_info *mnt_build_tree(struct mount_info *list)
return tree; return tree;
} }
static char *fstypes[] = { static struct fstype fstypes[] = {
"unsupported", { "unsupported" },
"proc", { "proc" },
"sysfs", { "sysfs" },
"devtmpfs", { "devtmpfs" },
}; };
static u32 encode_fstype(char *fst) struct fstype *find_fstype_by_name(char *fst)
{ {
int i; int i;
...@@ -199,22 +199,24 @@ static u32 encode_fstype(char *fst) ...@@ -199,22 +199,24 @@ static u32 encode_fstype(char *fst)
*/ */
for (i = 0; i < ARRAY_SIZE(fstypes); i++) for (i = 0; i < ARRAY_SIZE(fstypes); i++)
if (!strcmp(fstypes[i], fst)) if (!strcmp(fstypes[i].name, fst))
return i; return fstypes + i;
return 0; return &fstypes[0];
} }
static char *decode_fstype(u32 fst) static u32 encode_fstype(struct fstype *fst)
{ {
static char uns[12]; return fst - fstypes;
}
if (fst >= ARRAY_SIZE(fstypes)) { static struct fstype *decode_fstype(u32 fst)
sprintf(uns, "x%d", fst); {
return uns;
} if (fst >= ARRAY_SIZE(fstypes))
return &fstypes[0];
return fstypes[fst]; return &fstypes[fst];
} }
static inline int is_root(char *p) static inline int is_root(char *p)
...@@ -235,6 +237,9 @@ static int dump_one_mountpoint(struct mount_info *pm, int fd) ...@@ -235,6 +237,9 @@ static int dump_one_mountpoint(struct mount_info *pm, int fd)
pm->root, pm->mountpoint); pm->root, pm->mountpoint);
me.fstype = encode_fstype(pm->fstype); me.fstype = encode_fstype(pm->fstype);
if (fstypes[me.fstype].dump && fstypes[me.fstype].dump(pm))
return -1;
me.mnt_id = pm->mnt_id; me.mnt_id = pm->mnt_id;
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;
...@@ -245,7 +250,8 @@ static int dump_one_mountpoint(struct mount_info *pm, int fd) ...@@ -245,7 +250,8 @@ static int dump_one_mountpoint(struct mount_info *pm, int fd)
me.options = pm->options; me.options = pm->options;
if (!me.fstype && !is_root_mount(pm)) { if (!me.fstype && !is_root_mount(pm)) {
pr_err("FS %s unsupported\n", pm->fstype); pr_err("FS mnt %s dev 0x%x root %s unsupported\n",
pm->mountpoint, pm->s_dev, pm->root);
return -1; return -1;
} }
...@@ -336,17 +342,21 @@ static char *resolve_source(struct mount_info *mi) ...@@ -336,17 +342,21 @@ static char *resolve_source(struct mount_info *mi)
static int do_new_mount(struct mount_info *mi) static int do_new_mount(struct mount_info *mi)
{ {
char *src; char *src;
struct fstype *tp = mi->fstype;
src = resolve_source(mi); src = resolve_source(mi);
if (!src) if (!src)
return -1; return -1;
if (mount(src, mi->mountpoint, mi->fstype, if (mount(src, mi->mountpoint, tp->name,
mi->flags, mi->options) < 0) { mi->flags, 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;
return 0; return 0;
} }
...@@ -366,7 +376,7 @@ static int do_mount_one(struct mount_info *mi) ...@@ -366,7 +376,7 @@ static int do_mount_one(struct mount_info *mi)
if (!mi->parent) if (!mi->parent)
return 0; return 0;
pr_debug("\tMounting %s @%s\n", mi->fstype, mi->mountpoint); pr_debug("\tMounting %s @%s\n", mi->fstype->name, mi->mountpoint);
if (fsroot_mounted(mi)) if (fsroot_mounted(mi))
return do_new_mount(mi); return do_new_mount(mi);
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include "list.h" #include "list.h"
#include "util.h" #include "util.h"
#include "crtools.h" #include "crtools.h"
#include "mount.h"
#include "proc_parse.h" #include "proc_parse.h"
#include "protobuf.h" #include "protobuf.h"
...@@ -592,6 +593,7 @@ static int parse_mountinfo_ent(char *str, struct mount_info *new) ...@@ -592,6 +593,7 @@ static int parse_mountinfo_ent(char *str, struct mount_info *new)
unsigned int kmaj, kmin; unsigned int kmaj, kmin;
int ret, n; int ret, n;
char *opt; char *opt;
char *fstype;
ret = sscanf(str, "%i %i %u:%u %ms %ms %ms %n", ret = sscanf(str, "%i %i %u:%u %ms %ms %ms %n",
&new->mnt_id, &new->parent_mnt_id, &new->mnt_id, &new->parent_mnt_id,
...@@ -612,10 +614,13 @@ static int parse_mountinfo_ent(char *str, struct mount_info *new) ...@@ -612,10 +614,13 @@ static int parse_mountinfo_ent(char *str, struct mount_info *new)
return -1; return -1;
str += n; str += n;
ret = sscanf(str, "%ms %ms %ms", &new->fstype, &new->source, &opt); ret = sscanf(str, "%ms %ms %ms", &fstype, &new->source, &opt);
if (ret != 3) if (ret != 3)
return -1; return -1;
new->fstype = find_fstype_by_name(fstype);
free(fstype);
new->options = xmalloc(strlen(opt)); new->options = xmalloc(strlen(opt));
if (!new->options) if (!new->options)
return -1; return -1;
...@@ -658,7 +663,7 @@ struct mount_info *parse_mountinfo(pid_t pid) ...@@ -658,7 +663,7 @@ struct mount_info *parse_mountinfo(pid_t pid)
} }
pr_info("\ttype %s source %s %x %s @ %s flags %x options %s\n", pr_info("\ttype %s source %s %x %s @ %s flags %x options %s\n",
new->fstype, new->source, new->fstype->name, new->source,
new->s_dev, new->root, new->mountpoint, new->s_dev, new->root, new->mountpoint,
new->flags, new->options); new->flags, new->options);
......
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