[CRIU] [PATCHv3 14/30] page-xfer: dump compatible iovec
Pavel Emelyanov
xemul at virtuozzo.com
Tue Jul 5 04:13:24 PDT 2016
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 at 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 at openvz.org>
>> Signed-off-by: Dmitry Safonov <dsafonov at 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 at openvz.org
>> https://lists.openvz.org/mailman/listinfo/criu
> .
>
More information about the CRIU
mailing list