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

Pavel Emelyanov xemul at parallels.com
Tue Jun 26 05:37:36 EDT 2012


On 06/26/2012 12:07 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.
> 
> Other than that -- nothing special.

The patch got corrupted. Use attach.

> +static int dump_one_fifo(int lfd, u32 id, const struct fd_parms *p)
> +{
> +       int img_data = fdset_fd(glob_fdset, CR_FD_FIFO_DATA);
> +       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;

Good. But the dump_ghost_file on unlinked fifo will try to copy out
its contents. Not good.

> +       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;
> +
> +       if (write_img(img, &e) < 0)
> +               return -1;
> +
> +       return dump_one_pipe_data(img_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, img = -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->path) {
> +               pr_err("Nil path found on regfile %#x for fifo %#x\n",
> +                      rfi->rfe.id, info->fe.id);
> +               return -1;
> +       }
> +
> +       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;
> +               }
> +       }
> +
> +       /*
> +        * 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;
> +       }
> +
> +       img = open_image_ro(CR_FD_FIFO_DATA);
> +       if (img < 0)
> +               goto err_close_new;
> +
> +       if (restore_pipe_data(img, fake_fifo, info->fe.id,
> +                             info->bytes, info->off))
> +               goto err_unlink;
> +
> +       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;
> +       }

Most of the above is done by the open_fe_fd fn. Try to merge.

> +err_close_fake:
> +       close_safe(&img);
> +       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;
> +}

> +static int handle_fifo_data(void)
> +{
> +       int img, ret;
> +
> +       img = open_image_ro(CR_FD_FIFO_DATA);
> +       if (img < 0)
> +               return -1;
> +
> +       while (1) {
> +               struct pipe_data_entry pde;
> +               struct fifo_info *info;
> +
> +               ret = read_img_eof(img, &pde);
> +               if (ret <= 0)
> +                       break;
> +
> +               list_for_each_entry(info, &fifo_head, list) {
> +                       if (info->fe.pipe_id != pde.pipe_id)
> +                               continue;
> +
> +                       info->off       = lseek(img, 0, SEEK_CUR) + pde.off;
> +                       info->bytes     = pde.bytes;
> +
> +                       lseek(img, pde.bytes + pde.off, SEEK_CUR);
> +                       break;
> +               }
> +       }

This looks like handle_pipes_data.

> +       close(img);
> +       return ret;
> +}


More information about the CRIU mailing list