[CRIU] [PATCH 20/21] pipes: Add restore for fifo
Cyrill Gorcunov
gorcunov at openvz.org
Wed Jun 6 18:22:00 EDT 2012
To be able to open O_WRONLY fifos we
create fake fifo for that, which we
delete immediately O_WRONLY fifo-end
created.
Signed-off-by: Cyrill Gorcunov <gorcunov at openvz.org>
---
pipes.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 files changed, 160 insertions(+), 19 deletions(-)
diff --git a/pipes.c b/pipes.c
index f2bec6a..99230b0 100644
--- a/pipes.c
+++ b/pipes.c
@@ -24,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;
@@ -174,6 +175,105 @@ err:
return ret;
}
+static int recv_fifo_fd(struct pipe_info *info)
+{
+ struct fdinfo_list_entry *fle;
+ char path[PATH_MAX];
+ int tmp, fd;
+
+ fle = file_master(&info->d);
+ fd = fle->fe.fd;
+
+ pr_info("\tFifo waits fd for %d id %#x\n", fd, fle->fe.id);
+
+ tmp = recv_fd(fd);
+ if (tmp < 0) {
+ pr_err("Can't get fd %d\n", tmp);
+ return -1;
+ }
+ close(fd);
+
+ snprintf(path, PATH_MAX, "/proc/self/fd/%d", tmp);
+ fd = open(path, info->pe.flags | O_NONBLOCK);
+ close(tmp);
+
+ if (fd >= 0) {
+ if (restore_fown(fd, &info->pe.fown)) {
+ close(fd);
+ return -1;
+ }
+ }
+
+ return fd;
+}
+
+static int open_fifo_fd(struct pipe_info *info, char *path)
+{
+ int new_fifo, fake_fifo = -1;
+ struct pipe_info *p;
+ int sock = -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.
+ */
+ 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 ((info->pe.flags & O_ACCMODE) != O_RDONLY) {
+ if (restore_pipe_data(new_fifo, info))
+ goto err_close_new;
+ }
+
+ sock = socket(PF_UNIX, SOCK_DGRAM, 0);
+ if (sock < 0) {
+ pr_perror("Can't create socket");
+ return -1;
+ }
+
+ list_for_each_entry(p, &info->pipe_list, pipe_list) {
+ struct fdinfo_list_entry *fle = file_master(&p->d);
+
+ if (send_fd_to_peer(new_fifo, fle, sock)) {
+ pr_perror("Can't send file descriptor");
+ goto err_close_new;
+ }
+ }
+
+ close_safe(&sock);
+
+ 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(&sock);
+ close_safe(&new_fifo);
+ goto err_close_fake;
+}
+
static int recv_pipe_fd(struct pipe_info *pi)
{
struct fdinfo_list_entry *fle;
@@ -183,7 +283,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) {
@@ -206,26 +306,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;
@@ -235,7 +328,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;
@@ -250,15 +343,40 @@ 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:
+ if (!info->create)
+ return recv_fifo_fd(info);
+ else
+ 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;
@@ -288,18 +406,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)
@@ -310,6 +448,7 @@ int collect_pipes(void)
list_add_tail(&pi->list, &pipes);
}
+ xfree(pi ? pi->path : NULL);
xfree(pi);
close(fd);
@@ -443,6 +582,8 @@ static int dump_one_typed_pipe(int type, int lfd, u32 id, const struct fd_parms
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);
--
1.7.7.6
More information about the CRIU
mailing list