From 95964f1b13921d245ca7741d2d209e4754cb6ea8 Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Wed, 27 Jun 2012 20:57:36 +0400 Subject: [PATCH] mount: Core for creating mount namespace Namespace restore goes in two steps -- first, clean old mountpoints (except root) that are left after clone(CLONE_NEWNS) call. Next, repopulate the namespace with new mountpoints (except root) read from the image file. This patch adds the skeleton for the above -- reading the mountpoints from current proc and image and calling for mount/umount. The real action will come in further patches. Signed-off-by: Pavel Emelyanov --- include/mount.h | 1 + mount.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++- namespaces.c | 2 + 3 files changed, 137 insertions(+), 2 deletions(-) diff --git a/include/mount.h b/include/mount.h index 22f89c2a7..300807c68 100644 --- a/include/mount.h +++ b/include/mount.h @@ -10,5 +10,6 @@ struct cr_fdset; extern int dump_mnt_ns(int pid, struct cr_fdset *); struct cr_options; extern void show_mountpoints(int fd, struct cr_options *); +int prepare_mnt_ns(int pid); #endif /* MOUNT_H__ */ diff --git a/mount.c b/mount.c index ce7a00b2b..649cd647e 100644 --- a/mount.c +++ b/mount.c @@ -266,8 +266,6 @@ int dump_mnt_ns(int ns_pid, struct cr_fdset *fdset) return -1; } - mnt_build_tree(pm); - pr_info("Dumping mountpoints\n"); img_fd = fdset_fd(fdset, CR_FD_MOUNTPOINTS); @@ -284,6 +282,140 @@ int dump_mnt_ns(int ns_pid, struct cr_fdset *fdset) return 0; } +static int mnt_tree_for_each(struct mount_info *m, + int (*fn)(struct mount_info *)) +{ + pr_err("NOT IMPLEMENTED\n"); + return -1; +} + +static int mnt_tree_for_each_reverse(struct mount_info *m, + int (*fn)(struct mount_info *)) +{ + pr_err("NOT IMPLEMENTED\n"); + return -1; +} + +static int do_mount_one(struct mount_info *mi) +{ + if (!mi->parent) + return 0; + + pr_debug("\tMounting %s @%s\n", mi->fstype, mi->mountpoint); + return 0; +} + +static int do_umount_one(struct mount_info *mi) +{ + if (!mi->parent) + return 0; + + pr_debug("\tUmounting %s\n", mi->mountpoint); + return 0; +} + +static int clean_mnt_ns(void) +{ + struct mount_info *pm; + + pr_info("Cleaning mount namespace\n"); + + pm = parse_mountinfo(getpid()); + if (!pm) { + pr_err("Can't parse my new mount namespace\n"); + return -1; + } + + pm = mnt_build_tree(pm); + if (!pm) + return -1; + + return mnt_tree_for_each_reverse(pm, do_umount_one); +} + +static int populate_mnt_ns(int ns_pid) +{ + int img, ret; + struct mount_info *pms = NULL; + + pr_info("Populating mount namespace\n"); + + img = open_image_ro(CR_FD_MOUNTPOINTS, ns_pid); + if (img < 0) + return -1; + + pr_debug("Reading mountpoint images\n"); + + while (1) { + struct mnt_entry me; + struct mount_info *pm; + + ret = read_img_eof(img, &me); + if (ret <= 0) + break; + + ret = -1; + pm = xmalloc(sizeof(*pm)); + if (!pm) + break; + + mnt_entry_init(pm); + + pm->mnt_id = me.mnt_id; + pm->parent_mnt_id = me.parent_mnt_id; + pm->s_dev = me.root_dev; + pm->flags = me.flags; + pm->fstype = decode_fstype(me.fstype); /* FIXME: abort unsupported early */ + + pr_debug("\t\tGetting root for %d\n", pm->mnt_id); + if (read_img_str(img, &pm->root, me.root_dentry_len) < 0) + break; + + pr_debug("\t\tGetting mpt for %d\n", pm->mnt_id); + if (read_img_str(img, &pm->mountpoint, me.mountpoint_path_len) < 0) + break; + + pr_debug("\t\tGetting source for %d\n", pm->mnt_id); + if (read_img_str(img, &pm->source, me.source_len) < 0) + break; + + pr_debug("\t\tGetting opts for %d\n", pm->mnt_id); + if (read_img_str(img, &pm->options, me.options_len) < 0) + break; + + pr_debug("\tRead %d mp @ %s\n", pm->mnt_id, pm->mountpoint); + pm->next = pms; + pms = pm; + } + + close(img); + + pms = mnt_build_tree(pms); + if (!pms) + return -1; + + return mnt_tree_for_each(pms, do_mount_one); +} + +int prepare_mnt_ns(int ns_pid) +{ + int ret; + + pr_info("Restoring mount namespace\n"); + + /* + * The new mount namespace is filled with the mountpoint + * clones from the original one. We have to umount them + * prior to recreating new ones. + */ + + ret = clean_mnt_ns(); + if (!ret) + ret = populate_mnt_ns(ns_pid); + + return ret; +} + void show_mountpoints(int fd, struct cr_options *o) { struct mnt_entry me; diff --git a/namespaces.c b/namespaces.c index 67d3d8eeb..9e3644193 100644 --- a/namespaces.c +++ b/namespaces.c @@ -124,6 +124,8 @@ int prepare_namespace(int pid, unsigned long clone_flags) ret = prepare_utsns(pid); if (clone_flags & CLONE_NEWIPC) ret = prepare_ipc_ns(pid); + if (clone_flags & CLONE_NEWNS) + ret = prepare_mnt_ns(pid); return ret; }