[CRIU] [PATCH v5 15/42] pstree: Collect NSpid, NSsid and NStgid when possible
Kirill Tkhai
ktkhai at virtuozzo.com
Fri May 5 09:15:05 PDT 2017
v4: New
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
criu/cr-dump.c | 28 ++++++++++++++++---
criu/proc_parse.c | 78 +++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 99 insertions(+), 7 deletions(-)
diff --git a/criu/cr-dump.c b/criu/cr-dump.c
index 8ee1efa28..e971e153d 100644
--- a/criu/cr-dump.c
+++ b/criu/cr-dump.c
@@ -854,7 +854,16 @@ static int dump_task_thread(struct parasite_ctl *parasite_ctl,
pr_err("Can't dump thread for pid %d\n", pid);
goto err;
}
- tid->ns[0].virt = parasite_tid;
+
+ if (tid->ns[0].virt == -1)
+ tid->ns[0].virt = parasite_tid;
+ else {
+ /* It was collected in parse_pid_status() */
+ if (last_level_pid(tid) != parasite_tid) {
+ pr_err("Parasite and /proc/[pid]/status gave different tids\n");
+ goto err;
+ }
+ }
pstree_insert_pid(tid, item->ids->pid_ns_id);
@@ -1324,9 +1333,20 @@ static int dump_one_task(struct pstree_item *item)
goto err_cure_imgset;
}
- vpid(item) = misc.pid;
- vsid(item) = misc.sid;
- vpgid(item) = misc.pgid;
+ if (vpid(item) == -1) {
+ vpid(item) = misc.pid;
+ vsid(item) = misc.sid;
+ vpgid(item) = misc.pgid;
+ } else {
+ /* They were collected in parse_pid_status() */
+ if (last_level_pid(item->pid) != misc.pid ||
+ last_level_pid(item->sid) != misc.sid ||
+ last_level_pid(item->pgid) != misc.pgid) {
+ pr_err("Parasite and /proc/[pid]/status gave different pids\n");
+ goto err;
+ }
+ }
+
pstree_insert_pid(item->pid, item->ids->pid_ns_id);
pr_info("sid=%d pgid=%d pid=%d\n", vsid(item), vpgid(item), vpid(item));
diff --git a/criu/proc_parse.c b/criu/proc_parse.c
index d4f123904..072f65543 100644
--- a/criu/proc_parse.c
+++ b/criu/proc_parse.c
@@ -993,6 +993,44 @@ static int cap_parse(char *str, unsigned int *res)
return 0;
}
+static int get_ns_pid(char *str, struct pid **pid_ptr)
+{
+ pid_t pid[MAX_NS_NESTING];
+ int level, size, skip;
+ pid_t val;
+
+ skip = pid_ns_root_off();
+
+ level = 0;
+ while (sscanf(str, "%d%n", &val, &size) == 1) {
+ if (level == MAX_NS_NESTING) {
+ pr_err("Too nested hierarchy\n");
+ return -1;
+ }
+ str += size;
+ if (skip > 0) {
+ skip--;
+ continue;
+ }
+ pid[level++] = val;
+ }
+
+ if (level == 0) {
+ pr_err("Line can't be collected\n");
+ return -1;
+ }
+
+ (*pid_ptr) = xrealloc(*pid_ptr, PID_SIZE(level));
+ if (!*pid_ptr)
+ return -1;
+
+ (*pid_ptr)->level = level;
+ while (level-- > 0)
+ (*pid_ptr)->ns[level].virt = pid[level];
+
+ return 0;
+}
+
int parse_pid_status(pid_t pid, struct seize_task_status *ss,
struct pstree_item *item, struct pid **thread)
{
@@ -1002,6 +1040,7 @@ int parse_pid_status(pid_t pid, struct seize_task_status *ss,
int ret = -1;
char *str;
bool parsed_seccomp = false;
+ int expected_done;
f.fd = open_proc(pid, "status");
if (f.fd < 0)
@@ -1013,7 +1052,7 @@ int parse_pid_status(pid_t pid, struct seize_task_status *ss,
if (bfdopenr(&f))
return -1;
- while (done < 12) {
+ while (done < 14) {
str = breadline(&f);
if (str == NULL)
break;
@@ -1113,10 +1152,43 @@ int parse_pid_status(pid_t pid, struct seize_task_status *ss,
done++;
continue;
}
+ if (!strncmp(str, "NSpid:", 6)) {
+ if (get_ns_pid(str + 6, thread ? : &item->pid) < 0) {
+ pr_err("Can't get NSpid\n");
+ goto err_parse;
+ }
+ done++;
+ continue;
+ }
+ if (!strncmp(str, "NSpgid:", 7) && !thread) {
+ if (get_ns_pid(str + 7, &item->pgid) < 0) {
+ pr_err("Can't get NSpgid\n");
+ goto err_parse;
+ }
+ done++;
+ continue;
+ }
+ if (!strncmp(str, "NSsid:", 6) && !thread) {
+ if (get_ns_pid(str + 6, &item->sid) < 0) {
+ pr_err("Can't get NSsid\n");
+ goto err_parse;
+ }
+ done++;
+ continue;
+ }
+ }
+
+ if (!thread && (item->pid->level != item->sid->level ||
+ item->pid->level != item->pgid->level)) {
+ pr_err("Level mismatch\n");
+ goto err_parse;
}
- /* seccomp is optional */
- if (done >= 11 || (done == 10 && !parsed_seccomp))
+ /* seccomp and nspids are optional */
+ expected_done = (parsed_seccomp ? 11 : 10);
+ if (kdat.has_nspid)
+ expected_done += (thread ? 1 : 3);
+ if (done == expected_done)
ret = 0;
err_parse:
More information about the CRIU
mailing list