[CRIU] [PATCH] Make restored processes inherit file descriptors from criu
Pavel Emelyanov
xemul at parallels.com
Wed Nov 26 11:27:19 PST 2014
Hi, Saied.
I really hope you didn't plan this for 1.4. It's in several days
and the repo is in feature freeze.
> diff --git a/files-reg.c b/files-reg.c
> index 20b50a0..bfd1896 100644
> --- a/files-reg.c
> +++ b/files-reg.c
> @@ -962,6 +962,14 @@ int open_path(struct file_desc *d,
> }
>
> mntns_root = mntns_get_root_by_mnt_id(rfi->rfe->mnt_id);
> +
> +pr_debug(">>> open_path(): rfi->path=(%s)\n", rfi->path);
> + tmp = inherit_fd_lookup_id(rfi->path, true);
I've found no symmetric check on dump for pathed files. There are
two checks for pipes -- on dump and on restore -- but only one
here.
BTW, maybe we can pull the inherited fd logic higher the stack?
Like this.
On dump in the do_dump_gen_file() before we dive into the ops->dump()
callback we
* check that we have some inherited-fds in the game,
* get p->link path (it will be the path file files and should be
the pipe[ID] for pipes, if for pipes it's empty there's the
read_fd_link() helper out there)
* lookup the inherit-fd list
* dump the fd as inherited. BTW, shouldn't we put the inherited
mark on the fdinfo_entry rather than on the file entry?
On restore we can hook into the open_fd() routine. Instead of
doing just d->ops->open we
* check for external-fd being requested
* get the respective fd from the current fdtable (or from the
service-socket-queue as I suggested in another thread)
What do you think?
> + if (tmp >= 0) {
> + pr_info("File %s will be restored from fd %d\n", rfi->path, tmp);
> + return tmp;
> + }
> +
> tmp = open_cb(mntns_root, rfi, arg);
> if (tmp < 0) {
> pr_perror("Can't open file %s", rfi->path);
> +int inherit_fd_add(char *optarg)
> +{
> + char *cp;
> + int n;
> + int fd;
> + struct inherit_fd *inh;
> +
> + /* beding debug support */
> + fd = -1;
> + n = sscanf(optarg, "debug[%d]:", &fd);
> + if (n == 1) {
> + /*
> + * If the argument has the format debug[%d]:%s, it means
> + * just write out the string after colon to the file
> + * descriptor %d. This can be used to leave a restore
> + * marker in the output stream of the process.
> + */
> + if (fd < 0) {
> + pr_msg("Invalid fd number %d in argument %s\n",
> + fd, optarg);
> + return -1;
> + }
> + cp = strchr(optarg, ':') + 1;
> + n = strlen(cp);
> + if (write(fd, cp, n) != n) {
> + pr_msg("Cannot write debug message %s to fd %d\n",
> + cp, fd);
> + return -1;
> + }
> + return 0;
> + }
> + /* end debug support */
> +
> + fd = -1;
> + n = sscanf(optarg, "fd[%d]:", &fd);
> + if (n == 1) {
> + /* argument is in fd[%d]:%s format */
> + if (fd < 0) {
> + pr_msg("Invalid fd number %d in argument %s\n", fd, optarg);
> + return -1;
> + }
> + cp = strchr(optarg, ':');
> + *cp++ = '\0';
> + } else {
> + /* argument is in %s format */
> + cp = optarg;
But in this case inh_fd would be -1 and the validate routine would just
fail. What's the point in such an entry?
> + }
> +
> + if ((inh = xmalloc(sizeof *inh)) == NULL)
> + return -1;
> + inh->inh_id = cp;
> + inh->inh_fd = fd;
> + list_add_tail(&inh->l, &opts.inherit_fds);
> + return 0;
> +}
> @@ -304,6 +316,18 @@ static int open_pipe(struct file_desc *d)
>
> pr_info("\t\tCreating pipe pipe_id=%#x id=%#x\n", pi->pe->pipe_id, pi->pe->id);
>
> + pipe_name = pipe_id_string(pi->pe->pipe_id);
> + tmp = inherit_fd_lookup_id(pipe_name, true);
> + if (tmp >= 0) {
> + pr_info("Pipe %s will be restored from inherit fd %d\n",
> + pipe_name, tmp);
> + return tmp;
> + }
> + if (pi->pe->flags == INHERIT_FD) {
Should it rather be inverted? Like
if (pi->pe->flags == INHERIT_FD) {
tmp = inherit_fd_lookup_id();
...
}
> + pr_err("No inherit fd for pipe %s\n", pipe_name);
> + return -1;
> + }
> +
> if (!pi->create)
> return recv_pipe_fd(pi);
>
> @@ -497,13 +521,18 @@ static int dump_one_pipe(int lfd, u32 id, const struct fd_parms *p)
>
> pe.id = id;
> pe.pipe_id = pipe_id(p);
> - pe.flags = p->flags;
> pe.fown = (FownEntry *)&p->fown;
> + if (inherit_fd_lookup_id(pipe_id_string(pe.pipe_id), false) < 0)
> + pe.flags = p->flags;
> + else {
> + pe.flags = INHERIT_FD;
I think it's better to introduce a new optional filed in the image. Reading
explicit "inherited = True" in the criu show output would be less confusing :)
> + pr_info("Pipe %d marked as inherit fd\n", pe.pipe_id);
> + }
>
> if (pb_write_one(img_from_set(glob_imgset, CR_FD_PIPES), &pe, PB_PIPE))
> return -1;
>
> - return dump_one_pipe_data(&pd_pipes, lfd, p);
> + return pe.flags == INHERIT_FD ? 0 : dump_one_pipe_data(&pd_pipes, lfd, p);
> }
>
> @@ -93,6 +94,14 @@ void pr_vma(unsigned int loglevel, const struct vma_area *vma_area)
> int close_safe(int *fd)
> {
> int ret = 0;
> +
> + /*
> + * Don't close files descriptors that criu's caller
> + * set up to be inherited by the restored process.
> + */
> + if (inherit_fd_lookup_fd(*fd))
> + return 0;
> +
Just for the record -- I agree with Andrey, that this place is to generic
for inherited fd check.
> if (*fd > -1) {
> ret = close(*fd);
> if (!ret)
>
Thanks,
Pavel
More information about the CRIU
mailing list