Commit d448a75e authored by Pavel Emelyanov's avatar Pavel Emelyanov

pipe/fifo: Fix and cleanup data restore

Make it in two stages.

First -- collect pipe data into hash without checking for pipe/fifo existance.
Next -- when pipe/fifo gets restored walk the hash and search where the pipe data
is.
Signed-off-by: 's avatarPavel Emelyanov <xemul@parallels.com>
parent 3aa01f64
......@@ -73,6 +73,8 @@ 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 struct pipe_data_rst *pd_hash_fifo[PIPE_DATA_HASH_SIZE];
static int do_open_fifo(struct reg_file_info *rfi, void *arg)
{
struct fifo_info *info = arg;
......@@ -96,13 +98,12 @@ static int do_open_fifo(struct reg_file_info *rfi, void *arg)
goto out;
}
if (info->restore_data) {
if (restore_pipe_data(CR_FD_FIFO_DATA, fake_fifo, info->fe->id,
info->bytes, info->off)) {
if (info->restore_data)
if (restore_pipe_data(CR_FD_FIFO_DATA, fake_fifo,
info->fe->pipe_id, pd_hash_fifo)) {
close(new_fifo);
new_fifo = -1;
}
}
out:
close(fake_fifo);
......@@ -121,44 +122,9 @@ static struct file_desc_ops fifo_desc_ops = {
.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;
struct fifo_info *info = NULL, *f;
int img, ret;
img = open_image_ro(CR_FD_FIFO);
......@@ -183,15 +149,21 @@ int collect_fifo(void)
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();
/* check who will restore the fifo data */
list_for_each_entry(f, &fifo_head, list)
if (f->fe->pipe_id == info->fe->pipe_id)
break;
if (&f->list == &fifo_head) {
list_add(&info->list, &fifo_head);
info->restore_data = true;
}
}
xfree(info ? info->fe : NULL);
xfree(info);
close(img);
return ret;
return collect_pipe_data(CR_FD_FIFO_DATA, pd_hash_fifo);
}
......@@ -14,6 +14,17 @@ struct pipe_data_dump {
};
extern int dump_one_pipe_data(struct pipe_data_dump *pd, int lfd, const struct fd_parms *p);
extern int restore_pipe_data(int img_type, int pfd, u32 id, int bytes, off_t off);
struct pipe_data_rst {
struct pipe_data_entry pde;
struct pipe_data_rst *next;
};
#define PIPE_DATA_HASH_BITS 5
#define PIPE_DATA_HASH_SIZE (1 << PIPE_DATA_HASH_BITS)
#define PIPE_DATA_HASH_MASK (PIPE_DATA_HASH_SIZE - 1)
extern int collect_pipe_data(int img_type, struct pipe_data_rst **hash);
extern int restore_pipe_data(int img_type, int pfd, u32 id, struct pipe_data_rst **hash);
#endif
......@@ -39,34 +39,37 @@ static void show_saved_pipe_fds(struct pipe_info *pi)
pr_info(" `- FD %d pid %d\n", fle->fe->fd, fle->pid);
}
static int handle_pipes_data(void)
int collect_pipe_data(int img_type, struct pipe_data_rst **hash)
{
int fd, ret;
fd = open_image_ro(CR_FD_PIPES_DATA);
fd = open_image_ro(img_type);
if (fd < 0)
return -1;
while (1) {
struct pipe_info *pi;
struct pipe_data_entry pde;
struct pipe_data_rst *r;
u32 off;
ret = -1;
r = xmalloc(sizeof(*r));
if (!r)
break;
ret = read_img_eof(fd, &pde);
ret = read_img_eof(fd, &r->pde);
if (ret <= 0)
break;
list_for_each_entry(pi, &pipes, list) {
if (pi->pe.pipe_id != pde.pipe_id)
continue;
if (!pi->create)
continue;
off = r->pde.off + lseek(fd, 0, SEEK_CUR);
lseek(fd, r->pde.bytes + r->pde.off, SEEK_CUR);
r->pde.off = off;
pi->off = lseek(fd, 0, SEEK_CUR) + pde.off;
pi->bytes = pde.bytes;
ret = r->pde.pipe_id & PIPE_DATA_HASH_MASK;
r->next = hash[ret];
hash[ret] = r;
lseek(fd, pde.bytes + pde.off, SEEK_CUR);
break;
}
pr_info("Collected pipe data for %#x (chain %u)\n",
r->pde.pipe_id, ret);
}
close(fd);
......@@ -117,24 +120,33 @@ void mark_pipe_master(void)
}
list_splice(&head, &pipes);
handle_pipes_data();
}
int restore_pipe_data(int img_type, int pfd, u32 id, int bytes, off_t off)
static struct pipe_data_rst *pd_hash_pipes[PIPE_DATA_HASH_SIZE];
int restore_pipe_data(int img_type, int pfd, u32 id, struct pipe_data_rst **hash)
{
int img, size = 0, ret;
struct pipe_data_rst *pd;
for (pd = hash[id & PIPE_DATA_HASH_MASK]; pd != NULL; pd = pd->next)
if (pd->pde.pipe_id == id)
break;
if (!pd) { /* no data for this pipe */
pr_info("No data for pipe %#x\n", id);
return 0;
}
img = open_image_ro(img_type);
if (img < 0)
return -1;
lseek(img, off, SEEK_SET);
pr_info("\t\tSplicing data size=%d off=%ld\n", bytes, off);
pr_info("\t\tSplicing data size=%u off=%u\n", pd->pde.bytes, pd->pde.off);
lseek(img, pd->pde.off, SEEK_SET);
while (size != bytes) {
ret = splice(img, NULL, pfd, NULL, bytes - size, 0);
while (size != pd->pde.bytes) {
ret = splice(img, NULL, pfd, NULL, pd->pde.bytes - size, 0);
if (ret < 0) {
pr_perror("%#x: Error splicing data", id);
goto err;
......@@ -142,7 +154,7 @@ int restore_pipe_data(int img_type, int pfd, u32 id, int bytes, off_t off)
if (ret == 0) {
pr_err("%#x: Wanted to restore %d bytes, but got %d\n",
id, bytes, size);
id, pd->pde.bytes, size);
ret = -1;
goto err;
}
......@@ -207,7 +219,8 @@ static int open_pipe(struct file_desc *d)
return -1;
}
ret = restore_pipe_data(CR_FD_PIPES_DATA, pfd[1], pi->pe.id, pi->bytes, pi->off);
ret = restore_pipe_data(CR_FD_PIPES_DATA, pfd[1],
pi->pe.pipe_id, pd_hash_pipes);
if (ret)
return -1;
......@@ -295,7 +308,8 @@ int collect_pipes(void)
xfree(pi);
close(fd);
return ret;
return collect_pipe_data(CR_FD_PIPES_DATA, pd_hash_pipes);
}
int dump_one_pipe_data(struct pipe_data_dump *pd, int lfd, const struct fd_parms *p)
......
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