[CRIU] [PATCH 4/5] pstree: try to find a free pid between busy pids
Andrey Vagin
avagin at openvz.org
Fri Feb 19 10:13:30 PST 2016
From: Andrew Vagin <avagin at virtuozzo.com>
Currently our pid allocator returns max_pid++ and it can return a pid
which is bigger than kernel.max_pid.
(00.821430) 5506: Error (cr-restore.c:1540): Pid 300 do not match expected 32768
https://jira.sw.ru/browse/PSBM-42202
Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
---
criu/pstree.c | 93 +++++++++++++++++++++++++++++++++++------------------------
1 file changed, 56 insertions(+), 37 deletions(-)
diff --git a/criu/pstree.c b/criu/pstree.c
index 1be8c48..61fd5d3 100644
--- a/criu/pstree.c
+++ b/criu/pstree.c
@@ -331,8 +331,6 @@ err:
return ret;
}
-static int max_pid = 0;
-
static int prepare_pstree_for_shell_job(void)
{
pid_t current_sid = getsid(getpid());
@@ -379,8 +377,8 @@ static int prepare_pstree_for_shell_job(void)
pi->sid = current_sid;
}
- max_pid = max((int)current_sid, max_pid);
- max_pid = max((int)current_gid, max_pid);
+ insert_item(current_sid);
+ insert_item(current_gid);
return 0;
}
@@ -459,11 +457,8 @@ static int read_pstree_image(void)
break;
pi->pid.virt = e->pid;
- max_pid = max((int)e->pid, max_pid);
pi->pgid = e->pgid;
- max_pid = max((int)e->pgid, max_pid);
pi->sid = e->sid;
- max_pid = max((int)e->sid, max_pid);
pi->pid.state = TASK_ALIVE;
if (e->ppid == 0) {
@@ -543,11 +538,34 @@ static int read_pstree_image(void)
goto err;
}
}
+
err:
close_image(img);
return ret;
}
+#define RESERVED_PIDS 300
+static int get_free_pid()
+{
+ static struct pstree_item *prev, *next;
+
+ if (prev == NULL)
+ prev = rb_entry(rb_first(&root_rb), struct pstree_item, pid.node);
+
+ while (1) {
+ pid_t pid;
+ pid = prev->pid.virt + 1;
+ pid = pid < RESERVED_PIDS ? RESERVED_PIDS + 1 : pid;
+
+ next = rb_entry(rb_next(&prev->pid.node), struct pstree_item, pid.node);
+ if (&next->pid.node == NULL || next->pid.virt > pid)
+ return pid;
+ prev = next;
+ }
+
+ return -1;
+}
+
static int prepare_pstree_ids(void)
{
struct pstree_item *item, *child, *helper, *tmp;
@@ -562,6 +580,7 @@ static int prepare_pstree_ids(void)
* reparented to init.
*/
list_for_each_entry(item, &root_item->children, sibling) {
+ struct pstree_item *leader;
/*
* If a child belongs to the root task's session or it's
@@ -571,15 +590,36 @@ static int prepare_pstree_ids(void)
if (item->sid == root_item->sid || item->sid == item->pid.virt)
continue;
- helper = alloc_pstree_helper();
- if (helper == NULL)
- return -1;
- helper->sid = item->sid;
- helper->pgid = item->sid;
- helper->pid.virt = item->sid;
- helper->parent = root_item;
- helper->ids = root_item->ids;
- list_add_tail(&helper->sibling, &helpers);
+ leader = insert_item(item->sid);
+ if (leader->pid.state != TASK_UNDEF) {
+ pid_t pid;
+
+ pid = get_free_pid();
+ if (pid < 0)
+ break;
+ helper = insert_item(pid);
+ if (helper == NULL)
+ return -1;
+
+ pr_info("Session leader %d\n", item->sid);
+
+ helper->sid = item->sid;
+ helper->pgid = leader->pgid;
+ helper->ids = leader->ids;
+ helper->parent = leader;
+ list_add(&helper->sibling, &leader->children);
+
+ pr_info("Attach %d to the task %d\n",
+ helper->pid.virt, leader->pid.virt);
+ } else {
+ helper = leader;
+ helper->sid = item->sid;
+ helper->pgid = item->sid;
+ helper->parent = root_item;
+ helper->ids = root_item->ids;
+ list_add_tail(&helper->sibling, &helpers);
+ }
+ init_pstree_helper(helper);
pr_info("Add a helper %d for restoring SID %d\n",
helper->pid.virt, helper->sid);
@@ -639,27 +679,6 @@ static int prepare_pstree_ids(void)
continue;
}
-
- pr_info("Session leader %d\n", item->sid);
-
- /* Try to find helpers, who should be connected to the leader */
- list_for_each_entry(child, &helpers, sibling) {
- if (child->pid.state != TASK_HELPER)
- continue;
-
- if (child->sid != item->sid)
- continue;
-
- child->pgid = item->pgid;
- child->pid.virt = ++max_pid;
- child->parent = item;
- list_move(&child->sibling, &item->children);
-
- pr_info("Attach %d to the task %d\n",
- child->pid.virt, item->pid.virt);
-
- break;
- }
}
/* All other helpers are session leaders for own sessions */
--
2.5.0
More information about the CRIU
mailing list