[CRIU] [PATCHv1 13/26] page-pipe: add compatible iovec
Dmitry Safonov
dsafonov at virtuozzo.com
Thu Jun 16 03:53:30 PDT 2016
struct iovec may have different size for dumpee.
But that reason, pages dump will fail (with added debug to pie):
(00.011440) page-pipe: Page pipe:
(00.011441) page-pipe: * 1 pipes 8/523 iovs:
(00.011442) page-pipe: buf 16 pages, 8 iovs:
(00.011444) page-pipe: 0x8048000 3
(00.011446) page-pipe: 0xf7512000 1
(00.011447) page-pipe: 0xf76ca000 4
(00.011449) page-pipe: 0xf76cf000 1
(00.011450) page-pipe: 0xf76dc000 2
(00.011452) page-pipe: 0xf76e1000 1
(00.011454) page-pipe: 0xf7702000 2
(00.011455) page-pipe: 0xffdad000 2
(00.011470) page-pipe: * 0 holes:
(00.011471) PPB: 16 pages 8 segs 16 pipe 0 off
(00.011476) Sent msg to daemon 8 0 0
pie: __fetched msg: 8 0 0
(00.011479) Wait for ack 8 on daemon socket
pie: sys_vmsplice for 16 pages 8 segs 0 off
pie: buf 16 pages, 8 iovs:
pie: 0x8048000 0
pie: 0x3000 0
pie: 0xf7512000 0
pie: 0x1000 0
pie: 0xf76ca000 0
pie: 0x4000 0
pie: 0xf76cf000 0
pie: 0x1000 0
pie: Error (pie/parasite.c:93): Can't splice pages to pipe (0/16)
pie: __sent ack msg: 8 8 -1
Cc: Cyrill Gorcunov <gorcunov at openvz.org>
Signed-off-by: Dmitry Safonov <dsafonov at virtuozzo.com>
---
criu/include/page-pipe.h | 5 ++--
criu/include/parasite-syscall.h | 1 +
criu/mem.c | 4 +--
criu/page-pipe.c | 56 +++++++++++++++++++++++++++++++++++------
criu/parasite-syscall.c | 2 +-
criu/shmem.c | 2 +-
6 files changed, 56 insertions(+), 14 deletions(-)
diff --git a/criu/include/page-pipe.h b/criu/include/page-pipe.h
index 696dc9fa1141..19e7a898e77f 100644
--- a/criu/include/page-pipe.h
+++ b/criu/include/page-pipe.h
@@ -95,10 +95,11 @@ struct page_pipe {
bool chunk_mode; /* Restrict the maximum buffer size of pipes
and dump memory for a few iterations */
+ bool compat_iov; /* Use compatible iovs (struct compat_iovec) */
};
-extern struct page_pipe *create_page_pipe(unsigned int nr,
- struct iovec *, bool chunk_mode);
+extern struct page_pipe *create_page_pipe(unsigned int nr, struct iovec *,
+ bool chunk_mode, bool compat_iov);
extern void destroy_page_pipe(struct page_pipe *p);
extern int page_pipe_add_page(struct page_pipe *p, unsigned long addr,
unsigned int flags);
diff --git a/criu/include/parasite-syscall.h b/criu/include/parasite-syscall.h
index 74156d4182f9..388f96545583 100644
--- a/criu/include/parasite-syscall.h
+++ b/criu/include/parasite-syscall.h
@@ -122,6 +122,7 @@ extern int syscall_seized(struct parasite_ctl *ctl, int nr, unsigned long *ret,
extern int __parasite_execute_syscall(struct parasite_ctl *ctl,
user_regs_struct_t *regs, const char *code_syscall);
extern bool arch_can_dump_task(pid_t pid);
+extern bool seized_native(struct parasite_ctl *ctl);
/*
* The PTRACE_SYSCALL will trap task twice -- on
diff --git a/criu/mem.c b/criu/mem.c
index db61aedae4f2..0ddf7e5243d7 100644
--- a/criu/mem.c
+++ b/criu/mem.c
@@ -292,8 +292,8 @@ static int __parasite_dump_pages_seized(struct parasite_ctl *ctl,
return -1;
ret = -1;
- pp = create_page_pipe(vma_area_list->priv_size,
- pargs_iovs(args), pp_ret == NULL);
+ pp = create_page_pipe(vma_area_list->priv_size, pargs_iovs(args),
+ pp_ret == NULL, !seized_native(ctl));
if (!pp)
goto out;
diff --git a/criu/page-pipe.c b/criu/page-pipe.c
index 5faf155825cf..c38b96e89407 100644
--- a/criu/page-pipe.c
+++ b/criu/page-pipe.c
@@ -100,6 +100,18 @@ static struct page_pipe_buf *ppb_alloc_resize(struct page_pipe *pp, int size)
return ppb;
}
+/* XXX: move to arch-depended file, when non-x86 add support for compat mode */
+struct iovec_compat {
+ u32 iov_base;
+ u32 iov_len;
+};
+
+static inline void iov_init_compat(struct iovec_compat *iov, unsigned long addr)
+{
+ iov->iov_base = (u32)addr;
+ iov->iov_len = PAGE_SIZE;
+}
+
static int page_pipe_grow(struct page_pipe *pp, unsigned int flags)
{
struct page_pipe_buf *ppb;
@@ -125,8 +137,8 @@ out:
return 0;
}
-struct page_pipe *create_page_pipe(unsigned int nr_segs,
- struct iovec *iovs, bool chunk_mode)
+struct page_pipe *create_page_pipe(unsigned int nr_segs, struct iovec *iovs,
+ bool chunk_mode, bool compat_iov)
{
struct page_pipe *pp;
@@ -146,6 +158,7 @@ struct page_pipe *create_page_pipe(unsigned int nr_segs,
pp->holes = NULL;
pp->chunk_mode = chunk_mode;
+ pp->compat_iov = compat_iov;
if (page_pipe_grow(pp, 0))
return NULL;
@@ -213,7 +226,13 @@ static inline int try_add_page_to(struct page_pipe *pp, struct page_pipe_buf *pp
pr_debug("Add iov to page pipe (%u iovs, %u/%u total)\n",
ppb->nr_segs, pp->free_iov, pp->nr_iovs);
- iov_init(&ppb->iov[ppb->nr_segs++], addr);
+ if (pp->compat_iov) {
+ struct iovec_compat *iovs = (void *)ppb->iov;
+
+ iov_init_compat(&iovs[ppb->nr_segs++], addr);
+ } else {
+ iov_init(&ppb->iov[ppb->nr_segs++], addr);
+ }
pp->free_iov++;
BUG_ON(pp->free_iov > pp->nr_iovs);
out:
@@ -263,7 +282,13 @@ int page_pipe_add_hole(struct page_pipe *pp, unsigned long addr)
iov_grow_page(&pp->holes[pp->free_hole - 1], addr))
goto out;
- iov_init(&pp->holes[pp->free_hole++], addr);
+ if (pp->compat_iov) {
+ struct iovec_compat *iovs = (void *)pp->holes;
+
+ iov_init_compat(&iovs[pp->free_hole++], addr);
+ } else {
+ iov_init(&pp->holes[pp->free_hole++], addr);
+ }
out:
return 0;
}
@@ -434,6 +459,7 @@ void debug_show_page_pipe(struct page_pipe *pp)
struct page_pipe_buf *ppb;
int i;
struct iovec *iov;
+ struct iovec_compat *iov_c;
if (pr_quelled(LOG_DEBUG))
return;
@@ -445,14 +471,28 @@ void debug_show_page_pipe(struct page_pipe *pp)
pr_debug("\tbuf %u pages, %u iovs, flags: %x :\n",
ppb->pages_in, ppb->nr_segs, ppb->flags);
for (i = 0; i < ppb->nr_segs; i++) {
- iov = &ppb->iov[i];
- pr_debug("\t\t%p %lu\n", iov->iov_base, iov->iov_len / PAGE_SIZE);
+ if (pp->compat_iov) {
+ iov_c = (void *)ppb->iov;
+ pr_debug("\t\t%x %lu\n", iov_c[i].iov_base,
+ iov_c[i].iov_len / PAGE_SIZE);
+ } else {
+ iov = &ppb->iov[i];
+ pr_debug("\t\t%p %lu\n", iov->iov_base,
+ iov->iov_len / PAGE_SIZE);
+ }
}
}
pr_debug("* %u holes:\n", pp->free_hole);
for (i = 0; i < pp->free_hole; i++) {
- iov = &pp->holes[i];
- pr_debug("\t%p %lu\n", iov->iov_base, iov->iov_len / PAGE_SIZE);
+ if (pp->compat_iov) {
+ iov_c = (void *)pp->holes;
+ pr_debug("\t%x %lu\n", iov_c[i].iov_base,
+ iov_c[i].iov_len / PAGE_SIZE);
+ } else {
+ iov = &pp->holes[i];
+ pr_debug("\t%p %lu\n", iov->iov_base,
+ iov->iov_len / PAGE_SIZE);
+ }
}
}
diff --git a/criu/parasite-syscall.c b/criu/parasite-syscall.c
index 371e092c88e3..c7496cba0600 100644
--- a/criu/parasite-syscall.c
+++ b/criu/parasite-syscall.c
@@ -126,7 +126,7 @@ static int restore_thread_ctx(int pid, struct thread_ctx *ctx)
return ret;
}
-static inline bool seized_native(struct parasite_ctl *ctl)
+bool seized_native(struct parasite_ctl *ctl)
{
return user_regs_native(&ctl->orig.regs);
}
diff --git a/criu/shmem.c b/criu/shmem.c
index d9dd40520499..e0d085019e6c 100644
--- a/criu/shmem.c
+++ b/criu/shmem.c
@@ -586,7 +586,7 @@ static int dump_one_shmem(struct shmem_info *si)
if (!iovs)
goto err_unmap;
- pp = create_page_pipe((nrpages + 1) / 2, iovs, true);
+ pp = create_page_pipe((nrpages + 1) / 2, iovs, true, false);
if (!pp)
goto err_iovs;
--
2.8.3
More information about the CRIU
mailing list