Commit e6f6c9f1 authored by Cyrill Gorcunov's avatar Cyrill Gorcunov Committed by Pavel Emelyanov

pipes: Make dump_one_pipe to use dump_one_pipe_data

xemul: Why we haven't done this earlier? Because the pe entry contained the
amount of bytes in the pipe and this value had to be calculated before we
wrote this entry into the image. Now the pipe data is stored in another img
file and we can happily split pe dump and pde dump into two calls.
Signed-off-by: 's avatarCyrill Gorcunov <gorcunov@openvz.org>
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 8c54d8d9
...@@ -304,7 +304,6 @@ static int open_pipe(struct file_desc *d) ...@@ -304,7 +304,6 @@ static int open_pipe(struct file_desc *d)
static u32 *pipes_with_data; /* pipes for which data already dumped */ static u32 *pipes_with_data; /* pipes for which data already dumped */
static int nr_pipes = 0; static int nr_pipes = 0;
#if 0
static int dump_one_pipe_data(int lfd, u32 id, const struct fd_parms *p) static int dump_one_pipe_data(int lfd, u32 id, const struct fd_parms *p)
{ {
int pipe_size, i, bytes; int pipe_size, i, bytes;
...@@ -394,111 +393,22 @@ err_close: ...@@ -394,111 +393,22 @@ err_close:
err: err:
return ret; return ret;
} }
#endif
static int dump_one_pipe(int lfd, u32 id, const struct fd_parms *p) static int dump_one_pipe(int lfd, u32 id, const struct fd_parms *p)
{ {
struct pipe_entry pe; struct pipe_entry pe;
int fd_pipes;
int steal_pipe[2];
int pipe_size;
int has_bytes = 0;
int ret = -1;
int i = 0;
pr_info("Dumping pipe %d with id %#x pipe_id %#x\n", lfd, id, p->id); pr_info("Dumping pipe %d with id %#x pipe_id %#x\n", lfd, id, p->id);
fd_pipes = fdset_fd(glob_fdset, CR_FD_PIPES); pe.id = id;
pe.pipe_id = p->id;
if (p->flags & O_WRONLY) pe.flags = p->flags;
goto dump; pe.fown = p->fown;
for (i = 0; i < nr_pipes; i++) if (write_img(fdset_fd(glob_fdset, CR_FD_PIPES), &pe))
if (pipes_with_data[i] == p->id)
goto dump; /* data was dumped already */
nr_pipes++;
if (nr_pipes > PIPES_SIZE) {
pr_err("OOM storing pipe\n");
return -1; return -1;
}
pr_info("Dumping data from pipe %#x fd %d\n", id, lfd);
pipes_with_data[nr_pipes - 1] = p->id;
pipe_size = fcntl(lfd, F_GETPIPE_SZ);
if (pipe_size < 0) {
pr_err("Can't obtain piped data size\n");
goto err;
}
if (pipe(steal_pipe) < 0) {
pr_perror("Can't create pipe for stealing data");
goto err;
}
has_bytes = tee(lfd, steal_pipe[1], pipe_size, SPLICE_F_NONBLOCK);
if (has_bytes < 0) {
if (errno != EAGAIN) {
pr_perror("Can't pick pipe data");
goto err_close;
} else
has_bytes = 0;
}
dump:
pe.id = id;
pe.pipe_id = p->id;
pe.flags = p->flags;
pe.fown = p->fown;
if (write_img(fd_pipes, &pe))
goto err_close;
if (has_bytes) {
off_t off;
struct pipe_data_entry pde;
fd_pipes = fdset_fd(glob_fdset, CR_FD_PIPES_DATA);
pde.pipe_id = p->id;
pde.bytes = has_bytes;
pde.off = 0;
if (has_bytes > PIPE_MAX_NONALIG_SIZE) {
off = lseek(fd_pipes, 0, SEEK_CUR);
off += sizeof(pde);
off &= PAGE_SIZE -1;
if (off)
pde.off = PAGE_SIZE - off;
pr_info("off 0x%lx %#x\n", off, pde.off);
}
if (write_img(fd_pipes, &pde)) return dump_one_pipe_data(lfd, id, p);
goto err_close;
if (pde.off) {
off = lseek(fd_pipes, pde.off, SEEK_CUR);
pr_info("off 0x%lx\n", off);
}
ret = splice(steal_pipe[0], NULL, fd_pipes,
NULL, has_bytes, 0);
if (ret < 0) {
pr_perror("Can't push pipe data");
goto err_close;
}
}
ret = 0;
err_close:
if (has_bytes) {
close(steal_pipe[0]);
close(steal_pipe[1]);
}
err:
return ret;
} }
static const struct fdtype_ops pipe_ops = { static const struct fdtype_ops pipe_ops = {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment