[CRIU] Re: [PATCH 3/3] fifo: Add checkpoint restore for fifos

Pavel Emelyanov xemul at parallels.com
Wed Jun 27 13:24:58 EDT 2012


On 06/26/2012 06:49 PM, Cyrill Gorcunov wrote:
> 
> Checpoint and restore of fifo is similar to
> pipes c/r except the pipe end-points are named
> file.
> 
> Because the fifo has a name we use regular files
> facility for fifo path c/r.
> 
> Still there is a trick used to "open" fifo:
> the opening procedure migh sleep if a fifo's peer
> is not yet opened, so before doing a real open
> we yield a fake open procedure (with O_RDWR flag)
> which prevents us from sleeping even if peer
> is not yet ready.
> 
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
>  Makefile            |    1 +
>  cr-dump.c           |    9 ++-
>  cr-restore.c        |    4 +
>  cr-show.c           |   40 +++++++---
>  crtools.c           |    2 +
>  fifo.c              |  212 +++++++++++++++++++++++++++++++++++++++++++++++++++
>  files-reg.c         |    8 --
>  include/crtools.h   |    4 +
>  include/fifo.h      |   10 +++
>  include/files-reg.h |   10 +++
>  include/image.h     |    8 ++
>  11 files changed, 288 insertions(+), 20 deletions(-)
>  create mode 100644 fifo.c
>  create mode 100644 include/fifo.h
> 

> +static int dump_one_fifo(int lfd, u32 id, const struct fd_parms *p)
> +{
> +	int img = fdset_fd(glob_fdset, CR_FD_FIFO);
> +	struct fifo_entry e;
> +
> +	/*
> +	 * It's a trick here, we use regular files dumping
> +	 * code to save path to a fifo, then we reuse it
> +	 * on restore.
> +	 */
> +	if (dump_one_reg_file(lfd, id, p))
> +		return -1;
> +
> +	pr_info("Dumping fifo %d with id %#x pipe_id %#x\n",
> +		lfd, id, (u32)p->stat.st_ino);
> +
> +	e.id		= id;
> +	e.pipe_id	= p->stat.st_ino;

Why do we need two IDs for fifo? Isn't one enough?

> +	if (write_img(img, &e) < 0)
> +		return -1;
> +
> +	return dump_one_pipe_data(CR_FD_FIFO_DATA, lfd, id, p);
> +}

> +static int open_fifo_fd(struct file_desc *d)
> +{
> +	struct fifo_info *info = container_of(d, struct fifo_info, d);
> +	int new_fifo, fake_fifo = -1;
> +
> +	struct reg_file_info *rfi;
> +	struct file_desc *rd;
> +
> +	pr_info("\t\tCreating fifo pipe_id=%#x id=%#x\n",
> +		info->fe.pipe_id, info->fe.id);
> +
> +	rd = find_file_desc_raw(FDINFO_REG, info->fe.id);
> +	if (!rd) {
> +		pr_perror("Can't find regfile for fifo %#x\n", info->fe.id);
> +		return -1;
> +	}
> +
> +	rfi = container_of(rd, struct reg_file_info, d);
> +	if (rfi->remap_path) {
> +		if (link(rfi->remap_path, rfi->path) < 0) {
> +			pr_perror("Can't link %s -> %s\n",
> +				  rfi->remap_path, rfi->path);
> +			return -1;
> +		}
> +	} else {
> +		if (!rfi->path) {
> +			pr_err("Nil path found on regfile %#x for fifo %#x\n",
> +			       rfi->rfe.id, info->fe.id);
> +			return -1;
> +		}
> +	}
> +
> +	/*
> +	 * The fifos (except read-write fifos) do wait until
> +	 * another pipe-end get connected, so to be able to
> +	 * proceed the restoration procedure we open a fake
> +	 * fifo here.
> +	 */
> +	fake_fifo = open(rfi->path, O_RDWR);
> +	if (fake_fifo < 0) {
> +		pr_perror("Can't open fake fifo %#08x [%s]",
> +			  info->fe.id, rfi->path);
> +		return -1;
> +	}
> +
> +	new_fifo = open(rfi->path, rfi->rfe.flags);
> +	if (new_fifo < 0) {
> +		pr_perror("Can't open fifo %#08x [%s]",
> +			  info->fe.id, rfi->path);
> +		goto err_close_fake;
> +	}

Can the
  open(O_RDWR) + open(O_xxx)
be replaced with 
  open(O_xxx | O_NONBLOCK) + fcntl(~O_NONBLOCK);
?

This will allow to gracefully fix the comment labeled A: below.

> +
> +	if (restore_pipe_data(CR_FD_FIFO_DATA, fake_fifo, info->fe.id,
> +			      info->bytes, info->off))
> +		goto err_unlink;

Multiple fifo data restoration?

> +	if (rfi->remap_path)
> +		unlink(rfi->path);
> +
> +	if (restore_fown(new_fifo, &rfi->rfe.fown) < 0) {
> +		pr_perror("Can't restore owner on fifo %#08x",
> +			  info->fe.id);
> +		goto err_close_new;
> +	}

A: You didn't merge it with the open_fe_fd :\

> +err_close_fake:
> +	close_safe(&fake_fifo);
> +	return new_fifo;
> +
> +err_close_new:
> +	close_safe(&new_fifo);
> +	goto err_close_fake;
> +
> +err_unlink:
> +	if (rfi->remap_path)
> +		unlink(rfi->path);
> +	goto err_close_new;
> +}



More information about the CRIU mailing list