mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 06:15:24 +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);
|
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)
|
|||||||
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 = {
|
|||||||
.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)
|
|||||||
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);
|
||||||
list_add(&info->list, &fifo_head);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!ret)
|
/* check who will restore the fifo data */
|
||||||
ret = handle_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 ? 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 {
|
|||||||
};
|
};
|
||||||
|
|
||||||
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
|
||||||
|
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);
|
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 = read_img_eof(fd, &pde);
|
ret = -1;
|
||||||
|
r = xmalloc(sizeof(*r));
|
||||||
|
if (!r)
|
||||||
|
break;
|
||||||
|
|
||||||
|
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)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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 != pd->pde.bytes) {
|
||||||
|
ret = splice(img, NULL, pfd, NULL, pd->pde.bytes - size, 0);
|
||||||
while (size != bytes) {
|
|
||||||
ret = splice(img, NULL, pfd, NULL, 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)
|
|||||||
|
|
||||||
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)
|
|||||||
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)
|
|||||||
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)
|
||||||
|
Reference in New Issue
Block a user