[CRIU] [PATCH v2 31/57] proc_parse: Implement collect_pid_status()

Kirill Tkhai ktkhai at virtuozzo.com
Mon Apr 10 01:02:16 PDT 2017


On 07.04.2017 08:16, Andrei Vagin wrote:
> 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?

Hm. We use compel interface to call parse_pid_status():

int compel_wait_task(int pid, int ppid,
                int (*get_status)(int pid, struct seize_task_status *),
                struct seize_task_status *ss)

The interface works with struct seize_task_status. Can we change it to use
new type, containing status and ns_pids?
  
>> 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