From 475bb1e77522e6f40d4171266ec8e079b397a49c Mon Sep 17 00:00:00 2001 From: Pavel Emelyanov Date: Sat, 19 Jan 2013 01:16:19 +0400 Subject: [PATCH] rst: Evaluate per-task clone mask early When we've read all pstree-items and their ids we can get the desired clone-flags early and avoid all these dances with flag calculations in fork_with_pid and company. Signed-off-by: Pavel Emelyanov --- cr-restore.c | 14 ++++----- include/crtools.h | 2 ++ include/namespaces.h | 1 - include/syscall-types.h | 2 ++ namespaces.c | 50 -------------------------------- pstree.c | 63 +++++++++++++++++++++++++++++++++++------ 6 files changed, 65 insertions(+), 67 deletions(-) diff --git a/cr-restore.c b/cr-restore.c index 6f84ff01b..36498663c 100644 --- a/cr-restore.c +++ b/cr-restore.c @@ -799,19 +799,17 @@ static void write_pidfile(char *pfname, int pid) close(fd); } -static inline int fork_with_pid(struct pstree_item *item, unsigned long ns_clone_flags) +static inline int fork_with_pid(struct pstree_item *item) { int ret = -1; struct cr_clone_arg ca; pid_t pid = item->pid.virt; - pr_info("Forking task with %d pid (flags 0x%lx)\n", pid, ns_clone_flags); ca.item = item; - ca.clone_flags = ns_clone_flags; + ca.clone_flags = item->rst->clone_flags; - if (shared_fdtable(item)) - ca.clone_flags |= CLONE_FILES; + pr_info("Forking task with %d pid (flags 0x%lx)\n", pid, ca.clone_flags); if (!(ca.clone_flags & CLONE_NEWPID)) { char buf[32]; @@ -1070,7 +1068,7 @@ static int restore_task_with_children(void *_arg) BUG_ON(child->born_sid != -1 && getsid(getpid()) != child->born_sid); - ret = fork_with_pid(child, 0); + ret = fork_with_pid(child); if (ret < 0) exit(1); } @@ -1081,7 +1079,7 @@ static int restore_task_with_children(void *_arg) list_for_each_entry(child, ¤t->children, sibling) { if (restore_before_setsid(child)) continue; - ret = fork_with_pid(child, 0); + ret = fork_with_pid(child); if (ret < 0) exit(1); } @@ -1176,7 +1174,7 @@ static int restore_root_task(struct pstree_item *init, struct cr_options *opts) futex_set(&task_entries->nr_in_progress, stage_participants(CR_STATE_FORKING)); - ret = fork_with_pid(init, current_ns_mask); + ret = fork_with_pid(init); if (ret < 0) return -1; diff --git a/include/crtools.h b/include/crtools.h index 71f99c3ea..a96e3ce98 100644 --- a/include/crtools.h +++ b/include/crtools.h @@ -254,9 +254,11 @@ struct rst_info { void *premmapped_addr; unsigned long premmapped_len; + unsigned long clone_flags; int service_fd_id; struct fdt *fdt; + }; static inline int in_vma_area(struct vma_area *vma, unsigned long addr) diff --git a/include/namespaces.h b/include/namespaces.h index 3fc5acdb4..c0a1ff779 100644 --- a/include/namespaces.h +++ b/include/namespaces.h @@ -22,6 +22,5 @@ struct pstree_item; int dump_task_ns_ids(struct pstree_item *); extern unsigned long current_ns_mask; -int check_ns_ids(struct pstree_item *); #endif /* __CR_NS_H__ */ diff --git a/include/syscall-types.h b/include/syscall-types.h index 40390d51d..922375a1b 100644 --- a/include/syscall-types.h +++ b/include/syscall-types.h @@ -55,6 +55,8 @@ struct robust_list_head; #define CLONE_NEWNET 0x40000000 #endif +#define CLONE_ALLNS (CLONE_NEWPID | CLONE_NEWNET | CLONE_NEWIPC | CLONE_NEWUTS | CLONE_NEWNS) + #define setns sys_setns struct rlimit; diff --git a/namespaces.c b/namespaces.c index 76b3ef23e..847050814 100644 --- a/namespaces.c +++ b/namespaces.c @@ -260,56 +260,6 @@ int dump_namespaces(struct pid *ns_pid, unsigned int ns_flags) return 0; } -static unsigned long get_clone_mask(TaskKobjIdsEntry *i, - TaskKobjIdsEntry *p) -{ - unsigned long mask = 0; - - if (i->pid_ns_id != p->pid_ns_id) - mask |= CLONE_NEWPID; - if (i->net_ns_id != p->net_ns_id) - mask |= CLONE_NEWNET; - if (i->ipc_ns_id != p->ipc_ns_id) - mask |= CLONE_NEWIPC; - if (i->uts_ns_id != p->uts_ns_id) - mask |= CLONE_NEWUTS; - if (i->mnt_ns_id != p->mnt_ns_id) - mask |= CLONE_NEWNS; - - return mask; -} - -int check_ns_ids(struct pstree_item *item) -{ - struct pstree_item *p = item->parent; - - if (!p) { - if (!root_ids) { - current_ns_mask = opts.rst_namespaces_flags; - return 0; - } - - current_ns_mask = get_clone_mask(item->ids, root_ids); - pr_info("Will restore in %lx namespaces\n", current_ns_mask); - return 0; - } - - if (!item->ids) - return 0; - - while (!p->ids) { - p = p->parent; - BUG_ON(!p); /* must meet the root_item */ - } - - if (get_clone_mask(item->ids, p->ids)) { - pr_err("Task in sub namespace\n"); - return -1; - } - - return 0; -} - int prepare_namespace(int pid, unsigned long clone_flags) { pr_info("Restoring namespaces %d flags 0x%lx\n", diff --git a/pstree.c b/pstree.c index fd0484045..e1c800f13 100644 --- a/pstree.c +++ b/pstree.c @@ -304,7 +304,7 @@ static int prepare_pstree_ids(void) if (item->sid == root_item->sid || item->sid == item->pid.virt) continue; - helper = alloc_pstree_item(); + helper = alloc_pstree_item_with_rst(); if (helper == NULL) return -1; helper->sid = item->sid; @@ -422,7 +422,7 @@ static int prepare_pstree_ids(void) if (current_pgid == item->pgid) continue; - helper = alloc_pstree_item(); + helper = alloc_pstree_item_with_rst(); if (helper == NULL) return -1; helper->sid = item->sid; @@ -440,6 +440,27 @@ static int prepare_pstree_ids(void) return 0; } +static unsigned long get_clone_mask(TaskKobjIdsEntry *i, + TaskKobjIdsEntry *p) +{ + unsigned long mask = 0; + + if (i->files_id == p->files_id) + mask |= CLONE_FILES; + if (i->pid_ns_id != p->pid_ns_id) + mask |= CLONE_NEWPID; + if (i->net_ns_id != p->net_ns_id) + mask |= CLONE_NEWNET; + if (i->ipc_ns_id != p->ipc_ns_id) + mask |= CLONE_NEWIPC; + if (i->uts_ns_id != p->uts_ns_id) + mask |= CLONE_NEWUTS; + if (i->mnt_ns_id != p->mnt_ns_id) + mask |= CLONE_NEWNS; + + return mask; +} + static int prepare_pstree_kobj_ids(void) { struct pstree_item *item; @@ -447,23 +468,49 @@ static int prepare_pstree_kobj_ids(void) /* Find a process with minimal pid for shared fd tables */ for_each_pstree_item(item) { struct pstree_item *parent = item->parent; + TaskKobjIdsEntry *ids; + unsigned long cflags; + + if (!item->ids) { + if (item == root_item) { + cflags = opts.rst_namespaces_flags; + goto set_mask; + } - if (item->state == TASK_HELPER) continue; + } - if (check_ns_ids(item)) - return -1; + if (parent) + ids = parent->ids; + else + ids = root_ids; - if (parent == NULL) - continue; + cflags = get_clone_mask(item->ids, ids); - if (shared_fdtable(item)) { + if (cflags & CLONE_FILES) { int ret; ret = shared_fdt_prepare(item); if (ret) return ret; } + +set_mask: + item->rst->clone_flags = cflags; + + /* + * Workaround for current namespaces model -- + * all tasks should be in one namespace. And + * this namespace is either inherited from the + * crtools or is created for the init task (only) + */ + if (item == root_item) { + pr_info("Will restore in %lx namespaces\n", cflags); + current_ns_mask = cflags & CLONE_ALLNS; + } else if (cflags & CLONE_ALLNS) { + pr_err("Can't restore sub-task in NS\n"); + return -1; + } } return 0;