[CRIU] Re: [PATCH 3/3] fifo: Add checkpoint restore for fifos
Andrew Vagin
avagin at parallels.com
Wed Jun 27 04:12:01 EDT 2012
Don't forget to add proper test cases to the white list in zdtm.sh
On Tue, Jun 26, 2012 at 06:49:57PM +0400, 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
>
> diff --git a/Makefile b/Makefile
> index 3853028..2e8df3f 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -46,6 +46,7 @@ OBJS += sk-queue.o
> OBJS += files.o
> OBJS += files-reg.o
> OBJS += pipes.o
> +OBJS += fifo.o
> OBJS += file-ids.o
> OBJS += namespaces.o
> OBJS += uts_ns.o
> diff --git a/cr-dump.c b/cr-dump.c
> index 0d8833e..4f66c51 100644
> --- a/cr-dump.c
> +++ b/cr-dump.c
> @@ -37,6 +37,7 @@
> #include "files.h"
> #include "files-reg.h"
> #include "pipes.h"
> +#include "fifo.h"
> #include "shmem.h"
> #include "sk-inet.h"
> #include "eventfd.h"
> @@ -312,8 +313,12 @@ static int dump_one_file(pid_t pid, int fd, int lfd, char fd_flags,
> if (S_ISREG(p.stat.st_mode) || S_ISDIR(p.stat.st_mode))
> return dump_reg_file(&p, lfd, cr_fdset);
>
> - if (S_ISFIFO(p.stat.st_mode) && (statfs.f_type == PIPEFS_MAGIC))
> - return dump_pipe(&p, lfd, cr_fdset);
> + if (S_ISFIFO(p.stat.st_mode)) {
> + if (statfs.f_type == PIPEFS_MAGIC)
> + return dump_pipe(&p, lfd, cr_fdset);
> + else
> + return dump_fifo(&p, lfd, cr_fdset);
> + }
>
> return dump_unsupp_fd(&p);
> }
> diff --git a/cr-restore.c b/cr-restore.c
> index 79dadac..0459820 100644
> --- a/cr-restore.c
> +++ b/cr-restore.c
> @@ -36,6 +36,7 @@
> #include "files.h"
> #include "files-reg.h"
> #include "pipes.h"
> +#include "fifo.h"
> #include "sk-inet.h"
> #include "eventfd.h"
> #include "eventpoll.h"
> @@ -301,6 +302,9 @@ static int prepare_shared(void)
> if (collect_pipes())
> return -1;
>
> + if (collect_fifo())
> + return -1;
> +
> if (collect_inet_sockets())
> return -1;
>
> diff --git a/cr-show.c b/cr-show.c
> index 2b59cfe..c663fd2 100644
> --- a/cr-show.c
> +++ b/cr-show.c
> @@ -61,6 +61,7 @@ static char *fdtype2s(u8 type)
> [FDINFO_REG] = "reg",
> [FDINFO_INETSK] = "isk",
> [FDINFO_PIPE] = "pipe",
> + [FDINFO_FIFO] = "fifo",
> [FDINFO_UNIXSK] = "usk",
> [FDINFO_EVENTFD] = "efd",
> [FDINFO_EVENTPOLL] = "epl",
> @@ -174,24 +175,23 @@ void show_ghost_file(int fd, struct cr_options *o)
> pr_img_tail(CR_FD_GHOST_FILE);
> }
>
> -void show_pipes_data(int fd_pipes, struct cr_options *o)
> +void __show_pipes_data(int fd, struct cr_options *o)
> {
> struct pipe_data_entry e;
> - int ret;
> -
> - pr_img_head(CR_FD_PIPES_DATA);
>
> while (1) {
> - ret = read_img_eof(fd_pipes, &e);
> - if (ret <= 0)
> - goto out;
> + if (read_img_eof(fd, &e) <= 0)
> + break;
> pr_msg("pipeid: 0x%8x bytes: 0x%8x off: 0x%8x\n",
> e.pipe_id, e.bytes, e.off);
> -
> - lseek(fd_pipes, e.off + e.bytes, SEEK_CUR);
> + lseek(fd, e.off + e.bytes, SEEK_CUR);
> }
> +}
>
> -out:
> +void show_pipes_data(int fd_pipes, struct cr_options *o)
> +{
> + pr_img_head(CR_FD_PIPES_DATA);
> + __show_pipes_data(fd_pipes, o);
> pr_img_tail(CR_FD_PIPES_DATA);
> }
>
> @@ -216,6 +216,26 @@ out:
> pr_img_tail(CR_FD_PIPES);
> }
>
> +void show_fifo_data(int fd, struct cr_options *o)
> +{
> + pr_img_head(CR_FD_FIFO_DATA);
> + __show_pipes_data(fd, o);
> + pr_img_tail(CR_FD_FIFO_DATA);
> +}
> +
> +void show_fifo(int fd, struct cr_options *o)
> +{
> + struct fifo_entry e;
> +
> + pr_img_head(CR_FD_FIFO);
> + while (1) {
> + if (read_img_eof(fd, &e) <= 0)
> + break;
> + pr_msg("id: 0x%8x pipeid: 0x%8x\n", e.id, e.pipe_id);
> + }
> + pr_img_tail(CR_FD_FIFO);
> +}
> +
> void show_fs(int fd_fs, struct cr_options *o)
> {
> struct fs_entry fe;
> diff --git a/crtools.c b/crtools.c
> index d4d2305..c7c8c04 100644
> --- a/crtools.c
> +++ b/crtools.c
> @@ -60,6 +60,8 @@ struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX] = {
> FD_ENTRY(VMAS, "vmas-%d", show_vmas),
> FD_ENTRY(PIPES, "pipes", show_pipes),
> FD_ENTRY(PIPES_DATA, "pipes-data", show_pipes_data),
> + FD_ENTRY(FIFO, "fifo", show_fifo),
> + FD_ENTRY(FIFO_DATA, "fifo-data", show_fifo_data),
> FD_ENTRY(PSTREE, "pstree", show_pstree),
> FD_ENTRY(SIGACT, "sigacts-%d", show_sigacts),
> FD_ENTRY(UNIXSK, "unixsk", show_unixsk),
> diff --git a/fifo.c b/fifo.c
> new file mode 100644
> index 0000000..6916ca0
> --- /dev/null
> +++ b/fifo.c
> @@ -0,0 +1,212 @@
> +#include <unistd.h>
> +#include <sys/types.h>
> +#include <sys/stat.h>
> +#include <fcntl.h>
> +#include <stdlib.h>
> +
> +#include "crtools.h"
> +#include "image.h"
> +#include "files.h"
> +#include "files-reg.h"
> +#include "pipes.h"
> +
> +#include "fifo.h"
> +
> +struct fifo_info {
> + struct list_head list;
> + struct file_desc d;
> + struct fifo_entry fe;
> +
> + u32 bytes;
> + off_t off;
> +};
> +
> +static LIST_HEAD(fifo_head);
> +
> +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;
> +
> + if (write_img(img, &e) < 0)
> + return -1;
> +
> + return dump_one_pipe_data(CR_FD_FIFO_DATA, lfd, id, p);
> +}
> +
> +static const struct fdtype_ops fifo_ops = {
> + .type = FDINFO_FIFO,
> + .make_gen_id = make_gen_id,
> + .dump = dump_one_fifo,
> +};
> +
> +int dump_fifo(struct fd_parms *p, int lfd, const struct cr_fdset *set)
> +{
> + return do_dump_gen_file(p, lfd, &fifo_ops, set);
> +}
> +
> +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;
> + }
> +
> + if (restore_pipe_data(CR_FD_FIFO_DATA, 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;
> + }
> +
> +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;
> +}
> +
> +static struct file_desc_ops fifo_desc_ops = {
> + .type = FDINFO_FIFO,
> + .open = open_fifo_fd,
> +};
> +
> +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;
> + }
> + }
> +
> + close(img);
> + return ret;
> +}
> +
> +int collect_fifo(void)
> +{
> + struct fifo_info *info = NULL;
> + int img, ret = -1;
> +
> + img = open_image_ro(CR_FD_FIFO);
> + if (img < 0)
> + return -1;
> +
> + while (1) {
> + info = xmalloc(sizeof(*info));
> + if (!info) {
> + ret = -1;
> + break;
> + }
> +
> + ret = read_img_eof(img, &info->fe);
> + if (ret <= 0)
> + break;
> +
> + pr_info("Collected fifo entry ID %#x PIPE ID %#x\n",
> + info->fe.id, info->fe.pipe_id);
> +
> + file_desc_add(&info->d, info->fe.id, &fifo_desc_ops);
> + list_add(&info->list, &fifo_head);
> + }
> +
> + if (!ret)
> + ret = handle_fifo_data();
> +
> + xfree(info);
> + close(img);
> +
> + return ret;
> +}
> diff --git a/files-reg.c b/files-reg.c
> index 9ed4db1..48268ad 100644
> --- a/files-reg.c
> +++ b/files-reg.c
> @@ -14,14 +14,6 @@
>
> #include "files-reg.h"
>
> -struct reg_file_info {
> - struct file_desc d;
> -
> - struct reg_file_entry rfe;
> - char *remap_path;
> - char *path;
> -};
> -
> struct ghost_file {
> struct list_head list;
> u32 id;
> diff --git a/include/crtools.h b/include/crtools.h
> index 4a7875d..7c8ce3b 100644
> --- a/include/crtools.h
> +++ b/include/crtools.h
> @@ -54,6 +54,8 @@ enum {
> CR_FD_UNIXSK,
> CR_FD_PIPES,
> CR_FD_PIPES_DATA,
> + CR_FD_FIFO,
> + CR_FD_FIFO_DATA,
> CR_FD_REMAP_FPATH,
> CR_FD_EVENTFD,
> CR_FD_EVENTPOLL,
> @@ -104,6 +106,8 @@ void show_mm(int fd_mm, struct cr_options *o);
> void show_vmas(int fd_vma, struct cr_options *o);
> void show_pipes(int fd_pipes, struct cr_options *o);
> void show_pipes_data(int fd_pipes, struct cr_options *o);
> +void show_fifo(int fd, struct cr_options *o);
> +void show_fifo_data(int fd_pipes, struct cr_options *o);
> void show_pstree(int fd_pstree, struct cr_options *o);
> void show_sigacts(int fd_sigacts, struct cr_options *o);
> void show_itimers(int fd, struct cr_options *o);
> diff --git a/include/fifo.h b/include/fifo.h
> new file mode 100644
> index 0000000..031e7cf
> --- /dev/null
> +++ b/include/fifo.h
> @@ -0,0 +1,10 @@
> +#ifndef FIFO_H__
> +#define FIFO_H__
> +
> +struct fd_parms;
> +struct cr_fdset;
> +
> +extern int dump_fifo(struct fd_parms *p, int lfd, const struct cr_fdset *set);
> +extern int collect_fifo(void);
> +
> +#endif /* FIFO_H__ */
> diff --git a/include/files-reg.h b/include/files-reg.h
> index 1dc5ff5..977d260 100644
> --- a/include/files-reg.h
> +++ b/include/files-reg.h
> @@ -2,10 +2,20 @@
> #define FILES_REG_H__
>
> #include "types.h"
> +#include "files.h"
> +#include "image.h"
>
> struct cr_fdset;
> struct fd_parms;
>
> +struct reg_file_info {
> + struct file_desc d;
> +
> + struct reg_file_entry rfe;
> + char *remap_path;
> + char *path;
> +};
> +
> extern int open_reg_by_id(u32 id);
> extern void clear_ghost_files(void);
> extern int collect_reg_files(void);
> diff --git a/include/image.h b/include/image.h
> index 1e8dbd0..6b404a0 100644
> --- a/include/image.h
> +++ b/include/image.h
> @@ -17,6 +17,8 @@
> #define VMAS_MAGIC 0x54123737 /* Tula */
> #define PIPES_MAGIC 0x56513555 /* Tver */
> #define PIPES_DATA_MAGIC 0x56453709 /* Dubna */
> +#define FIFO_MAGIC 0x58364939 /* Kirov */
> +#define FIFO_DATA_MAGIC 0x59333054 /* Tosno */
> #define SIGACT_MAGIC 0x55344201 /* Murom */
> #define UNIXSK_MAGIC 0x54373943 /* Ryazan */
> #define INETSK_MAGIC 0x56443851 /* Pereslavl */
> @@ -45,6 +47,7 @@ enum fd_types {
> FDINFO_UND,
> FDINFO_REG,
> FDINFO_PIPE,
> + FDINFO_FIFO,
> FDINFO_INETSK,
> FDINFO_UNIXSK,
> FDINFO_EVENTFD,
> @@ -162,6 +165,11 @@ struct pipe_data_entry {
> u8 data[0];
> } __packed;
>
> +struct fifo_entry {
> + u32 id;
> + u32 pipe_id;
> +} __packed;
> +
> /*
> * splice() connect cache pages to pipe buffer, so
> * some part of pages may be loosed if data are not
More information about the CRIU
mailing list