[CRIU] [PATCH v2 31/57] proc_parse: Implement collect_pid_status()
Andrei Vagin
avagin at virtuozzo.com
Thu Apr 6 22:16:38 PDT 2017
On Tue, Mar 28, 2017 at 06:38:50PM +0300, Kirill Tkhai wrote:
> Implement helper, which allows to collect NSpids in
> the whole pid hierarhy (i.e., when pid->level > 1).
>
We already have parse_pid_status(). Can we read /proc/pid/status for
each process only once?
> 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 13b71092..88336048 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 84a8f9ea..4201fd10 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