Message ID | 20160628192423.14943-15-dsafonov@virtuozzo.com |
---|---|
State | Rejected |
Series | "x86 Compatible C/R, part 2" |
Headers | show |
diff --git a/criu/include/page-pipe.h b/criu/include/page-pipe.h index 19e7a898e77f..474ffa004daa 100644 --- a/criu/include/page-pipe.h +++ b/criu/include/page-pipe.h @@ -98,6 +98,12 @@ struct page_pipe { bool compat_iov; /* Use compatible iovs (struct compat_iovec) */ }; +/* XXX: move to arch-depended file, when non-x86 add support for compat mode */ +struct iovec_compat { + u32 iov_base; + u32 iov_len; +}; + 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); diff --git a/criu/page-pipe.c b/criu/page-pipe.c index c38b96e89407..db597b27f1e2 100644 --- a/criu/page-pipe.c +++ b/criu/page-pipe.c @@ -100,12 +100,6 @@ 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; diff --git a/criu/page-xfer.c b/criu/page-xfer.c index 3813712fefcf..8c2c799c0b0f 100644 --- a/criu/page-xfer.c +++ b/criu/page-xfer.c @@ -320,61 +320,81 @@ int open_page_xfer(struct page_xfer *xfer, int fd_type, long id) return open_page_local_xfer(xfer, fd_type, id); } +static int page_xfer_dump_hole(struct page_xfer *xfer, + struct iovec *hole, unsigned long off) +{ + BUG_ON(hole->iov_base < (void *)off); + hole->iov_base -= off; + pr_debug("\th %p [%u]\n", hole->iov_base, + (unsigned int)(hole->iov_len / PAGE_SIZE)); + + if (xfer->write_hole(xfer, hole)) + return -1; + + return 0; +} + +static struct iovec get_iov(struct iovec *iovs, unsigned int n, bool compat) +{ + if (likely(!compat)) { + return iovs[n]; + } else { + struct iovec ret; + struct iovec_compat *tmp = (struct iovec_compat*)(void *)iovs; + + tmp += n; + ret.iov_base = (void *)(uintptr_t)tmp->iov_base; + ret.iov_len = tmp->iov_len; + return ret; + } +} + int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp, unsigned long off) { struct page_pipe_buf *ppb; - struct iovec *hole = NULL; + unsigned int cur_hole = 0; + int ret; pr_debug("Transfering pages:\n"); - if (pp->free_hole) - hole = &pp->holes[0]; - list_for_each_entry(ppb, &pp->bufs, l) { - int i; + unsigned int i; pr_debug("\tbuf %d/%d\n", ppb->pages_in, ppb->nr_segs); for (i = 0; i < ppb->nr_segs; i++) { - struct iovec *iov = &ppb->iov[i]; - - while (hole && (hole->iov_base < iov->iov_base)) { - BUG_ON(hole->iov_base < (void *)off); - hole->iov_base -= off; - pr_debug("\th %p [%u]\n", hole->iov_base, - (unsigned int)(hole->iov_len / PAGE_SIZE)); - if (xfer->write_hole(xfer, hole)) - return -1; - - hole++; - if (hole >= &pp->holes[pp->free_hole]) - hole = NULL; + struct iovec iov = get_iov(ppb->iov, i, pp->compat_iov); + + for (; cur_hole < pp->free_hole ; cur_hole++) { + struct iovec hole = get_iov(pp->holes, cur_hole, + pp->compat_iov); + + if (hole.iov_base < iov.iov_base) + break; + ret = page_xfer_dump_hole(xfer, &hole, off); + if (ret) + return ret; } - BUG_ON(iov->iov_base < (void *)off); - iov->iov_base -= off; - pr_debug("\tp %p [%u]\n", iov->iov_base, - (unsigned int)(iov->iov_len / PAGE_SIZE)); + BUG_ON(iov.iov_base < (void *)off); + iov.iov_base -= off; + pr_debug("\tp %p [%u]\n", iov.iov_base, + (unsigned int)(iov.iov_len / PAGE_SIZE)); - if (xfer->write_pagemap(xfer, iov)) + if (xfer->write_pagemap(xfer, &iov)) return -1; - if (xfer->write_pages(xfer, ppb->p[0], iov->iov_len)) + if (xfer->write_pages(xfer, ppb->p[0], iov.iov_len)) return -1; } } - while (hole) { - BUG_ON(hole->iov_base < (void *)off); - hole->iov_base -= off; - pr_debug("\th* %p [%u]\n", hole->iov_base, - (unsigned int)(hole->iov_len / PAGE_SIZE)); - if (xfer->write_hole(xfer, hole)) - return -1; + for (; cur_hole < pp->free_hole ; cur_hole++) { + struct iovec hole = get_iov(pp->holes, cur_hole, pp->compat_iov); - hole++; - if (hole >= &pp->holes[pp->free_hole]) - hole = NULL; + ret = page_xfer_dump_hole(xfer, &hole, off); + if (ret) + return ret; } return 0;
On Tue, Jun 28, 2016 at 10:24:07PM +0300, Dmitry Safonov wrote: > Change page_xfer_dump_pages the way it could handle compatible iovs. > Separated hole dumping in page_xfer_dump_hole and introduced > iterator function get_iov which will return native iovec, > converting compatible iovec if needed. > > Fixes: > (00.009060) Fetched ack: 7 7 0 > (00.009061) Transfering pages: > (00.009062) buf 16/16 > (00.009063) p 0x100008048000 [32841] > (00.009101) Error (page-xfer.c:504): Only 65536 of 17592320561152 bytes have been spliced > (00.009253) page-pipe: Killing page pipe > (00.009263) ---------------------------------------- > [root@fc22-vm criu]# ./test/zdtm.py run -t zdtm/static/env00 --pre 2 === Run 1/1 ================ ========================== Run zdtm/static/env00 in h ========================== Start test ./env00 --pidfile=env00.pid --outfile=env00.out --envname=ENV_00_TEST Run criu pre-dump Run criu pre-dump Run criu dump Run criu restore =[log]=> dump/zdtm/static/env00/24/3/restore.log ------------------------ grep Error ------------------------ (00.035223) 24: Error (mem.c:826): Page entry address 400000 outside of VMA 7fffddbcf000-7fffddbd1000 (00.035323) Error (cr-restore.c:1885): Restoring FAILED. ------------------------ ERROR OVER ------------------------ ################# Test zdtm/static/env00 FAIL at CRIU restore ################## ##################################### FAIL ##################################### https://github.com/xemul/criu/issues/185 > Cc: Cyrill Gorcunov <gorcunov@openvz.org> > Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com> > --- > criu/include/page-pipe.h | 6 ++++ > criu/page-pipe.c | 6 ---- > criu/page-xfer.c | 88 +++++++++++++++++++++++++++++------------------- > 3 files changed, 60 insertions(+), 40 deletions(-) > > diff --git a/criu/include/page-pipe.h b/criu/include/page-pipe.h > index 19e7a898e77f..474ffa004daa 100644 > --- a/criu/include/page-pipe.h > +++ b/criu/include/page-pipe.h > @@ -98,6 +98,12 @@ struct page_pipe { > bool compat_iov; /* Use compatible iovs (struct compat_iovec) */ > }; > > +/* XXX: move to arch-depended file, when non-x86 add support for compat mode */ > +struct iovec_compat { > + u32 iov_base; > + u32 iov_len; > +}; > + > 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); > diff --git a/criu/page-pipe.c b/criu/page-pipe.c > index c38b96e89407..db597b27f1e2 100644 > --- a/criu/page-pipe.c > +++ b/criu/page-pipe.c > @@ -100,12 +100,6 @@ 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; > diff --git a/criu/page-xfer.c b/criu/page-xfer.c > index 3813712fefcf..8c2c799c0b0f 100644 > --- a/criu/page-xfer.c > +++ b/criu/page-xfer.c > @@ -320,61 +320,81 @@ int open_page_xfer(struct page_xfer *xfer, int fd_type, long id) > return open_page_local_xfer(xfer, fd_type, id); > } > > +static int page_xfer_dump_hole(struct page_xfer *xfer, > + struct iovec *hole, unsigned long off) > +{ > + BUG_ON(hole->iov_base < (void *)off); > + hole->iov_base -= off; > + pr_debug("\th %p [%u]\n", hole->iov_base, > + (unsigned int)(hole->iov_len / PAGE_SIZE)); > + > + if (xfer->write_hole(xfer, hole)) > + return -1; > + > + return 0; > +} > + > +static struct iovec get_iov(struct iovec *iovs, unsigned int n, bool compat) > +{ > + if (likely(!compat)) { > + return iovs[n]; > + } else { > + struct iovec ret; > + struct iovec_compat *tmp = (struct iovec_compat*)(void *)iovs; > + > + tmp += n; > + ret.iov_base = (void *)(uintptr_t)tmp->iov_base; > + ret.iov_len = tmp->iov_len; > + return ret; > + } > +} > + > int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp, > unsigned long off) > { > struct page_pipe_buf *ppb; > - struct iovec *hole = NULL; > + unsigned int cur_hole = 0; > + int ret; > > pr_debug("Transfering pages:\n"); > > - if (pp->free_hole) > - hole = &pp->holes[0]; > - > list_for_each_entry(ppb, &pp->bufs, l) { > - int i; > + unsigned int i; > > pr_debug("\tbuf %d/%d\n", ppb->pages_in, ppb->nr_segs); > > for (i = 0; i < ppb->nr_segs; i++) { > - struct iovec *iov = &ppb->iov[i]; > - > - while (hole && (hole->iov_base < iov->iov_base)) { > - BUG_ON(hole->iov_base < (void *)off); > - hole->iov_base -= off; > - pr_debug("\th %p [%u]\n", hole->iov_base, > - (unsigned int)(hole->iov_len / PAGE_SIZE)); > - if (xfer->write_hole(xfer, hole)) > - return -1; > - > - hole++; > - if (hole >= &pp->holes[pp->free_hole]) > - hole = NULL; > + struct iovec iov = get_iov(ppb->iov, i, pp->compat_iov); > + > + for (; cur_hole < pp->free_hole ; cur_hole++) { > + struct iovec hole = get_iov(pp->holes, cur_hole, > + pp->compat_iov); > + > + if (hole.iov_base < iov.iov_base) > + break; > + ret = page_xfer_dump_hole(xfer, &hole, off); > + if (ret) > + return ret; > } > > - BUG_ON(iov->iov_base < (void *)off); > - iov->iov_base -= off; > - pr_debug("\tp %p [%u]\n", iov->iov_base, > - (unsigned int)(iov->iov_len / PAGE_SIZE)); > + BUG_ON(iov.iov_base < (void *)off); > + iov.iov_base -= off; > + pr_debug("\tp %p [%u]\n", iov.iov_base, > + (unsigned int)(iov.iov_len / PAGE_SIZE)); > > - if (xfer->write_pagemap(xfer, iov)) > + if (xfer->write_pagemap(xfer, &iov)) > return -1; > - if (xfer->write_pages(xfer, ppb->p[0], iov->iov_len)) > + if (xfer->write_pages(xfer, ppb->p[0], iov.iov_len)) > return -1; > } > } > > - while (hole) { > - BUG_ON(hole->iov_base < (void *)off); > - hole->iov_base -= off; > - pr_debug("\th* %p [%u]\n", hole->iov_base, > - (unsigned int)(hole->iov_len / PAGE_SIZE)); > - if (xfer->write_hole(xfer, hole)) > - return -1; > + for (; cur_hole < pp->free_hole ; cur_hole++) { > + struct iovec hole = get_iov(pp->holes, cur_hole, pp->compat_iov); > > - hole++; > - if (hole >= &pp->holes[pp->free_hole]) > - hole = NULL; > + ret = page_xfer_dump_hole(xfer, &hole, off); > + if (ret) > + return ret; > } > > return 0; > -- > 2.9.0 > > _______________________________________________ > CRIU mailing list > CRIU@openvz.org > https://lists.openvz.org/mailman/listinfo/criu
On 07/05/2016 11:25 AM, Andrew Vagin wrote: > On Tue, Jun 28, 2016 at 10:24:07PM +0300, Dmitry Safonov wrote: >> Change page_xfer_dump_pages the way it could handle compatible iovs. >> Separated hole dumping in page_xfer_dump_hole and introduced >> iterator function get_iov which will return native iovec, >> converting compatible iovec if needed. >> >> Fixes: >> (00.009060) Fetched ack: 7 7 0 >> (00.009061) Transfering pages: >> (00.009062) buf 16/16 >> (00.009063) p 0x100008048000 [32841] >> (00.009101) Error (page-xfer.c:504): Only 65536 of 17592320561152 bytes have been spliced >> (00.009253) page-pipe: Killing page pipe >> (00.009263) ---------------------------------------- >> > > [root@fc22-vm criu]# ./test/zdtm.py run -t zdtm/static/env00 --pre 2 > === Run 1/1 ================ > > ========================== Run zdtm/static/env00 in h ========================== > Start test > ./env00 --pidfile=env00.pid --outfile=env00.out --envname=ENV_00_TEST > Run criu pre-dump > Run criu pre-dump > Run criu dump > Run criu restore > =[log]=> dump/zdtm/static/env00/24/3/restore.log > ------------------------ grep Error ------------------------ > (00.035223) 24: Error (mem.c:826): Page entry address 400000 outside of VMA 7fffddbcf000-7fffddbd1000 > (00.035323) Error (cr-restore.c:1885): Restoring FAILED. > ------------------------ ERROR OVER ------------------------ > ################# Test zdtm/static/env00 FAIL at CRIU restore ################## > ##################################### FAIL ##################################### > > https://github.com/xemul/criu/issues/185 The pagemap image for test becomes unsorted. >> Cc: Cyrill Gorcunov <gorcunov@openvz.org> >> Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com> >> --- >> criu/include/page-pipe.h | 6 ++++ >> criu/page-pipe.c | 6 ---- >> criu/page-xfer.c | 88 +++++++++++++++++++++++++++++------------------- >> 3 files changed, 60 insertions(+), 40 deletions(-) >> >> diff --git a/criu/include/page-pipe.h b/criu/include/page-pipe.h >> index 19e7a898e77f..474ffa004daa 100644 >> --- a/criu/include/page-pipe.h >> +++ b/criu/include/page-pipe.h >> @@ -98,6 +98,12 @@ struct page_pipe { >> bool compat_iov; /* Use compatible iovs (struct compat_iovec) */ >> }; >> >> +/* XXX: move to arch-depended file, when non-x86 add support for compat mode */ >> +struct iovec_compat { >> + u32 iov_base; >> + u32 iov_len; >> +}; >> + >> 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); >> diff --git a/criu/page-pipe.c b/criu/page-pipe.c >> index c38b96e89407..db597b27f1e2 100644 >> --- a/criu/page-pipe.c >> +++ b/criu/page-pipe.c >> @@ -100,12 +100,6 @@ 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; >> diff --git a/criu/page-xfer.c b/criu/page-xfer.c >> index 3813712fefcf..8c2c799c0b0f 100644 >> --- a/criu/page-xfer.c >> +++ b/criu/page-xfer.c >> @@ -320,61 +320,81 @@ int open_page_xfer(struct page_xfer *xfer, int fd_type, long id) >> return open_page_local_xfer(xfer, fd_type, id); >> } >> >> +static int page_xfer_dump_hole(struct page_xfer *xfer, >> + struct iovec *hole, unsigned long off) >> +{ >> + BUG_ON(hole->iov_base < (void *)off); >> + hole->iov_base -= off; >> + pr_debug("\th %p [%u]\n", hole->iov_base, >> + (unsigned int)(hole->iov_len / PAGE_SIZE)); >> + >> + if (xfer->write_hole(xfer, hole)) >> + return -1; >> + >> + return 0; >> +} >> + >> +static struct iovec get_iov(struct iovec *iovs, unsigned int n, bool compat) >> +{ >> + if (likely(!compat)) { >> + return iovs[n]; >> + } else { >> + struct iovec ret; >> + struct iovec_compat *tmp = (struct iovec_compat*)(void *)iovs; >> + >> + tmp += n; >> + ret.iov_base = (void *)(uintptr_t)tmp->iov_base; >> + ret.iov_len = tmp->iov_len; >> + return ret; >> + } >> +} >> + >> int page_xfer_dump_pages(struct page_xfer *xfer, struct page_pipe *pp, >> unsigned long off) >> { >> struct page_pipe_buf *ppb; >> - struct iovec *hole = NULL; >> + unsigned int cur_hole = 0; >> + int ret; >> >> pr_debug("Transfering pages:\n"); >> >> - if (pp->free_hole) >> - hole = &pp->holes[0]; >> - >> list_for_each_entry(ppb, &pp->bufs, l) { >> - int i; >> + unsigned int i; >> >> pr_debug("\tbuf %d/%d\n", ppb->pages_in, ppb->nr_segs); >> >> for (i = 0; i < ppb->nr_segs; i++) { >> - struct iovec *iov = &ppb->iov[i]; >> - >> - while (hole && (hole->iov_base < iov->iov_base)) { >> - BUG_ON(hole->iov_base < (void *)off); >> - hole->iov_base -= off; >> - pr_debug("\th %p [%u]\n", hole->iov_base, >> - (unsigned int)(hole->iov_len / PAGE_SIZE)); >> - if (xfer->write_hole(xfer, hole)) >> - return -1; >> - >> - hole++; >> - if (hole >= &pp->holes[pp->free_hole]) >> - hole = NULL; >> + struct iovec iov = get_iov(ppb->iov, i, pp->compat_iov); >> + >> + for (; cur_hole < pp->free_hole ; cur_hole++) { >> + struct iovec hole = get_iov(pp->holes, cur_hole, >> + pp->compat_iov); >> + >> + if (hole.iov_base < iov.iov_base) >> + break; >> + ret = page_xfer_dump_hole(xfer, &hole, off); >> + if (ret) >> + return ret; >> } >> >> - BUG_ON(iov->iov_base < (void *)off); >> - iov->iov_base -= off; >> - pr_debug("\tp %p [%u]\n", iov->iov_base, >> - (unsigned int)(iov->iov_len / PAGE_SIZE)); >> + BUG_ON(iov.iov_base < (void *)off); >> + iov.iov_base -= off; >> + pr_debug("\tp %p [%u]\n", iov.iov_base, >> + (unsigned int)(iov.iov_len / PAGE_SIZE)); >> >> - if (xfer->write_pagemap(xfer, iov)) >> + if (xfer->write_pagemap(xfer, &iov)) >> return -1; >> - if (xfer->write_pages(xfer, ppb->p[0], iov->iov_len)) >> + if (xfer->write_pages(xfer, ppb->p[0], iov.iov_len)) >> return -1; >> } >> } >> >> - while (hole) { >> - BUG_ON(hole->iov_base < (void *)off); >> - hole->iov_base -= off; >> - pr_debug("\th* %p [%u]\n", hole->iov_base, >> - (unsigned int)(hole->iov_len / PAGE_SIZE)); >> - if (xfer->write_hole(xfer, hole)) >> - return -1; >> + for (; cur_hole < pp->free_hole ; cur_hole++) { >> + struct iovec hole = get_iov(pp->holes, cur_hole, pp->compat_iov); >> >> - hole++; >> - if (hole >= &pp->holes[pp->free_hole]) >> - hole = NULL; >> + ret = page_xfer_dump_hole(xfer, &hole, off); >> + if (ret) >> + return ret; >> } >> >> return 0; >> -- >> 2.9.0 >> >> _______________________________________________ >> CRIU mailing list >> CRIU@openvz.org >> https://lists.openvz.org/mailman/listinfo/criu > . >
On 07/05/2016 02:13 PM, Pavel Emelyanov wrote: > On 07/05/2016 11:25 AM, Andrew Vagin wrote: >> On Tue, Jun 28, 2016 at 10:24:07PM +0300, Dmitry Safonov wrote: >>> Change page_xfer_dump_pages the way it could handle compatible iovs. >>> Separated hole dumping in page_xfer_dump_hole and introduced >>> iterator function get_iov which will return native iovec, >>> converting compatible iovec if needed. >>> >>> Fixes: >>> (00.009060) Fetched ack: 7 7 0 >>> (00.009061) Transfering pages: >>> (00.009062) buf 16/16 >>> (00.009063) p 0x100008048000 [32841] >>> (00.009101) Error (page-xfer.c:504): Only 65536 of 17592320561152 bytes have been spliced >>> (00.009253) page-pipe: Killing page pipe >>> (00.009263) ---------------------------------------- >>> >> >> [root@fc22-vm criu]# ./test/zdtm.py run -t zdtm/static/env00 --pre 2 >> === Run 1/1 ================ >> >> ========================== Run zdtm/static/env00 in h ========================== >> Start test >> ./env00 --pidfile=env00.pid --outfile=env00.out --envname=ENV_00_TEST >> Run criu pre-dump >> Run criu pre-dump >> Run criu dump >> Run criu restore >> =[log]=> dump/zdtm/static/env00/24/3/restore.log >> ------------------------ grep Error ------------------------ >> (00.035223) 24: Error (mem.c:826): Page entry address 400000 outside of VMA 7fffddbcf000-7fffddbd1000 >> (00.035323) Error (cr-restore.c:1885): Restoring FAILED. >> ------------------------ ERROR OVER ------------------------ >> ################# Test zdtm/static/env00 FAIL at CRIU restore ################## >> ##################################### FAIL ##################################### >> >> https://github.com/xemul/criu/issues/185 > > The pagemap image for test becomes unsorted. Yes, thanks, I have reproduced and also found image unsorted. Working on fix.
Change page_xfer_dump_pages the way it could handle compatible iovs. Separated hole dumping in page_xfer_dump_hole and introduced iterator function get_iov which will return native iovec, converting compatible iovec if needed. Fixes: (00.009060) Fetched ack: 7 7 0 (00.009061) Transfering pages: (00.009062) buf 16/16 (00.009063) p 0x100008048000 [32841] (00.009101) Error (page-xfer.c:504): Only 65536 of 17592320561152 bytes have been spliced (00.009253) page-pipe: Killing page pipe (00.009263) ---------------------------------------- Cc: Cyrill Gorcunov <gorcunov@openvz.org> Signed-off-by: Dmitry Safonov <dsafonov@virtuozzo.com> --- criu/include/page-pipe.h | 6 ++++ criu/page-pipe.c | 6 ---- criu/page-xfer.c | 88 +++++++++++++++++++++++++++++------------------- 3 files changed, 60 insertions(+), 40 deletions(-)