[CRIU] [PATCH 6/6] pstree: try to find a free pid between busy pids (v2)
Pavel Emelyanov
xemul at virtuozzo.com
Tue Mar 15 06:12:06 PDT 2016
On 03/15/2016 09:37 AM, Andrey Vagin wrote:
> 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
>
> v2: handle error code from insert_item()
> Signed-off-by: Andrew Vagin <avagin at virtuozzo.com>
> ---
> criu/pstree.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++---------
> 1 file changed, 54 insertions(+), 9 deletions(-)
>
> diff --git a/criu/pstree.c b/criu/pstree.c
> index 3a278fa..096abec 100644
> --- a/criu/pstree.c
> +++ b/criu/pstree.c
> @@ -325,8 +325,6 @@ err:
> return ret;
> }
>
> -static int max_pid = 0;
> -
> static int prepare_pstree_for_shell_job(void)
> {
> pid_t current_sid = getsid(getpid());
> @@ -373,12 +371,31 @@ 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);
> + if (lookup_create_item(current_sid))
> + return -1;
> + if (lookup_create_item(current_gid))
> + return -1;
This particular hunk seem to belong to different patch... #3?
>
> return 0;
> }
>
> +static struct pid *pstree_pid_by_virt(pid_t pid)
> +{
> + struct rb_node *node = pid_root_rb.rb_node;
> +
> + while (node) {
> + struct pid *this = rb_entry(node, struct pid, node);
> +
> + if (pid < this->virt)
> + node = node->rb_left;
> + else if (pid > this->virt)
> + node = node->rb_right;
> + else
> + return this;
> + }
> + return NULL;
> +}
> +
> /*
> * Try to find a pid node in the tree and insert a new one,
> * it is not there yet. If pid_node isn't set, pstree_item
> @@ -465,11 +482,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) {
> @@ -558,11 +572,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(&pid_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;
> @@ -578,6 +615,7 @@ static int prepare_pstree_ids(void)
> */
> list_for_each_entry(item, &root_item->children, sibling) {
> struct pstree_item *leader;
> + struct pid *node;
>
> /*
> * If a child belongs to the root task's session or it's
> @@ -587,9 +625,16 @@ static int prepare_pstree_ids(void)
> if (item->sid == root_item->sid || item->sid == item->pid.virt)
> continue;
>
> - leader = insert_item(item->sid);
> + node = pstree_pid_by_virt(item->sid);
> + BUG_ON(node == NULL);
> + leader = container_of(node, struct pstree_item, pid);
> if (leader->pid.state != TASK_UNDEF) {
> - helper = insert_item(++max_pid);
> + pid_t pid;
> +
> + pid = get_free_pid();
> + if (pid < 0)
> + break;
> + helper = lookup_create_item(pid);
> if (helper == NULL)
> return -1;
>
>
More information about the CRIU
mailing list