mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 14:25:49 +00:00
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 <xemul@parallels.com>
This commit is contained in:
14
cr-restore.c
14
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;
|
||||
|
||||
|
@@ -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)
|
||||
|
@@ -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__ */
|
||||
|
@@ -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;
|
||||
|
50
namespaces.c
50
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",
|
||||
|
63
pstree.c
63
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;
|
||||
|
Reference in New Issue
Block a user