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

Cyrill Gorcunov gorcunov at openvz.org
Thu Jun 28 18:37:09 EDT 2012


On Thu, Jun 28, 2012 at 10:20:27PM +0400, Cyrill Gorcunov wrote:
> 
> I find it inconvenient, open_reg_by_id is already used
> 
> [cyrill at moon crtools]$ git grep open_reg_by_id
> cr-restore.c:   exe_fd = open_reg_by_id(args->mm.exe_file_id);
> fifo.c: open_reg_by_id
> files-reg.c:int open_reg_by_id(u32 id)
> files.c:        cwd = open_reg_by_id(fe.cwd_id);
> files.c:        return open_reg_by_id(vma_entry->shmid);
> include/files-reg.h:extern int open_reg_by_id(u32 id);
> 
> should I pass real_open for all callers? Actually I've had idea
> of reworking this all completely to make more flexible design
> on path remapping, so Pavel will you be fine if I
> 
>  - add explicit comment on 1)
>  - add fixme for reg-files engine and will redesign this on
>    weekend (i'm about to switch to tty task at moment)
> 
> Hm?

Anyway, here is a patch updated (comments fix). I'll redesign
it later but at moment i would like to stick with this patch,
since it brings minimal changes to files-reg.c.

	Cyrill
-------------- next part --------------
>From c2dda824eb7aaf1c1dcd0628f98d24d9d5503d39 Mon Sep 17 00:00:00 2001
From: Cyrill Gorcunov <gorcunov at openvz.org>
Date: Tue, 26 Jun 2012 02:36:13 +0400
Subject: [PATCH 3/7] fifo: Add checkpoint restore for fifos v3

Checkpoint 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. Also we need writable fifo
end to restore data queued.

v2:
 - add open/priv members to reg_file_info
 - make open_fifo_fd to use open_fe_fd
 - comment on pipe_id
 - make sure the fifo data is not restored twice

v3:
 - drop useless fixme comment and add sane one

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              |  206 +++++++++++++++++++++++++++++++++++++++++++++++++++
 files-reg.c         |   18 ++---
 include/crtools.h   |    4 +
 include/fifo.h      |   10 +++
 include/files-reg.h |   15 ++++
 include/image.h     |    8 ++
 11 files changed, 295 insertions(+), 22 deletions(-)
 create mode 100644 fifo.c
 create mode 100644 include/fifo.h

diff --git a/Makefile b/Makefile
index 8b35b64..ec97561 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 1a0a4b8..9ee3463 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"
@@ -293,8 +294,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 a2e162d..19c7d5f 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"
@@ -86,6 +87,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 fe89368..97c8037 100644
--- a/cr-show.c
+++ b/cr-show.c
@@ -62,6 +62,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",
@@ -175,24 +176,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);
 }
 
@@ -217,6 +217,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..289bef0
--- /dev/null
+++ b/fifo.c
@@ -0,0 +1,206 @@
+#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"
+
+/*
+ * FIFO checkpoint and restore is done in a bit unusual manner.
+ * We use files-reg.c engine to save fifo path and flags,
+ * thus regular files image will contain fifo descriptos which
+ * are useless for reg-files engine itself but needed for our fifo
+ * engine.
+ *
+ * In particual we dump fifo-entry automatically and appropriate
+ * reg-file entry manually, thus on restore we need to ask reg-file
+ * engine to restore fifo path and flags via direct call.
+ */
+
+struct fifo_info {
+	struct list_head	list;
+	struct file_desc	d;
+	struct fifo_entry	fe;
+
+	u32			bytes;
+	off_t			off;
+	bool			restore_data;
+};
+
+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 reg_file_info *rfi)
+{
+	struct fifo_info *info = rfi->priv;
+	int new_fifo, fake_fifo = -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 %#x [%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 %#x [%s]", info->fe.id, rfi->path);
+		goto out;
+	}
+
+	if (restore_pipe_data(CR_FD_FIFO_DATA, fake_fifo, info->fe.id,
+			      info->bytes, info->off)) {
+		close(new_fifo);
+		new_fifo = -1;
+	}
+
+out:
+	close(fake_fifo);
+	return new_fifo;
+}
+
+static int open_fifo_fd(struct file_desc *d)
+{
+	struct fifo_info *info = container_of(d, struct fifo_info, d);
+	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->open != __open_fifo_fd)
+		rfi->open = __open_fifo_fd;
+	rfi->priv = info;
+
+	return open_fe_fd(rd);
+}
+
+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 ||
+			    info->restore_data)
+				continue;
+
+			info->off	= lseek(img, 0, SEEK_CUR) + pde.off;
+			info->bytes	= pde.bytes;
+
+			lseek(img, pde.bytes + pde.off, SEEK_CUR);
+
+			info->restore_data = true;
+			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 = xzalloc(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 82659b5..f2079c5 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;
@@ -348,7 +340,12 @@ int dump_reg_file(struct fd_parms *p, int lfd,
 	return do_dump_gen_file(p, lfd, &regfile_ops, cr_fdset);
 }
 
-static int open_fe_fd(struct file_desc *d)
+static int __open_reg_fd(struct reg_file_info *rfi)
+{
+	return open(rfi->path, rfi->rfe.flags);
+}
+
+int open_fe_fd(struct file_desc *d)
 {
 	struct reg_file_info *rfi;
 	int tmp;
@@ -362,7 +359,7 @@ static int open_fe_fd(struct file_desc *d)
 			return -1;
 		}
 
-	tmp = open(rfi->path, rfi->rfe.flags);
+	tmp = rfi->open(rfi);
 	if (tmp < 0) {
 		pr_perror("Can't open file %s", rfi->path);
 		return -1;
@@ -422,6 +419,7 @@ int collect_reg_files(void)
 			break;
 
 		rfi->remap_path = NULL;
+		rfi->open = __open_reg_fd;
 
 		pr_info("Collected [%s] ID %#x\n", rfi->path, rfi->rfe.id);
 		file_desc_add(&rfi->d, rfi->rfe.id, &reg_desc_ops);
diff --git a/include/crtools.h b/include/crtools.h
index 73f227a..c258990 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..7de5bb5 100644
--- a/include/files-reg.h
+++ b/include/files-reg.h
@@ -2,13 +2,28 @@
 #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;
+
+	int			(*open)(struct reg_file_info *rfi);
+	void			*priv;
+};
+
 extern int open_reg_by_id(u32 id);
 extern void clear_ghost_files(void);
 extern int collect_reg_files(void);
+extern int open_fe_fd(struct file_desc *d);
 
 extern int dump_reg_file(struct fd_parms *p, int lfd, const struct cr_fdset *cr_fdset);
 extern int dump_one_reg_file(int lfd, u32 id, const struct fd_parms *p);
diff --git a/include/image.h b/include/image.h
index b4d00e6..fbd7917 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,
@@ -161,6 +164,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
-- 
1.7.7.6



More information about the CRIU mailing list