Commit 7f9961b3 authored by Andrew Vagin's avatar Andrew Vagin Committed by Pavel Emelyanov

pstree: prepare to store all pid-s in rb-tree (v3)

It will allow us to find a free pid and will speed up
searching an item by pid.

The current algorithm to searching a free pid may return
a value bigger that kernel.max_pid.

v2: add a coment before insert_pid()
    rename root_rb to pid_root_rb and make it "static"
v3: rename insert_{pid,item} into lookup_create_{pid,item}
Signed-off-by: 's avatarAndrew Vagin <avagin@virtuozzo.com>
Signed-off-by: 's avatarPavel Emelyanov <xemul@virtuozzo.com>
parent 60470bae
......@@ -360,18 +360,17 @@ static int open_remap_dead_process(struct reg_file_info *rfi,
{
struct pstree_item *helper;
for_each_pstree_item(helper) {
/* don't need to add multiple tasks */
if (helper->pid.virt == rfe->remap_id) {
pr_info("Skipping helper for restoring /proc/%d; pid exists\n", rfe->remap_id);
return 0;
}
}
helper = alloc_pstree_helper();
helper = lookup_create_item(rfe->remap_id);
if (!helper)
return -1;
if (helper->pid.state != TASK_UNDEF) {
pr_info("Skipping helper for restoring /proc/%d; pid exists\n", rfe->remap_id);
return 0;
}
init_pstree_helper(helper);
helper->sid = root_item->sid;
helper->pgid = root_item->pgid;
helper->pid.virt = rfe->remap_id;
......
......@@ -112,10 +112,12 @@
#define TASK_COMM_LEN 16
#define TASK_UNDEF 0x0
#define TASK_ALIVE 0x1
#define TASK_DEAD 0x2
#define TASK_STOPPED 0x3
#define TASK_HELPER 0x4
#define TASK_THREAD 0x5
#define CR_PARENT_LINK "parent"
......
......@@ -2,6 +2,7 @@
#define __CR_PID_H__
#include "stdbool.h"
#include "rbtree.h"
struct pid {
/*
......@@ -19,6 +20,8 @@ struct pid {
pid_t virt;
int state; /* TASK_XXX constants */
struct rb_node node;
};
/*
......
......@@ -64,10 +64,10 @@ static inline bool task_alive(struct pstree_item *i)
extern void free_pstree(struct pstree_item *root_item);
extern struct pstree_item *__alloc_pstree_item(bool rst);
#define alloc_pstree_item() __alloc_pstree_item(false)
#define alloc_pstree_item_with_rst() __alloc_pstree_item(true)
extern struct pstree_item *alloc_pstree_helper(void);
extern void init_pstree_helper(struct pstree_item *ret);
extern struct pstree_item *lookup_create_item(pid_t pid);
extern struct pstree_item *root_item;
extern struct pstree_item *pstree_item_next(struct pstree_item *item);
#define for_each_pstree_item(pi) \
......
......@@ -17,6 +17,9 @@
#include "images/pstree.pb-c.h"
struct pstree_item *root_item;
static struct rb_root pid_root_rb;
#define alloc_pstree_item_with_rst() __alloc_pstree_item(true)
void core_entry_free(CoreEntry *core)
{
......@@ -224,7 +227,7 @@ void init_pstree_helper(struct pstree_item *ret)
task_entries->nr_helpers++;
}
struct pstree_item *alloc_pstree_helper(void)
static struct pstree_item *alloc_pstree_helper(void)
{
struct pstree_item *ret;
......@@ -379,9 +382,63 @@ static int prepare_pstree_for_shell_job(void)
max_pid = max((int)current_sid, max_pid);
max_pid = max((int)current_gid, max_pid);
if (lookup_create_item(current_sid) == NULL)
return -1;
if (lookup_create_item(current_gid) == NULL)
return -1;
return 0;
}
/*
* 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
* is inserted.
*/
static struct pid *lookup_create_pid(pid_t pid, struct pid *pid_node)
{
struct rb_node *node = pid_root_rb.rb_node;
struct rb_node **new = &pid_root_rb.rb_node;
struct rb_node *parent = NULL;
while (node) {
struct pid *this = rb_entry(node, struct pid, node);
parent = *new;
if (pid < this->virt)
node = node->rb_left, new = &((*new)->rb_left);
else if (pid > this->virt)
node = node->rb_right, new = &((*new)->rb_right);
else
return this;
}
if (!pid_node) {
struct pstree_item *item;
item = alloc_pstree_item_with_rst();
if (item == NULL)
return NULL;
item->pid.virt = pid;
pid_node = &item->pid;
}
rb_link_and_balance(&pid_root_rb, &pid_node->node, parent, new);
return pid_node;
}
struct pstree_item *lookup_create_item(pid_t pid)
{
struct pid *node;;
node = lookup_create_pid(pid, NULL);
if (!node)
return NULL;
BUG_ON(node->state == TASK_THREAD);
return container_of(node, struct pstree_item, pid);
}
static int read_pstree_ids(struct pstree_item *pi)
{
int ret;
......@@ -425,18 +482,29 @@ static int read_pstree_image(void)
break;
ret = -1;
pi = alloc_pstree_item_with_rst();
pi = lookup_create_item(e->pid);
if (pi == NULL)
break;
BUG_ON(pi->pid.state != TASK_UNDEF);
/*
* All pids should be added in the tree to be able to find
* free pid-s for helpers. pstree_item for these pid-s will
* be initialized when we meet PstreeEntry with this pid or
* we will create helpers for them.
*/
if (lookup_create_item(e->pgid) == NULL)
break;
if (lookup_create_item(e->sid) == NULL)
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) {
if (root_item) {
......@@ -484,9 +552,19 @@ static int read_pstree_image(void)
break;
for (i = 0; i < e->n_threads; i++) {
struct pid *node;
pi->threads[i].real = -1;
pi->threads[i].virt = e->threads[i];
max_pid = max((int)e->threads[i], max_pid);
pi->threads[i].state = TASK_THREAD;
if (i == 0)
continue; /* A thread leader is in a tree already */
node = lookup_create_pid(pi->threads[i].virt, &pi->threads[i]);
BUG_ON(node == NULL);
if (node != &pi->threads[i]) {
pr_err("Unexpected task %d in a tree %d\n", e->threads[i], i);
return -1;
}
}
task_entries->nr_threads += e->n_threads;
......
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