[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