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) ...@@ -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); 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) static int do_open_fifo(struct reg_file_info *rfi, void *arg)
{ {
struct fifo_info *info = arg; struct fifo_info *info = arg;
...@@ -96,13 +98,12 @@ static int do_open_fifo(struct reg_file_info *rfi, void *arg) ...@@ -96,13 +98,12 @@ static int do_open_fifo(struct reg_file_info *rfi, void *arg)
goto out; goto out;
} }
if (info->restore_data) { if (info->restore_data)
if (restore_pipe_data(CR_FD_FIFO_DATA, fake_fifo, info->fe->id, if (restore_pipe_data(CR_FD_FIFO_DATA, fake_fifo,
info->bytes, info->off)) { info->fe->pipe_id, pd_hash_fifo)) {
close(new_fifo); close(new_fifo);
new_fifo = -1; new_fifo = -1;
} }
}
out: out:
close(fake_fifo); close(fake_fifo);
...@@ -121,44 +122,9 @@ static struct file_desc_ops fifo_desc_ops = { ...@@ -121,44 +122,9 @@ static struct file_desc_ops fifo_desc_ops = {
.open = open_fifo_fd, .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) int collect_fifo(void)
{ {
struct fifo_info *info = NULL; struct fifo_info *info = NULL, *f;
int img, ret; int img, ret;
img = open_image_ro(CR_FD_FIFO); img = open_image_ro(CR_FD_FIFO);
...@@ -183,15 +149,21 @@ int collect_fifo(void) ...@@ -183,15 +149,21 @@ int collect_fifo(void)
info->fe->id, info->fe->pipe_id); info->fe->id, info->fe->pipe_id);
file_desc_add(&info->d, info->fe->id, &fifo_desc_ops); file_desc_add(&info->d, info->fe->id, &fifo_desc_ops);
/* 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); list_add(&info->list, &fifo_head);
info->restore_data = true;
}
} }
if (!ret)
ret = handle_fifo_data();
xfree(info ? info->fe : NULL); xfree(info ? info->fe : NULL);
xfree(info); xfree(info);
close(img); close(img);
return ret; return collect_pipe_data(CR_FD_FIFO_DATA, pd_hash_fifo);
} }
...@@ -14,6 +14,17 @@ struct pipe_data_dump { ...@@ -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 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 #endif
...@@ -39,34 +39,37 @@ static void show_saved_pipe_fds(struct pipe_info *pi) ...@@ -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); 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; int fd, ret;
fd = open_image_ro(CR_FD_PIPES_DATA); fd = open_image_ro(img_type);
if (fd < 0) if (fd < 0)
return -1; return -1;
while (1) { while (1) {
struct pipe_info *pi; struct pipe_data_rst *r;
struct pipe_data_entry pde; 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) if (ret <= 0)
break; break;
list_for_each_entry(pi, &pipes, list) { off = r->pde.off + lseek(fd, 0, SEEK_CUR);
if (pi->pe.pipe_id != pde.pipe_id) lseek(fd, r->pde.bytes + r->pde.off, SEEK_CUR);
continue; r->pde.off = off;
if (!pi->create)
continue;
pi->off = lseek(fd, 0, SEEK_CUR) + pde.off; ret = r->pde.pipe_id & PIPE_DATA_HASH_MASK;
pi->bytes = pde.bytes; r->next = hash[ret];
hash[ret] = r;
lseek(fd, pde.bytes + pde.off, SEEK_CUR); pr_info("Collected pipe data for %#x (chain %u)\n",
break; r->pde.pipe_id, ret);
}
} }
close(fd); close(fd);
...@@ -117,24 +120,33 @@ void mark_pipe_master(void) ...@@ -117,24 +120,33 @@ void mark_pipe_master(void)
} }
list_splice(&head, &pipes); 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; 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); img = open_image_ro(img_type);
if (img < 0) if (img < 0)
return -1; return -1;
lseek(img, off, SEEK_SET); pr_info("\t\tSplicing data size=%u off=%u\n", pd->pde.bytes, pd->pde.off);
lseek(img, pd->pde.off, SEEK_SET);
pr_info("\t\tSplicing data size=%d off=%ld\n", bytes, off);
while (size != bytes) { while (size != pd->pde.bytes) {
ret = splice(img, NULL, pfd, NULL, bytes - size, 0); ret = splice(img, NULL, pfd, NULL, pd->pde.bytes - size, 0);
if (ret < 0) { if (ret < 0) {
pr_perror("%#x: Error splicing data", id); pr_perror("%#x: Error splicing data", id);
goto err; goto err;
...@@ -142,7 +154,7 @@ int restore_pipe_data(int img_type, int pfd, u32 id, int bytes, off_t off) ...@@ -142,7 +154,7 @@ int restore_pipe_data(int img_type, int pfd, u32 id, int bytes, off_t off)
if (ret == 0) { if (ret == 0) {
pr_err("%#x: Wanted to restore %d bytes, but got %d\n", pr_err("%#x: Wanted to restore %d bytes, but got %d\n",
id, bytes, size); id, pd->pde.bytes, size);
ret = -1; ret = -1;
goto err; goto err;
} }
...@@ -207,7 +219,8 @@ static int open_pipe(struct file_desc *d) ...@@ -207,7 +219,8 @@ static int open_pipe(struct file_desc *d)
return -1; 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) if (ret)
return -1; return -1;
...@@ -295,7 +308,8 @@ int collect_pipes(void) ...@@ -295,7 +308,8 @@ int collect_pipes(void)
xfree(pi); xfree(pi);
close(fd); 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) 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