[CRIU] [PATCH 02/10] pstree: make helper items for pgid replaceable
Pavel Tikhomirov
ptikhomirov at virtuozzo.com
Tue Jul 4 12:08:01 MSK 2017
If process group leader pid level is > than our pid level we will
see only part of a group leaders's pid in /proc/pid/status in NSpgid
field. So if we add such a pgid first with lookup_create_pid, adding
the leader later would fail.
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
criu/include/pstree.h | 2 ++
criu/pstree.c | 60 +++++++++++++++++++++++++++++++++++++++++++++------
2 files changed, 55 insertions(+), 7 deletions(-)
diff --git a/criu/include/pstree.h b/criu/include/pstree.h
index a3d8c31..3817694 100644
--- a/criu/include/pstree.h
+++ b/criu/include/pstree.h
@@ -31,6 +31,8 @@ struct pstree_item {
};
struct ns_id *user_ns;
struct ns_id *pid_for_children_ns;
+
+ int replaceable;
};
#define vpid(item) (item->pid->ns[0].virt)
diff --git a/criu/pstree.c b/criu/pstree.c
index a2744c4..e712dd3 100644
--- a/criu/pstree.c
+++ b/criu/pstree.c
@@ -530,7 +530,7 @@ static struct pid *find_pid_or_place_in_hier(struct rb_node **root, pid_t pid, i
* it is not there yet. If pid_node isn't set, pstree_item
* is inserted.
*/
-static struct pid *lookup_create_pid(pid_t *pid, int level, struct pid *pid_node, int ns_id)
+static struct pid *__lookup_create_pid(pid_t *pid, int level, struct pid *pid_node, int ns_id, int replaceable)
{
struct rb_node **new = NULL, *parent = NULL;
struct pid *found;
@@ -565,16 +565,42 @@ static struct pid *lookup_create_pid(pid_t *pid, int level, struct pid *pid_node
if (item == NULL)
return NULL;
+ if (replaceable)
+ item->replaceable = true;
+
for (i = 0; i < level; i++)
item->pid->ns[i].virt = pid[i];
pid_node = item->pid;
}
for (i = level-1; i >= 0; i--) {
+
+again:
found = find_pid_or_place_in_hier(&ns->pid.rb_root.rb_node, pid[i], i, &parent, &new);
if (found) {
- pr_err("pid is already linked\n");
- return NULL;
+ if (found->item->replaceable) {
+ int j;
+ struct ns_id *tmp = ns;
+
+ pr_info("%d: Removing old (short cut) pid on all lower levels", found->ns[0].virt);
+ for (j = i; j >= 0; j--) {
+ BUG_ON(pid_node->ns[j].virt != found->ns[j].virt);
+ rb_erase(&found->ns[j].node, &tmp->pid.rb_root);
+ tmp = tmp->parent;
+ if (!tmp && j) {
+ pr_err("tmp ns has no parent\n");
+ return NULL;
+ }
+ }
+ /*
+ * Just leave these pid and found item unlinked and unused,
+ * it seems that we can't do anything with it here.
+ */
+ goto again;
+ } else {
+ pr_err("pid is already linked\n");
+ return NULL;
+ }
}
if (!pid[i]) {
pr_err("Zero pid level\n");
@@ -590,6 +616,11 @@ static struct pid *lookup_create_pid(pid_t *pid, int level, struct pid *pid_node
return pid_node;
}
+static struct pid *lookup_create_pid(pid_t *pid, int level, struct pid *pid_node, int ns_id)
+{
+ return __lookup_create_pid(pid, level, pid_node, ns_id, false);
+}
+
void pstree_insert_pid(struct pid *pid_node, uint32_t ns_id)
{
struct pid* n;
@@ -605,11 +636,11 @@ void pstree_insert_pid(struct pid *pid_node, uint32_t ns_id)
BUG_ON(n != pid_node);
}
-struct pstree_item *lookup_create_item(pid_t *pid, int level, uint32_t ns_id)
+struct pstree_item *__lookup_create_item(pid_t *pid, int level, uint32_t ns_id, int replaceable)
{
struct pid *node;;
- node = lookup_create_pid(pid, level, NULL, ns_id);
+ node = __lookup_create_pid(pid, level, NULL, ns_id, replaceable);
if (!node)
return NULL;
BUG_ON(node->state == TASK_THREAD);
@@ -617,6 +648,16 @@ struct pstree_item *lookup_create_item(pid_t *pid, int level, uint32_t ns_id)
return node->item;
}
+struct pstree_item *lookup_create_item(pid_t *pid, int level, uint32_t ns_id)
+{
+ return __lookup_create_item(pid, level, ns_id, false);
+}
+
+struct pstree_item *lookup_replaceable_item(pid_t *pid, int level, uint32_t ns_id)
+{
+ return __lookup_create_item(pid, level, ns_id, true);
+}
+
struct pid *__pstree_pid_by_virt(struct ns_id *ns, pid_t pid)
{
struct rb_node *node = ns->pid.rb_root.rb_node;
@@ -821,10 +862,15 @@ static int read_pstree_image(pid_t *pid_max)
* be initialized when we meet PstreeEntry with this pid or
* we will create helpers for them.
*/
- if (lookup_create_item((pid_t *)e->ns_pgid, e->n_ns_pgid, ids->pid_ns_id) == NULL)
- break;
if (lookup_create_item((pid_t *)e->ns_sid, e->n_ns_sid, ids->pid_ns_id) == NULL)
break;
+ /*
+ * Pgid can be cut by level of current task
+ * when process group leader is in several
+ * nested pidns'es so mark it as replaceable.
+ */
+ if (lookup_replaceable_item((pid_t *)e->ns_pgid, e->n_ns_pgid, ids->pid_ns_id) == NULL)
+ break;
BUG_ON(vpid(pi) != e->ns_pid[0]);
if (e->ns_pid[0] > *pid_max)
--
2.9.4
More information about the CRIU
mailing list