mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-30 22:05:36 +00:00
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: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
62
fifo.c
62
fifo.c
@@ -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
|
||||
|
66
pipes.c
66
pipes.c
@@ -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 = read_img_eof(fd, &pde);
|
||||
ret = -1;
|
||||
r = xmalloc(sizeof(*r));
|
||||
if (!r)
|
||||
break;
|
||||
|
||||
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=%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) {
|
||||
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)
|
||||
|
Reference in New Issue
Block a user