[CRIU] Re: [PATCH cr 1/2] crtools: link pstree_item-s in a tree (v2)

Pavel Emelyanov xemul at parallels.com
Wed May 30 04:27:20 EDT 2012


> @@ -709,7 +697,10 @@ static int cr_show_all(struct cr_options *opts)
>  	}
>  
>  out:
> -	free_pstree(&pstree_list);
> +	list_for_each_entry(item, &pstree_list, list) {

list_for_each_entry_safe ?

> +		xfree(item->threads);
> +		xfree(item);
> +	}
>  	return ret;
>  }
>  

> @@ -707,11 +711,16 @@ static int restore_root_task(pid_t pid, struct cr_options *opts)
>  
>  out:
>  	if (ret < 0) {
> -		pr_err("Someone can't be restored\n");
>  		struct pstree_item *pi;
> +		pr_err("Someone can't be restored\n");
> +
> +		pi = root_item;
> +		while (pi) {
> +			if ((int) pi->pid > 0)

Why cast to int?
How can a pid be zero?

> +				kill(pi->pid, SIGKILL);
> +			pi = pstree_item_next(pi);
> +		}
>  
> -		list_for_each_entry(pi, &tasks, list)
> -			kill(pi->pid, SIGKILL);
>  		return 1;
>  	}
>  

> @@ -593,15 +611,16 @@ static void restore_pgid(void)
>  static int restore_task_with_children(void *_arg)
>  {
>  	struct cr_clone_arg *ca = _arg;
> +	struct pstree_item *child;
>  	pid_t pid;
> -	int ret, i;
> +	int ret;
>  	sigset_t blockmask;
>  
>  	close_safe(&ca->fd);
>  
>  	pid = getpid();
> -	if (ca->pid != pid) {
> -		pr_err("Pid %d do not match expected %d\n", pid, ca->pid);
> +	if (ca->item->pid != pid) {

Just a nitpick -- you can initialize me (next hunk) earlier and dereference it here.

> +		pr_err("Pid %d do not match expected %d\n", pid, ca->item->pid);
>  		exit(-1);
>  	}
>  
> @@ -609,14 +628,7 @@ static int restore_task_with_children(void *_arg)
>  	if (ret < 0)
>  		exit(1);
>  
> -	list_for_each_entry(me, &tasks, list)
> -		if (me->pid == pid)
> -			break;
> -
> -	if (me == list_entry(&tasks, struct pstree_item, list)) {
> -		pr_err("Pid %d not found in pstree image\n", pid);
> -		exit(1);
> -	}
> +	me = ca->item;
>  
>  	if (ca->clone_flags) {
>  		ret = prepare_namespace(me->pid, ca->clone_flags);

> @@ -178,7 +191,8 @@ static int prepare_shared(void)
>  	if (collect_inotify())
>  		return -1;
>  
> -	list_for_each_entry(pi, &tasks, list) {
> +	pi = root_item;
> +	while (pi) {
>  		ret = prepare_shmem_pid(pi->pid);
>  		if (ret < 0)
>  			break;
> @@ -186,6 +200,8 @@ static int prepare_shared(void)
>  		ret = prepare_fd_pid(pi->pid, pi->rst);
>  		if (ret < 0)
>  			break;
> +
> +		pi = pstree_item_next(pi);

It's perfectly worth having a

for_each_pstree_item(pi)

which is

for (pi = root_item; pi != NULL; pi = pstree_item_next(pi))

>  	}
>  
>  	mark_pipe_master();

> @@ -88,37 +89,50 @@ static int prepare_pstree(void)
>  
>  	while (1) {
>  		struct pstree_entry e;
> -		struct pstree_item *pi;
>  
>  		ret = read_img_eof(ps_fd, &e);
>  		if (ret <= 0)
>  			break;
>  
>  		ret = -1;
> -		pi = xmalloc(sizeof(*pi));
> +		pi = alloc_pstree_item();
>  		if (pi == NULL)
>  			break;
>  
>  		pi->rst = xzalloc(sizeof(*pi->rst));
> -		if (pi->rst == NULL)
> +		if (pi->rst == NULL) {
> +			xfree(pi);
>  			break;
> +		}
>  
>  		pi->pid = e.pid;
>  		pi->pgid = e.pgid;
>  		pi->sid = e.sid;
>  
> -		ret = -1;
> -		pi->nr_children = e.nr_children;
> -		pi->children = xmalloc(e.nr_children * sizeof(u32));
> -		if (!pi->children)
> -			break;
> +		if (e.ppid == 0) {
> +			BUG_ON(root_item);
> +			root_item = pi;
> +			pi->parent = NULL;
> +			INIT_LIST_HEAD(&pi->list);
> +		} else {
> +			struct pstree_item *item = root_item;

Taking into account the way the dump saves pstrees in the image, it's
worth having a fast path here -- cache the last seen parent locally and
don't search for the whole pstree for parent.

> +
> +			while (item) {
> +				if (item->pid == e.ppid)
> +					break;
> +				item = pstree_item_next(item);
> +			}
>  
> -		ret = read_img_buf(ps_fd, pi->children,
> -				e.nr_children * sizeof(u32));
> -		if (ret < 0)
> -			break;
> +			if (item == NULL) {
> +				pr_err("Can't find a parent for %d", pi->pid);
> +				xfree(pi);
> +				break;
> +			}
> +
> +			pi->parent = item;
> +			list_add(&pi->list, &item->children);
> +		}
>  
> -		ret = -1;
>  		pi->nr_threads = e.nr_threads;
>  		pi->threads = xmalloc(e.nr_threads * sizeof(u32));
>  		if (!pi->threads)

> @@ -180,16 +179,18 @@ struct pstree_item {
>  	struct list_head	list;

You put them in a tree and iterate this tree. Thus, why do we need a
separate plain list?

>  	pid_t			pid;		/* leader pid */
>  	struct pstree_item	*parent;
> +	struct list_head	children;	/* array of children */
>  	pid_t			pgid;
>  	pid_t			sid;
>  	int			state;		/* TASK_XXX constants */
> -	int			nr_children;	/* number of children */
>  	int			nr_threads;	/* number of threads */
>  	u32			*threads;	/* array of threads */
> -	u32			*children;	/* array of children */
>  	struct rst_info		*rst;
>  };
>  

> +struct pstree_item *alloc_pstree_item()
> +{
> +struct pstree_item *pstree_item_next(struct pstree_item *item)
>  {

Taking into account the fact you uses this in the restore also it's worth
moving the pstree items management into some generic .c file. E.g. util.c
or new pstree.c

Thanks,
Pavel


More information about the CRIU mailing list