Commit 42205175 authored by Andrew Vagin's avatar Andrew Vagin Committed by Pavel Emelyanov

pstree: use rbtree to find a specified pid (v3)

Currently we enumirate all children of the init task and
if a task isn't a session leader, we create a helper,
collect all children with this sid to the children list of this helper.

When all children of the init task has been enumirated, we try to find
a session leader for each helper.

We use this way to enumirate all tasks only once.

Now we are going to collect all tasks in rbtree, so we can find
a sessial leader when we need it. It will not affect performance,
because without searching a session leader, we can't add a helper
to the tree.

v2: rename lookup_pid to pstree_pid_by_virt
    use pstree_pid_by_virt in pstree_item_by_virt
v3: handle session leaders in this patch too
Signed-off-by: 's avatarAndrew Vagin <avagin@virtuozzo.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent 7f9961b3
...@@ -19,8 +19,6 @@ ...@@ -19,8 +19,6 @@
struct pstree_item *root_item; struct pstree_item *root_item;
static struct rb_root pid_root_rb; static struct rb_root pid_root_rb;
#define alloc_pstree_item_with_rst() __alloc_pstree_item(true)
void core_entry_free(CoreEntry *core) void core_entry_free(CoreEntry *core)
{ {
if (core->tc && core->tc->timers) if (core->tc && core->tc->timers)
...@@ -227,17 +225,6 @@ void init_pstree_helper(struct pstree_item *ret) ...@@ -227,17 +225,6 @@ void init_pstree_helper(struct pstree_item *ret)
task_entries->nr_helpers++; task_entries->nr_helpers++;
} }
static struct pstree_item *alloc_pstree_helper(void)
{
struct pstree_item *ret;
ret = alloc_pstree_item_with_rst();
if (ret)
init_pstree_helper(ret);
return ret;
}
/* Deep first search on children */ /* Deep first search on children */
struct pstree_item *pstree_item_next(struct pstree_item *item) struct pstree_item *pstree_item_next(struct pstree_item *item)
{ {
...@@ -416,7 +403,7 @@ static struct pid *lookup_create_pid(pid_t pid, struct pid *pid_node) ...@@ -416,7 +403,7 @@ static struct pid *lookup_create_pid(pid_t pid, struct pid *pid_node)
if (!pid_node) { if (!pid_node) {
struct pstree_item *item; struct pstree_item *item;
item = alloc_pstree_item_with_rst(); item = __alloc_pstree_item(true);
if (item == NULL) if (item == NULL)
return NULL; return NULL;
...@@ -439,6 +426,23 @@ struct pstree_item *lookup_create_item(pid_t pid) ...@@ -439,6 +426,23 @@ struct pstree_item *lookup_create_item(pid_t pid)
return container_of(node, struct pstree_item, pid); return container_of(node, struct pstree_item, pid);
} }
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;
}
static int read_pstree_ids(struct pstree_item *pi) static int read_pstree_ids(struct pstree_item *pi)
{ {
int ret; int ret;
...@@ -595,6 +599,7 @@ static int prepare_pstree_ids(void) ...@@ -595,6 +599,7 @@ static int prepare_pstree_ids(void)
* reparented to init. * reparented to init.
*/ */
list_for_each_entry(item, &root_item->children, sibling) { 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 * If a child belongs to the root task's session or it's
...@@ -604,15 +609,32 @@ static int prepare_pstree_ids(void) ...@@ -604,15 +609,32 @@ 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_helper(); leader = pstree_item_by_virt(item->sid);
if (helper == NULL) BUG_ON(leader == NULL);
return -1; if (leader->pid.state != TASK_UNDEF) {
helper->sid = item->sid; helper = lookup_create_item(++max_pid);
helper->pgid = item->sid; if (helper == NULL)
helper->pid.virt = item->sid; return -1;
helper->parent = root_item;
helper->ids = root_item->ids; pr_info("Session leader %d\n", item->sid);
list_add_tail(&helper->sibling, &helpers);
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", pr_info("Add a helper %d for restoring SID %d\n",
helper->pid.virt, helper->sid); helper->pid.virt, helper->sid);
...@@ -672,27 +694,6 @@ static int prepare_pstree_ids(void) ...@@ -672,27 +694,6 @@ static int prepare_pstree_ids(void)
continue; 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 */ /* All other helpers are session leaders for own sessions */
...@@ -700,18 +701,15 @@ static int prepare_pstree_ids(void) ...@@ -700,18 +701,15 @@ static int prepare_pstree_ids(void)
/* Add a process group leader if it is absent */ /* Add a process group leader if it is absent */
for_each_pstree_item(item) { for_each_pstree_item(item) {
struct pstree_item *gleader; struct pid *pid;
if (!item->pgid || item->pid.virt == item->pgid) if (!item->pgid || item->pid.virt == item->pgid)
continue; continue;
for_each_pstree_item(gleader) { pid = pstree_pid_by_virt(item->pgid);
if (gleader->pid.virt == item->pgid) if (pid->state != TASK_UNDEF) {
break; BUG_ON(pid->state == TASK_THREAD);
} rsti(item)->pgrp_leader = container_of(pid, struct pstree_item, pid);
if (gleader) {
rsti(item)->pgrp_leader = gleader;
continue; continue;
} }
...@@ -723,9 +721,9 @@ static int prepare_pstree_ids(void) ...@@ -723,9 +721,9 @@ static int prepare_pstree_ids(void)
if (current_pgid == item->pgid) if (current_pgid == item->pgid)
continue; continue;
helper = alloc_pstree_helper(); helper = container_of(pid, struct pstree_item, pid);
if (helper == NULL) init_pstree_helper(helper);
return -1;
helper->sid = item->sid; helper->sid = item->sid;
helper->pgid = item->pgid; helper->pgid = item->pgid;
helper->pid.virt = item->pgid; helper->pid.virt = item->pgid;
...@@ -897,13 +895,14 @@ bool restore_before_setsid(struct pstree_item *child) ...@@ -897,13 +895,14 @@ bool restore_before_setsid(struct pstree_item *child)
struct pstree_item *pstree_item_by_virt(pid_t virt) struct pstree_item *pstree_item_by_virt(pid_t virt)
{ {
struct pstree_item *item; struct pid *pid;
for_each_pstree_item(item) { pid = pstree_pid_by_virt(virt);
if (item->pid.virt == virt) if (pid == NULL)
return item; return NULL;
} BUG_ON(pid->state == TASK_THREAD);
return NULL;
return container_of(pid, struct pstree_item, pid);
} }
struct pstree_item *pstree_item_by_real(pid_t real) struct pstree_item *pstree_item_by_real(pid_t real)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment