[CRIU] Re: [PATCH 19/24] pipes: Add c/r for fifo files
Cyrill Gorcunov
gorcunov at openvz.org
Thu Jun 7 12:49:41 EDT 2012
On Thu, Jun 07, 2012 at 05:29:15PM +0400, Cyrill Gorcunov wrote:
>
> Basically pipes are superset over fifos,
> so we integrate fifo c/r into pipes.c.
>
> Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
> ---
Updated patch is enveloped, use it instead.
Cyrill
-------------- next part --------------
>From c82a795b55a7c2ff6411aac21dcb1b6d3efc166b Mon Sep 17 00:00:00 2001
From: Cyrill Gorcunov <gorcunov at openvz.org>
Date: Wed, 6 Jun 2012 20:54:13 +0400
Subject: [PATCH 19/24] pipes: Add c/r for fifo files
MIME-Version: 1.0
Content-Type: multipart/mixed; boundary="------------1.7.7.6"
This is a multi-part message in MIME format.
--------------1.7.7.6
Content-Type: text/plain; charset=UTF-8; format=fixed
Content-Transfer-Encoding: 8bit
Basically pipes are superset over fifos,
so we integrate fifo c/r into pipes.c.
The idea of restoring fifoa is the following
- since fifo may block on opening if there is
no reader/writer, we use O_NONBLOCK to escape
this
- O_NONBLOCK is not enough for write-only fifos,
to this sake we create fake fifo reader and once
writer is created we close reader immediately
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
cr-dump.c | 8 ++-
cr-show.c | 15 ++++-
include/image.h | 10 +++
include/pipes.h | 3 +
pipes.c | 193 ++++++++++++++++++++++++++++++++++++++++++++++++-------
5 files changed, 202 insertions(+), 27 deletions(-)
--------------1.7.7.6
Content-Type: text/x-patch; name="0019-pipes-Add-c-r-for-fifo-files.patch"
Content-Transfer-Encoding: 8bit
Content-Disposition: attachment; filename="0019-pipes-Add-c-r-for-fifo-files.patch"
diff --git a/cr-dump.c b/cr-dump.c
index 1b6c2f6..bed4267 100644
--- a/cr-dump.c
+++ b/cr-dump.c
@@ -495,8 +495,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-show.c b/cr-show.c
index 31c1565..207203b 100644
--- a/cr-show.c
+++ b/cr-show.c
@@ -22,6 +22,7 @@
#include "image.h"
#include "uts_ns.h"
#include "ipc_ns.h"
+#include "pipes.h"
#define DEF_PAGES_PER_LINE 6
@@ -206,9 +207,19 @@ void show_pipes(int fd_pipes, struct cr_options *o)
ret = read_img_eof(fd_pipes, &e);
if (ret <= 0)
goto out;
- pr_msg("id: 0x%8x pipeid: 0x%8x flags: 0x%8x ",
- e.id, e.pipe_id, e.flags);
+ pr_msg("id: 0x%8x pipeid: 0x%8x type: %4s flags: 0x%8x ",
+ e.id, e.pipe_id, pipetype2s(e.type), e.flags);
show_fown_cont(&e.fown);
+
+ if (e.len) {
+ int ret = read(fd_pipes, 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");
}
diff --git a/include/image.h b/include/image.h
index 4ffa845..fbbcc7a 100644
--- a/include/image.h
+++ b/include/image.h
@@ -147,11 +147,21 @@ struct pstree_entry {
u32 nr_threads;
} __packed;
+enum {
+ PIPE_TYPE_ANON,
+ PIPE_TYPE_FIFO,
+
+ PIPE_TYPE_MAX,
+};
+
struct pipe_entry {
u32 id;
u32 pipe_id;
u32 flags;
fown_t fown;
+ u16 type;
+ u16 len;
+ u8 name[0];
} __packed;
struct pipe_data_entry {
diff --git a/include/pipes.h b/include/pipes.h
index 59a34dc..3a92ca8 100644
--- a/include/pipes.h
+++ b/include/pipes.h
@@ -1,8 +1,11 @@
#ifndef CR_PIPES_H__
#define CR_PIPES_H__
+extern char *pipetype2s(int type);
+
extern int collect_pipes(void);
extern void mark_pipe_master(void);
extern int dump_pipe(struct fd_parms *p, int lfd, const struct cr_fdset *cr_fdset);
+extern int dump_fifo(struct fd_parms *p, int lfd, const struct cr_fdset *cr_fdset);
#endif /* CR_PIPES_H__ */
diff --git a/pipes.c b/pipes.c
index c3aa240..58827cb 100644
--- a/pipes.c
+++ b/pipes.c
@@ -9,6 +9,7 @@
#include "files.h"
#include "pipes.h"
#include "util-net.h"
+#include "proc_parse.h"
/*
* The sequence of objects which should be restored:
@@ -23,6 +24,7 @@ struct pipe_info {
* This is pure circular list without head */
struct list_head list; /* list head for fdinfo_list_entry-s */
struct file_desc d;
+ char *path;
int create;
int bytes;
off_t off;
@@ -30,6 +32,20 @@ struct pipe_info {
static LIST_HEAD(pipes);
+char *pipetype2s(int type)
+{
+ static char *str[PIPE_TYPE_MAX + 1] = {
+ [PIPE_TYPE_ANON] = "anon",
+ [PIPE_TYPE_FIFO] = "fifo",
+ [PIPE_TYPE_MAX] = "unknown",
+ };
+
+ if (type >= PIPE_TYPE_MAX)
+ type = PIPE_TYPE_MAX;
+
+ return str[type];
+}
+
static void show_saved_pipe_fds(struct pipe_info *pi)
{
struct fdinfo_list_entry *fle;
@@ -159,6 +175,55 @@ err:
return ret;
}
+static int open_fifo_fd(struct pipe_info *info, char *path)
+{
+ int new_fifo, fake_fifo = -1;
+
+ /*
+ * This requires some comments -- in case if fifo
+ * was opened for write-only mode we need a fake
+ * reader to be able to not block on restore, once
+ * writer restored, we close our fake reader.
+ *
+ * Another trick is that we use O_NONBLOCK on fifo
+ * opening, otherwise the restore procedure might
+ * stuck waiting for other fifo end to connect.
+ */
+ if ((info->pe.flags & O_ACCMODE) == O_WRONLY) {
+ fake_fifo = open(path, O_RDONLY | O_NONBLOCK);
+ if (fake_fifo < 0) {
+ pr_perror("Can't open fake reader on fifo %#08x [%s]",
+ info->pe.id, path);
+ return -1;
+ }
+ pr_info("Fake fifo %d created\n", fake_fifo);
+ }
+
+ new_fifo = open(path, info->pe.flags | O_NONBLOCK);
+ if (new_fifo < 0) {
+ pr_perror("Can't open fifo %#08x [%s]",
+ info->pe.id, path);
+ goto err_close_fake;
+ }
+
+ if (restore_pipe_data(new_fifo, info))
+ goto err_close_new;
+
+ if (rst_file_params(new_fifo, &info->pe.fown, info->pe.flags)) {
+ pr_perror("Can't restore params on fifo %#08x",
+ info->pe.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;
+}
+
static int recv_pipe_fd(struct pipe_info *pi)
{
struct fdinfo_list_entry *fle;
@@ -168,7 +233,7 @@ static int recv_pipe_fd(struct pipe_info *pi)
fle = file_master(&pi->d);
fd = fle->fe.fd;
- pr_info("\tWaiting fd for %d\n", fd);
+ pr_info("\tPipe waits fd for %d id %#x\n", fd, fle->fe.id);
tmp = recv_fd(fd);
if (tmp < 0) {
@@ -191,26 +256,19 @@ static int recv_pipe_fd(struct pipe_info *pi)
return fd;
}
-static int open_pipe(struct file_desc *d)
+static int open_pipe_fd(struct pipe_info *info)
{
- struct pipe_info *pi, *p;
+ struct pipe_info *p;
int ret, tmp;
int pfd[2];
int sock;
- pi = container_of(d, struct pipe_info, d);
-
- pr_info("\t\tCreating pipe pipe_id=%#x id=%#x\n", pi->pe.pipe_id, pi->pe.id);
-
- if (!pi->create)
- return recv_pipe_fd(pi);
-
if (pipe(pfd) < 0) {
pr_perror("Can't create pipe");
return -1;
}
- ret = restore_pipe_data(pfd[1], pi);
+ ret = restore_pipe_data(pfd[1], info);
if (ret)
return -1;
@@ -220,7 +278,7 @@ static int open_pipe(struct file_desc *d)
return -1;
}
- list_for_each_entry(p, &pi->pipe_list, pipe_list) {
+ list_for_each_entry(p, &info->pipe_list, pipe_list) {
struct fdinfo_list_entry *fle;
int fd;
@@ -235,15 +293,38 @@ static int open_pipe(struct file_desc *d)
close(sock);
- close(pfd[!(pi->pe.flags & O_WRONLY)]);
- tmp = pfd[pi->pe.flags & O_WRONLY];
+ close(pfd[!(info->pe.flags & O_WRONLY)]);
+ tmp = pfd[info->pe.flags & O_WRONLY];
- if (rst_file_params(tmp, &pi->pe.fown, pi->pe.flags))
+ if (rst_file_params(tmp, &info->pe.fown, info->pe.flags))
return -1;
return tmp;
}
+static int open_pipe(struct file_desc *d)
+{
+ struct pipe_info *info = container_of(d, struct pipe_info, d);
+
+ pr_info("\t\tCreating %s pipe_id=%#x id=%#x\n",
+ pipetype2s(info->pe.type), info->pe.pipe_id, info->pe.id);
+
+ switch (info->pe.type) {
+ case PIPE_TYPE_ANON:
+ if (!info->create)
+ return recv_pipe_fd(info);
+ else
+ return open_pipe_fd(info);
+ case PIPE_TYPE_FIFO:
+ BUG_ON(!info->create);
+ return open_fifo_fd(info, info->path);
+ default:
+ BUG_ON(1);
+ }
+
+ return -1;
+}
+
static int want_transport(struct fdinfo_entry *fe, struct file_desc *d)
{
struct pipe_info *pi;
@@ -273,18 +354,38 @@ int collect_pipes(void)
if (pi == NULL)
break;
+ pi->path = NULL;
+
ret = read_img_eof(fd, &pi->pe);
if (ret <= 0)
break;
- pr_info("Collected pipe entry ID %#x PIPE ID %#x\n",
- pi->pe.id, pi->pe.pipe_id);
+ if (pi->pe.len) {
+ pi->path = xmalloc(pi->pe.len + 1);
+ ret = read_img_buf_eof(fd, pi->path, pi->pe.len);
+ if (ret <= 0) {
+ ret = -1;
+ pr_err("Corrupted path in %s %#x\n",
+ pipetype2s(pi->pe.type), pi->pe.id);
+ break;
+ }
+ pi->path[pi->pe.len] = '\0';
+ }
+
+ pr_info("Collected %s entry ID %#x PIPE ID %#x\n",
+ pipetype2s(pi->pe.type), pi->pe.id, pi->pe.pipe_id);
file_desc_add(&pi->d, pi->pe.id, &pipe_desc_ops);
list_for_each_entry(tmp, &pipes, list) {
- if (pi->pe.pipe_id == tmp->pe.pipe_id)
- break;
+ /*
+ * Only anon pipes are created in one place
+ * and sent via SCM, the fifo should be
+ * created explicitly.
+ */
+ if (pi->pe.pipe_id == tmp->pe.pipe_id &&
+ pi->pe.type == PIPE_TYPE_ANON)
+ break;
}
if (&tmp->list == &pipes)
@@ -295,6 +396,7 @@ int collect_pipes(void)
list_add_tail(&pi->list, &pipes);
}
+ xfree(pi ? pi->path : NULL);
xfree(pi);
close(fd);
@@ -394,23 +496,52 @@ err:
return ret;
}
-static int dump_one_pipe(int lfd, u32 id, const struct fd_parms *p)
+static int dump_one_typed_pipe(int type, int lfd, u32 id, const struct fd_parms *p)
{
struct pipe_entry pe;
+ char *path;
- pr_info("Dumping pipe %d with id %#x pipe_id %#x\n", lfd, id, p->id);
+ if (type >= PIPE_TYPE_MAX) {
+ pr_err("Unknown pipe type %d on %d\n", type, p->fd);
+ return -1;
+ }
+
+ pr_info("Dumping %s %d with id %#x pipe_id %#x\n",
+ pipetype2s(type), lfd, id, p->id);
pe.id = id;
pe.pipe_id = p->id;
pe.flags = p->flags;
pe.fown = p->fown;
+ pe.type = type;
- if (write_img(fdset_fd(glob_fdset, CR_FD_PIPES), &pe))
- return -1;
+ switch (type) {
+ case PIPE_TYPE_ANON:
+ pe.len = 0;
+ if (write_img(fdset_fd(glob_fdset, CR_FD_PIPES), &pe))
+ return -1;
+ break;
+ case PIPE_TYPE_FIFO:
+ path = read_proc_selffd_link(lfd, (int *)&pe.len);
+ if (!path)
+ return -1;
+ if (write_img(fdset_fd(glob_fdset, CR_FD_PIPES), &pe))
+ return -1;
+ if (write_img_buf(fdset_fd(glob_fdset, CR_FD_PIPES), path, pe.len))
+ return -1;
+ break;
+ default:
+ BUG_ON(1);
+ }
return dump_one_pipe_data(lfd, id, p);
}
+static int dump_one_pipe(int lfd, u32 id, const struct fd_parms *p)
+{
+ return dump_one_typed_pipe(PIPE_TYPE_ANON, lfd, id, p);
+}
+
static const struct fdtype_ops pipe_ops = {
.type = FDINFO_PIPE,
.make_gen_id = make_gen_id,
@@ -421,3 +552,19 @@ int dump_pipe(struct fd_parms *p, int lfd, const struct cr_fdset *cr_fdset)
{
return do_dump_gen_file(p, lfd, &pipe_ops, cr_fdset);
}
+
+static int dump_one_fifo(int lfd, u32 id, const struct fd_parms *p)
+{
+ return dump_one_typed_pipe(PIPE_TYPE_FIFO, lfd, id, p);
+}
+
+static const struct fdtype_ops fifo_ops = {
+ .type = FDINFO_PIPE,
+ .make_gen_id = make_gen_id,
+ .dump = dump_one_fifo,
+};
+
+int dump_fifo(struct fd_parms *p, int lfd, const struct cr_fdset *cr_fdset)
+{
+ return do_dump_gen_file(p, lfd, &fifo_ops, cr_fdset);
+}
--------------1.7.7.6--
More information about the CRIU
mailing list