[CRIU] [PATCH v3 32/55] pstree: Dump and restore NSpid, NSsid etc

Kirill Tkhai ktkhai at virtuozzo.com
Wed Apr 26 03:41:13 PDT 2017


On 10.04.2017 11:20, Kirill Tkhai wrote:
> Use new added fields to store pids in the whole ns hierarhy.
> 
> Signed-off-by: Kirill Tkhai <ktkhai at virtuozzo.com>
> ---
>  criu/pstree.c |  176 ++++++++++++++++++++++++++++++++++++++++++++-------------
>  1 file changed, 135 insertions(+), 41 deletions(-)
> 
> diff --git a/criu/pstree.c b/criu/pstree.c
> index 653f39920..55e5fc99e 100644
> --- a/criu/pstree.c
> +++ b/criu/pstree.c
> @@ -289,11 +289,43 @@ int preorder_pstree_traversal(struct pstree_item *item, int (*f)(struct pstree_i
>  	return 0;
>  }
>  
> +static void free_pstree_entry(PstreeEntry *e)
> +{
> +	int i;
> +
> +	xfree(e->ns_pid);
> +	xfree(e->ns_pgid);
> +	xfree(e->ns_sid);
> +
> +	if (e->tids) {
> +		for (i = 0; i < e->n_tids; i++) {
> +			if (e->tids[i]) {
> +				xfree(e->tids[i]->tid);
> +				xfree(e->tids[i]);
> +			}
> +		}
> +		xfree(e->tids);
> +	}
> +}
> +
> +static int plant_ns_xid(uint32_t **ns_xid, size_t *n_ns_xid, int level, struct pid *xid)
> +{
> +	int i;
> +
> +	*ns_xid = xmalloc(level * sizeof(uint32_t));
> +	if (!*ns_xid)
> +		return -1;
> +	for (i = 0; i < level; i++)
> +			(*ns_xid)[i] = xid->ns[i].virt;
> +	*n_ns_xid = level;
> +	return 0;
> +}
> +
>  int dump_pstree(struct pstree_item *root_item)
>  {
>  	struct pstree_item *item = root_item;
>  	PstreeEntry e = PSTREE_ENTRY__INIT;
> -	int ret = -1, i;
> +	int ret = -1, i, level;
>  	struct cr_img *img;
>  
>  	pr_info("\n");
> @@ -323,33 +355,41 @@ int dump_pstree(struct pstree_item *root_item)
>  
>  	for_each_pstree_item(item) {
>  		pr_info("Process: %d(%d)\n", vpid(item), item->pid->real);
> +		level = item->pid->level;
>  
> -		e.pid		= vpid(item);
>  		e.ppid		= item->parent ? vpid(item->parent) : 0;
> -		e.pgid		= item->pgid->ns[0].virt;
> -		e.sid		= item->sid->ns[0].virt;
> -		e.n_threads	= item->nr_threads;
> -		e.has_pid	= true;
> -		e.has_pgid	= true;
> -		e.has_sid	= true;
> -
> -		e.threads = xmalloc(sizeof(e.threads[0]) * e.n_threads);
> -		if (!e.threads)
> -			goto err;
> -
> -		for (i = 0; i < item->nr_threads; i++)
> -			e.threads[i] = item->threads[i]->ns[0].virt;
>  
> +		if (plant_ns_xid(&e.ns_pid,  &e.n_ns_pid,  level, item->pid)  < 0 ||
> +		    plant_ns_xid(&e.ns_pgid, &e.n_ns_pgid, level, item->pgid) < 0 ||
> +		    plant_ns_xid(&e.ns_sid,  &e.n_ns_sid,  level, item->sid)  < 0)
> +			goto err;
> +		e.n_tids	= item->nr_threads;
> +		if (e.n_tids) {
> +			e.tids	= xzalloc(e.n_tids * sizeof(NsTid *));
> +			if (!e.tids)
> +				goto err;
> +			for (i = 0; i < e.n_tids; i++) {
> +				e.tids[i] = xzalloc(sizeof(NsTid));
> +				if (!e.tids[i])
> +					goto err;
> +				ns_tid__init(e.tids[i]);
> +				e.tids[i]->n_tid = level;
> +				if (plant_ns_xid(&e.tids[i]->tid, &e.tids[i]->n_tid,
> +						 level, item->threads[i])  < 0)
> +					goto err;
> +			}
> +		}
>  		ret = pb_write_one(img, &e, PB_PSTREE);
> -		xfree(e.threads);
> -
>  		if (ret)
>  			goto err;
> +		free_pstree_entry(&e);
> +		pstree_entry__init(&e);
>  	}
>  	ret = 0;
>  
>  err:
>  	pr_info("----------------------------------------\n");
> +	free_pstree_entry(&e);
>  	close_image(img);
>  	return ret;
>  }
> @@ -586,11 +626,62 @@ static int read_pstree_ids(pid_t pid, TaskKobjIdsEntry **ids)
>  	return ret;
>  }
>  
> +static int read_one_pstree(struct cr_img *img, PstreeEntry **ret_e)
> +{
> +	PstreeEntry *e;
> +	int i, ret;
> +
> +	ret = pb_read_one_eof(img, ret_e, PB_PSTREE);
> +	if (ret <= 0)
> +		return ret;
> +	e = *ret_e;
> +	if ((!e->has_pid && !e->n_ns_pid) || (!e->has_pgid && !e->n_ns_pgid) ||
> +	    (!e->has_sid && !e->n_ns_sid) || (e->n_threads && e->n_tids))
> +		goto err;
> +	/* Assign ns_pid, ns_pgid and ns_sid if here is old format image */
> +#define ASSIGN_NSXID_IF_NEED(name, source)		\
> +	if (!e->n_##name) {				\
> +		e->n_##name = 1;			\
> +		e->name = xmalloc(sizeof(uint32_t));	\
> +		if (!e->name)				\
> +			goto err;			\
> +		e->name[0] = e->source;			\
> +	}
> +	ASSIGN_NSXID_IF_NEED(ns_pid, pid);
> +	ASSIGN_NSXID_IF_NEED(ns_pgid, pgid);
> +	ASSIGN_NSXID_IF_NEED(ns_sid, sid);
> +#undef ASSIGN_NSXID_IF_NEED
> +
> +	/* Assign tids if here is old format image */
> +	if (!e->n_tids) {
> +		e->n_tids = e->n_threads;
> +		e->tids = xzalloc(e->n_tids * sizeof(NsTid *));
> +		if (!e->tids)
> +			goto err;
> +		for (i = 0; i < e->n_tids; i++) {
> +			e->tids[i] = xzalloc(sizeof(NsTid));
> +			if (!e->tids[i])
> +				goto err;
> +			ns_tid__init(e->tids[i]);
> +			e->tids[i]->n_tid = 1;
> +			e->tids[i]->tid = xmalloc(sizeof(uint32_t));
> +			if (!e->tids[i]->tid)
> +				goto err;
> +			e->tids[i]->tid[0] = e->threads[i];
> +		}
> +	}
> +
> +	return 1;
> +err:
> +	pr_err("Error of reading pstree\n");
> +	return -1;
> +}
> +
>  static int read_pstree_image(pid_t *pid_max)
>  {
>  	struct pstree_item *pi, *parent;
>  	TaskKobjIdsEntry *ids;
> -	int ret = 0, i;
> +	int ret = 0, i, k;
>  	struct cr_img *img;
>  	struct pid *pid;
>  
> @@ -603,11 +694,11 @@ static int read_pstree_image(pid_t *pid_max)
>  	while (1) {
>  		PstreeEntry *e;
>  
> -		ret = pb_read_one_eof(img, &e, PB_PSTREE);
> +		ret = read_one_pstree(img, &e);
>  		if (ret <= 0)
>  			break;
>  
> -		ret = read_pstree_ids(e->pid, &ids);
> +		ret = read_pstree_ids(e->ns_pid[0], &ids);
>  		if (ret < 0)
>  			break;
>  
> @@ -617,7 +708,7 @@ static int read_pstree_image(pid_t *pid_max)
>  		if (e->ppid) {
>  			pid = pstree_pid_by_virt(e->ppid);
>  			if (!pid || pid->state == TASK_UNDEF || pid->state == TASK_THREAD) {
> -				pr_err("Can't find a parent for %d\n", e->pid);
> +				pr_err("Can't find a parent for %d\n", e->ns_pid[0]);
>  				pstree_entry__free_unpacked(e, NULL);
>  				break;
>  			}
> @@ -642,7 +733,7 @@ static int read_pstree_image(pid_t *pid_max)
>  			break;
>  		}
>  
> -		pi = lookup_create_item((pid_t *)&e->pid, 1, ids->pid_ns_id);
> +		pi = lookup_create_item((pid_t *)e->ns_pid, e->n_ns_pid, ids->pid_ns_id);
>  		if (pi == NULL)
>  			break;
>  		BUG_ON(pi->pid->state != TASK_UNDEF);
> @@ -655,26 +746,28 @@ static int read_pstree_image(pid_t *pid_max)
>  		 * be initialized when we meet PstreeEntry with this pid or
>  		 * we will create helpers for them.
>  		 */
> -		if (lookup_create_item((pid_t *)&e->pgid, 1, ids->pid_ns_id) == NULL)
> +		if (lookup_create_item((pid_t *)e->ns_pgid, e->n_ns_pgid, ids->pid_ns_id) == NULL)
>  			break;
> -		if (lookup_create_item((pid_t *)&e->sid, 1, ids->pid_ns_id) == NULL)
> +		if (lookup_create_item((pid_t *)e->ns_sid, e->n_ns_sid, ids->pid_ns_id) == NULL)
>  			break;
>  
> -		pi->pid->ns[0].virt = e->pid;
> -		if (e->pid > *pid_max)
> -			*pid_max = e->pid;
> -		pi->pgid->ns[0].virt = e->pgid;
> -		if (e->pgid > *pid_max)
> -			*pid_max = e->pgid;
> -		pi->sid->ns[0].virt = e->sid;
> -		if (e->sid > *pid_max)
> -			*pid_max = e->sid;
> +		BUG_ON(pi->pid->ns[0].virt != e->ns_pid[0]);
> +		if (e->ns_pid[0] > *pid_max)
> +			*pid_max = e->ns_pid[0];
> +		for (i = 0; i < pi->pgid->level; i++)
> +			pi->pgid->ns[i].virt = e->ns_pgid[0];

Here must be ns_pgid[i]

> +		if (e->ns_pgid[0] > *pid_max)
> +			*pid_max = e->ns_pgid[0];
> +		for (i = 0; i < pi->sid->level; i++)
> +			pi->sid->ns[i].virt = e->ns_sid[i];
> +		if (e->ns_sid[0] > *pid_max)
> +			*pid_max = e->ns_sid[0];
>  		pi->pid->state = TASK_ALIVE;
>  
>  		if (!parent) {
>  			if (root_item) {
>  				pr_err("Parent missed on non-root task "
> -				       "with pid %d, image corruption!\n", e->pid);
> +				       "with pid %d, image corruption!\n", e->ns_pid[0]);
>  				goto err;
>  			}
>  			root_item = pi;
> @@ -684,33 +777,34 @@ static int read_pstree_image(pid_t *pid_max)
>  			list_add(&pi->sibling, &parent->children);
>  		}
>  
> -		pi->nr_threads = e->n_threads;
> -		pi->threads = xzalloc(e->n_threads * sizeof(struct pid *));
> +		pi->nr_threads = e->n_tids;
> +		pi->threads = xzalloc(e->n_tids * sizeof(struct pid *));
>  		if (!pi->threads)
>  			break;
>  
> -		for (i = 0; i < e->n_threads; i++) {
> +		for (i = 0; i < e->n_tids; i++) {
>  			struct pid *node;
>  			pi->threads[i] = xmalloc(sizeof(struct pid) + (pi->pid->level-1) * sizeof(node->ns[0]));
>  			if (!pi->threads)
>  				goto err;
>  			pi->threads[i]->real = -1;
>  			pi->threads[i]->level = pi->pid->level;
> -			pi->threads[i]->ns[0].virt = e->threads[i];
> +			for (k = 0; k < pi->pid->level; k++)
> +				pi->threads[i]->ns[k].virt = e->tids[i]->tid[k];
>  			pi->threads[i]->state = TASK_THREAD;
>  			pi->threads[i]->item = NULL;
>  			if (i == 0)
>  				continue; /* A thread leader is in a tree already */
> -			node = lookup_create_pid((pid_t *)&pi->threads[i]->ns[0].virt, 1, pi->threads[i], ids->pid_ns_id);
> +			node = lookup_create_pid((pid_t *)e->tids[i]->tid, e->tids[i]->n_tid, pi->threads[i], ids->pid_ns_id);
>  
>  			BUG_ON(node == NULL);
>  			if (node != pi->threads[i]) {
> -				pr_err("Unexpected task %d in a tree %d\n", e->threads[i], i);
> +				pr_err("Unexpected task %d in a tree %d\n", e->tids[i]->tid[0], i);
>  				return -1;
>  			}
>  		}
>  
> -		task_entries->nr_threads += e->n_threads;
> +		task_entries->nr_threads += e->n_tids;
>  		task_entries->nr_tasks++;
>  
>  		pstree_entry__free_unpacked(e, NULL);
> 


More information about the CRIU mailing list