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

Cyrill Gorcunov gorcunov at openvz.org
Fri May 25 12:09:30 EDT 2012


This patch adds ability to checkpoint/restore fifo
files. Note we don't dump/restore queued data from
fifo since the fifo file might belown to completely
different process (ie not created by us), so we rather
act as on regular files.

Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
 Makefile          |    1 +
 cr-dump.c         |    9 +++-
 cr-restore.c      |    4 ++
 cr-show.c         |   33 ++++++++++++
 crtools.c         |    1 +
 fifo.c            |  145 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/crtools.h |    2 +
 include/fifo.h    |   10 ++++
 include/image.h   |   11 ++++
 9 files changed, 214 insertions(+), 2 deletions(-)
 create mode 100644 fifo.c
 create mode 100644 include/fifo.h

diff --git a/Makefile b/Makefile
index f99e67b..bf2a3b2 100644
--- a/Makefile
+++ b/Makefile
@@ -45,6 +45,7 @@ OBJS		+= sk-unix.o
 OBJS		+= sk-queue.o
 OBJS		+= files.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 b9b147d..ec22895 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -35,6 +35,7 @@
 #include "parasite-syscall.h"
 #include "files.h"
 #include "pipes.h"
+#include "fifo.h"
 #include "shmem.h"
 #include "sk-inet.h"
 #include "eventfd.h"
@@ -496,8 +497,12 @@ static int dump_one_file(pid_t pid, int fd, int lfd, char fd_flags,
             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 62e84e8..f835cdc 100644
--- a/cr-restore.c
+++ b/cr-restore.c
@@ -34,6 +34,7 @@
 #include "lock.h"
 #include "files.h"
 #include "pipes.h"
+#include "fifo.h"
 #include "sk-inet.h"
 #include "eventfd.h"
 #include "eventpoll.h"
@@ -160,6 +161,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 1c766a0..c09bef2 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",
@@ -216,6 +217,38 @@ out:
 	pr_img_tail(CR_FD_PIPES);
 }
 
+void show_fifo(int fd, struct cr_options *o)
+{
+	struct fifo_file_entry e;
+	int ret;
+
+	pr_img_head(CR_FD_FIFO);
+
+	while (1) {
+		ret = read_img_eof(fd, &e);
+		if (ret <= 0)
+			goto out;
+		pr_msg("id: 0x%8x id: 0x%8x flags: 0x%8x ",
+		       e.id, e.id, e.flags);
+		show_fown_cont(&e.fown);
+
+		if (e.len) {
+			int ret = read(fd, local_buf, e.len);
+
+			if (ret != e.len) {
+				pr_perror("Can't read %d bytes", e.len);
+				goto out;
+			}
+			local_buf[e.len] = 0;
+			pr_msg(" --> %s", local_buf);
+		}
+		pr_msg("\n");
+	}
+
+out:
+	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 fc0e010..b27181d 100644
--- a/crtools.c
+++ b/crtools.c
@@ -60,6 +60,7 @@ 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(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..23a0797
--- /dev/null
+++ b/fifo.c
@@ -0,0 +1,145 @@
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "crtools.h"
+#include "image.h"
+#include "files.h"
+#include "fifo.h"
+#include "util-net.h"
+
+static char pathbuf[PATH_MAX];
+
+struct fifo_file_info {
+	struct fifo_file_entry	ffe;
+	char			*path;
+	struct file_desc	d;
+};
+
+static int fifo_open(struct file_desc *d)
+{
+	struct fifo_file_info *info;
+	int tmp;
+
+	info = container_of(d, struct fifo_file_info, d);
+
+	tmp = open(info->path, info->ffe.flags);
+	if (tmp < 0) {
+		pr_perror("Can't open fifo %#08x [%s]",
+			  info->ffe.id, info->path);
+		return -1;
+	}
+
+	lseek(tmp, info->ffe.pos, SEEK_SET);
+
+	if (rst_file_params(tmp, &info->ffe.fown, info->ffe.flags)) {
+		pr_perror("Can't restore params on fifo %#08x",
+			  info->ffe.id);
+		goto err_close;
+	}
+
+	return tmp;
+
+err_close:
+	close(tmp);
+	return -1;
+}
+
+static struct file_desc_ops fifo_desc_ops = {
+	.type = FDINFO_FIFO,
+	.open = fifo_open,
+};
+
+int collect_fifo(void)
+{
+	struct fifo_file_info *info = NULL;
+	int fd, ret = -1;
+
+	fd = open_image_ro(CR_FD_FIFO);
+	if (fd < 0)
+		return -1;
+
+	while (1) {
+		int len;
+
+		info = xzalloc(sizeof(*info));
+		if (!info) {
+			ret = -1;
+			break;
+		}
+
+		ret = read_img_eof(fd, &info->ffe);
+		if (ret <= 0)
+			break;
+
+		len = info->ffe.len;
+		info->path = xmalloc(len + 1);
+		if (!info->path) {
+			ret = -1;
+			break;
+		}
+
+		ret = read_img_buf(fd, info->path, len);
+		if (ret < 0)
+			break;
+
+		info->path[len] = '\0';
+
+		pr_info("Collected fifo [%s] ID %#x\n", info->path, info->ffe.id);
+		file_desc_add(&info->d, info->ffe.id, &fifo_desc_ops);
+	}
+
+	if (info) {
+		xfree(info->path);
+		xfree(info);
+	}
+
+	close(fd);
+
+	return ret;
+}
+
+static int dump_one_fifo(int lfd, u32 id, const struct fd_parms *p)
+{
+	struct fifo_file_entry e;
+	char fd_str[128];
+	int len, fd;
+
+	snprintf(fd_str, sizeof(fd_str), "/proc/self/fd/%d", lfd);
+	len = readlink(fd_str, pathbuf, sizeof(pathbuf) - 1);
+	if (len < 0) {
+		pr_perror("Can't readlink %s", fd_str);
+		return len;
+	}
+
+	pathbuf[len] = '\0';
+	pr_info("Dumping path for fifo %d fd via self %d [%s]\n",
+		p->fd, lfd, pathbuf);
+	pr_info("Dumping fifo %d with id %#x\n", lfd, id);
+
+	e.id	= id;
+	e.flags	= p->flags;
+	e.len	= len;
+	e.pos	= p->pos;
+	e.fown	= p->fown;
+
+	fd = fdset_fd(glob_fdset, CR_FD_FIFO);
+	if (write_img(fd, &e))
+		return -1;
+	if (write_img_buf(fd, pathbuf, len))
+		return -1;
+
+	return 0;
+}
+
+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);
+}
diff --git a/include/crtools.h b/include/crtools.h
index fdfb59b..be42466 100644
--- a/include/crtools.h
+++ b/include/crtools.h
@@ -55,6 +55,7 @@ enum {
 	CR_FD_UNIXSK,
 	CR_FD_PIPES,
 	CR_FD_PIPES_DATA,
+	CR_FD_FIFO,
 	CR_FD_REMAP_FPATH,
 	CR_FD_EVENTFD,
 	CR_FD_EVENTPOLL,
@@ -113,6 +114,7 @@ void show_remap_files(int fd, struct cr_options *o);
 void show_ghost_file(int fd, struct cr_options *o);
 void show_fown_cont(fown_t *fown);
 void show_eventfds(int fd, struct cr_options *o);
+void show_fifo(int fd, struct cr_options *o);
 
 extern void print_data(unsigned long addr, unsigned char *data, size_t size);
 extern struct cr_fd_desc_tmpl fdset_template[CR_FD_MAX];
diff --git a/include/fifo.h b/include/fifo.h
new file mode 100644
index 0000000..7a7b328
--- /dev/null
+++ b/include/fifo.h
@@ -0,0 +1,10 @@
+#ifndef CR_FIFO_H__
+#define CR_FIFO_H__
+
+#include "files.h"
+#include "crtools.h"
+
+extern int collect_fifo(void);
+extern int dump_fifo(struct fd_parms *p, int lfd, const struct cr_fdset *set);
+
+#endif /* CR_FIFO_H__ */
diff --git a/include/image.h b/include/image.h
index 3e5f36d..7fb901e 100644
--- a/include/image.h
+++ b/include/image.h
@@ -40,11 +40,13 @@
 #define INOTIFY_MAGIC		0x48424431 /* Volgograd */
 #define INOTIFY_WD_MAGIC	0x54562009 /* Svetlogorsk (Rauschen) */
 #define MOUNTPOINTS_MAGIC	0x55563928 /* Petushki */
+#define FIFO_MAGIC		0x59443036 /* Kolpino */
 
 enum fd_types {
 	FDINFO_UND,
 	FDINFO_REG,
 	FDINFO_PIPE,
+	FDINFO_FIFO,
 	FDINFO_INETSK,
 	FDINFO_UNIXSK,
 	FDINFO_EVENTFD,
@@ -66,6 +68,15 @@ typedef struct {
 	u32	pid;
 } __packed fown_t;
 
+struct fifo_file_entry {
+	u32	id;
+	u16	flags;
+	u16	len;
+	u64	pos;
+	fown_t	fown;
+	u8	name[0];
+} __packed;
+
 struct reg_file_entry {
 	u32	id;
 	u16	flags;
-- 
1.7.7.6



More information about the CRIU mailing list