mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 22:35:33 +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);
|
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;
|
int ret = -1;
|
||||||
struct cr_clone_arg ca;
|
struct cr_clone_arg ca;
|
||||||
pid_t pid = item->pid.virt;
|
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.item = item;
|
||||||
ca.clone_flags = ns_clone_flags;
|
ca.clone_flags = item->rst->clone_flags;
|
||||||
|
|
||||||
if (shared_fdtable(item))
|
pr_info("Forking task with %d pid (flags 0x%lx)\n", pid, ca.clone_flags);
|
||||||
ca.clone_flags |= CLONE_FILES;
|
|
||||||
|
|
||||||
if (!(ca.clone_flags & CLONE_NEWPID)) {
|
if (!(ca.clone_flags & CLONE_NEWPID)) {
|
||||||
char buf[32];
|
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);
|
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)
|
if (ret < 0)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@@ -1081,7 +1079,7 @@ static int restore_task_with_children(void *_arg)
|
|||||||
list_for_each_entry(child, ¤t->children, sibling) {
|
list_for_each_entry(child, ¤t->children, sibling) {
|
||||||
if (restore_before_setsid(child))
|
if (restore_before_setsid(child))
|
||||||
continue;
|
continue;
|
||||||
ret = fork_with_pid(child, 0);
|
ret = fork_with_pid(child);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
exit(1);
|
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));
|
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)
|
if (ret < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@@ -254,9 +254,11 @@ struct rst_info {
|
|||||||
|
|
||||||
void *premmapped_addr;
|
void *premmapped_addr;
|
||||||
unsigned long premmapped_len;
|
unsigned long premmapped_len;
|
||||||
|
unsigned long clone_flags;
|
||||||
|
|
||||||
int service_fd_id;
|
int service_fd_id;
|
||||||
struct fdt *fdt;
|
struct fdt *fdt;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline int in_vma_area(struct vma_area *vma, unsigned long addr)
|
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 *);
|
int dump_task_ns_ids(struct pstree_item *);
|
||||||
|
|
||||||
extern unsigned long current_ns_mask;
|
extern unsigned long current_ns_mask;
|
||||||
int check_ns_ids(struct pstree_item *);
|
|
||||||
|
|
||||||
#endif /* __CR_NS_H__ */
|
#endif /* __CR_NS_H__ */
|
||||||
|
@@ -55,6 +55,8 @@ struct robust_list_head;
|
|||||||
#define CLONE_NEWNET 0x40000000
|
#define CLONE_NEWNET 0x40000000
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#define CLONE_ALLNS (CLONE_NEWPID | CLONE_NEWNET | CLONE_NEWIPC | CLONE_NEWUTS | CLONE_NEWNS)
|
||||||
|
|
||||||
#define setns sys_setns
|
#define setns sys_setns
|
||||||
|
|
||||||
struct rlimit;
|
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;
|
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)
|
int prepare_namespace(int pid, unsigned long clone_flags)
|
||||||
{
|
{
|
||||||
pr_info("Restoring namespaces %d flags 0x%lx\n",
|
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)
|
if (item->sid == root_item->sid || item->sid == item->pid.virt)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
helper = alloc_pstree_item();
|
helper = alloc_pstree_item_with_rst();
|
||||||
if (helper == NULL)
|
if (helper == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
helper->sid = item->sid;
|
helper->sid = item->sid;
|
||||||
@@ -422,7 +422,7 @@ static int prepare_pstree_ids(void)
|
|||||||
if (current_pgid == item->pgid)
|
if (current_pgid == item->pgid)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
helper = alloc_pstree_item();
|
helper = alloc_pstree_item_with_rst();
|
||||||
if (helper == NULL)
|
if (helper == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
helper->sid = item->sid;
|
helper->sid = item->sid;
|
||||||
@@ -440,6 +440,27 @@ static int prepare_pstree_ids(void)
|
|||||||
return 0;
|
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)
|
static int prepare_pstree_kobj_ids(void)
|
||||||
{
|
{
|
||||||
struct pstree_item *item;
|
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 */
|
/* Find a process with minimal pid for shared fd tables */
|
||||||
for_each_pstree_item(item) {
|
for_each_pstree_item(item) {
|
||||||
struct pstree_item *parent = item->parent;
|
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;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (check_ns_ids(item))
|
if (parent)
|
||||||
return -1;
|
ids = parent->ids;
|
||||||
|
else
|
||||||
|
ids = root_ids;
|
||||||
|
|
||||||
if (parent == NULL)
|
cflags = get_clone_mask(item->ids, ids);
|
||||||
continue;
|
|
||||||
|
|
||||||
if (shared_fdtable(item)) {
|
if (cflags & CLONE_FILES) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = shared_fdt_prepare(item);
|
ret = shared_fdt_prepare(item);
|
||||||
if (ret)
|
if (ret)
|
||||||
return 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;
|
return 0;
|
||||||
|
Reference in New Issue
Block a user