[CRIU] [PATCH v3 28/55] proc_parse: Implement collect_pid_status()
Kirill Tkhai
ktkhai at virtuozzo.com
Mon Apr 10 01:19:42 PDT 2017
Implement helper, which allows to collect NSpids in
the whole pid hierarhy (i.e., when pid->level > 1).
Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
---
criu/include/proc_parse.h | 11 +++++
criu/proc_parse.c | 100 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 111 insertions(+)
diff --git a/criu/include/proc_parse.h b/criu/include/proc_parse.h
index 13b710926..883360484 100644
--- a/criu/include/proc_parse.h
+++ b/criu/include/proc_parse.h
@@ -64,6 +64,14 @@ struct proc_pid_stat {
int exit_code;
};
+
+struct proc_pid_status {
+ uint32_t *nspid;
+ uint32_t *nspgid;
+ uint32_t *nssid;
+ size_t n_levels;
+};
+
struct seccomp_info {
SeccompFilter filter;
int id;
@@ -105,4 +113,7 @@ extern int parse_threads(int pid, struct pid ***_t, int *_n);
int parse_children(pid_t pid, pid_t **_c, int *_n);
+extern void free_pid_status(struct proc_pid_status *st);
+extern int collect_pid_status(pid_t tgid, pid_t tid, unsigned skip, struct proc_pid_status *st);
+
#endif /* __CR_PROC_PARSE_H__ */
diff --git a/criu/proc_parse.c b/criu/proc_parse.c
index 84a8f9ea1..4201fd106 100644
--- a/criu/proc_parse.c
+++ b/criu/proc_parse.c
@@ -2579,3 +2579,103 @@ int parse_children(pid_t pid, pid_t **_c, int *_n)
return -1;
}
+static int get_ns_pid(char *str, unsigned skip, uint32_t **pid, size_t *n_level)
+{
+ int nr, size;
+ pid_t val;
+
+ *pid = NULL;
+ nr = 0;
+ while (sscanf(str, "%d%n", &val, &size) == 1) {
+ str += size;
+ if (skip > 0) {
+ skip--;
+ continue;
+ }
+ nr++;
+ *pid = xrealloc(*pid, nr * sizeof(uint32_t));
+ if (!*pid) {
+ pr_err("Can't alloc memory\n");
+ return -1;
+ }
+ (*pid)[nr - 1] = val;
+ }
+
+ BUG_ON((*n_level && nr != *n_level) || nr < 1);
+ *n_level = nr;
+
+ return 0;
+}
+
+static void init_proc_pid_status(struct proc_pid_status *st)
+{
+ st->nspid = st->nspgid = st->nssid = NULL;
+ st->n_levels = 0;
+}
+
+int collect_pid_status(pid_t tgid, pid_t tid, unsigned skip, struct proc_pid_status *st)
+{
+ int nr_dump;
+ struct bfd f;
+ char *str;
+
+ if (tid == -1) {
+ f.fd = open_proc(tgid, "status");
+ nr_dump = 3;
+ } else {
+ f.fd = open_proc(tgid, "task/%d/status", tid);
+ nr_dump = 1; /* Threads don't need pgid and sid */
+ }
+ if (f.fd < 0)
+ return -1;
+ if (bfdopenr(&f))
+ return -1;
+ init_proc_pid_status(st);
+
+ while (nr_dump) {
+ str = breadline(&f);
+ if (str == NULL)
+ break;
+ if (IS_ERR(str))
+ goto out;
+
+ if (!strncmp(str, "NSpid:", 6)) {
+ if (get_ns_pid(str + 6, skip, &st->nspid, &st->n_levels) < 0) {
+ pr_err("Can't get NSpid\n");
+ goto out;
+ }
+ nr_dump--;
+ }
+
+ if (!strncmp(str, "NSpgid:", 7) && tid == -1) {
+ if (get_ns_pid(str + 7, skip, &st->nspgid, &st->n_levels) < 0) {
+ pr_err("Can't get NSpgid\n");
+ goto out;
+ }
+ nr_dump--;
+ }
+
+ if (!strncmp(str, "NSsid:", 6) && tid == -1) {
+ if (get_ns_pid(str + 6, skip, &st->nssid, &st->n_levels) < 0) {
+ pr_err("Can't get NSsid\n");
+ goto out;
+ }
+ nr_dump--;
+ }
+ }
+out:
+ bclose(&f);
+ if (nr_dump) {
+ pr_err("Can't get task's NS pids\n");
+ return -1;
+ }
+ return 0;
+}
+
+void free_pid_status(struct proc_pid_status *st)
+{
+ xfree(st->nspid);
+ xfree(st->nspgid);
+ xfree(st->nssid);
+ init_proc_pid_status(st);
+}
More information about the CRIU
mailing list