[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v10 19/31] libxc/restore: send dirty pfn list to primary when checkpoint under colo
Send dirty pfn list to primary when checkpoint under colo. Signed-off-by: Yang Hongyang <hongyang.yang@xxxxxxxxxxxx> Signed-off-by: Wen Congyang <wency@xxxxxxxxxxxxxx> --- tools/libxc/xc_sr_common.h | 4 ++ tools/libxc/xc_sr_restore.c | 120 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 123 insertions(+), 1 deletion(-) diff --git a/tools/libxc/xc_sr_common.h b/tools/libxc/xc_sr_common.h index a24a9ad..29ab4eb 100644 --- a/tools/libxc/xc_sr_common.h +++ b/tools/libxc/xc_sr_common.h @@ -226,6 +226,10 @@ struct xc_sr_context struct xc_sr_restore_ops ops; struct restore_callbacks *callbacks; + int send_back_fd; + unsigned long p2m_size; + xc_hypercall_buffer_t dirty_bitmap_hbuf; + /* From Image Header. */ uint32_t format_version; diff --git a/tools/libxc/xc_sr_restore.c b/tools/libxc/xc_sr_restore.c index 2ae8154..37c0416 100644 --- a/tools/libxc/xc_sr_restore.c +++ b/tools/libxc/xc_sr_restore.c @@ -411,6 +411,92 @@ static int handle_page_data(struct xc_sr_context *ctx, struct xc_sr_record *rec) return rc; } +/* + * Send checkpoint dirty pfn list to primary. + */ +static int send_checkpoint_dirty_pfn_list(struct xc_sr_context *ctx) +{ + xc_interface *xch = ctx->xch; + int rc = -1; + unsigned count, written; + uint64_t i, *pfns = NULL; + struct iovec *iov = NULL; + xc_shadow_op_stats_t stats = { 0, ctx->restore.p2m_size }; + struct xc_sr_record rec = + { + .type = REC_TYPE_CHECKPOINT_DIRTY_PFN_LIST, + }; + DECLARE_HYPERCALL_BUFFER_SHADOW(unsigned long, dirty_bitmap, + &ctx->restore.dirty_bitmap_hbuf); + + if ( xc_shadow_control( + xch, ctx->domid, XEN_DOMCTL_SHADOW_OP_CLEAN, + HYPERCALL_BUFFER(dirty_bitmap), ctx->restore.p2m_size, + NULL, 0, &stats) != ctx->restore.p2m_size ) + { + PERROR("Failed to retrieve logdirty bitmap"); + goto err; + } + + for ( i = 0, count = 0; i < ctx->restore.p2m_size; i++ ) + { + if ( test_bit(i, dirty_bitmap) ) + count++; + } + + + pfns = malloc(count * sizeof(*pfns)); + if ( !pfns ) + { + ERROR("Unable to allocate %zu bytes of memory for dirty pfn list", + count * sizeof(*pfns)); + goto err; + } + + for ( i = 0, written = 0; i < ctx->restore.p2m_size; ++i ) + { + if ( !test_bit(i, dirty_bitmap) ) + continue; + + if ( written > count ) + { + ERROR("Dirty pfn list exceed"); + goto err; + } + + pfns[written++] = i; + } + + /* iovec[] for writev(). */ + iov = malloc(3 * sizeof(*iov)); + if ( !iov ) + { + ERROR("Unable to allocate memory for sending dirty bitmap"); + goto err; + } + + rec.length = count * sizeof(*pfns); + + iov[0].iov_base = &rec.type; + iov[0].iov_len = sizeof(rec.type); + + iov[1].iov_base = &rec.length; + iov[1].iov_len = sizeof(rec.length); + + iov[2].iov_base = pfns; + iov[2].iov_len = count * sizeof(*pfns); + + if ( writev_exact(ctx->restore.send_back_fd, iov, 3) ) + { + PERROR("Failed to write dirty bitmap to stream"); + goto err; + } + + rc = 0; + err: + return rc; +} + static int process_record(struct xc_sr_context *ctx, struct xc_sr_record *rec); static int handle_checkpoint(struct xc_sr_context *ctx) { @@ -500,7 +586,9 @@ static int handle_checkpoint(struct xc_sr_context *ctx) #undef HANDLE_CALLBACK_RETURN_VALUE - /* TODO: send dirty pfn list to primary */ + rc = send_checkpoint_dirty_pfn_list(ctx); + if ( rc ) + goto err; } err: @@ -572,6 +660,21 @@ static int setup(struct xc_sr_context *ctx) { xc_interface *xch = ctx->xch; int rc; + DECLARE_HYPERCALL_BUFFER_SHADOW(unsigned long, dirty_bitmap, + &ctx->restore.dirty_bitmap_hbuf); + + if ( ctx->restore.checkpointed == MIG_STREAM_COLO ) + { + dirty_bitmap = xc_hypercall_buffer_alloc_pages(xch, dirty_bitmap, + NRPAGES(bitmap_size(ctx->restore.p2m_size))); + + if ( !dirty_bitmap ) + { + ERROR("Unable to allocate memory for dirty bitmap"); + rc = -1; + goto err; + } + } rc = ctx->restore.ops.setup(ctx); if ( rc ) @@ -605,10 +708,15 @@ static void cleanup(struct xc_sr_context *ctx) { xc_interface *xch = ctx->xch; unsigned i; + DECLARE_HYPERCALL_BUFFER_SHADOW(unsigned long, dirty_bitmap, + &ctx->restore.dirty_bitmap_hbuf); for ( i = 0; i < ctx->restore.buffered_rec_num; i++ ) free(ctx->restore.buffered_records[i].data); + if ( ctx->restore.checkpointed == MIG_STREAM_COLO ) + xc_hypercall_buffer_free_pages(xch, dirty_bitmap, + NRPAGES(bitmap_size(ctx->restore.p2m_size))); free(ctx->restore.buffered_records); free(ctx->restore.populated_pfns); if ( ctx->restore.ops.cleanup(ctx) ) @@ -719,6 +827,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom, int checkpointed_stream, struct restore_callbacks *callbacks, int send_back_fd) { + xen_pfn_t nr_pfns; struct xc_sr_context ctx = { .xch = xch, @@ -732,6 +841,7 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom, ctx.restore.xenstore_domid = store_domid; ctx.restore.checkpointed = checkpointed_stream; ctx.restore.callbacks = callbacks; + ctx.restore.send_back_fd = send_back_fd; /* Sanity checks for callbacks. */ if ( checkpointed_stream ) @@ -766,6 +876,14 @@ int xc_domain_restore(xc_interface *xch, int io_fd, uint32_t dom, if ( read_headers(&ctx) ) return -1; + if ( xc_domain_nr_gpfns(xch, dom, &nr_pfns) < 0 ) + { + PERROR("Unable to obtain the guest p2m size"); + return -1; + } + + ctx.restore.p2m_size = nr_pfns; + if ( ctx.dominfo.hvm ) { ctx.restore.ops = restore_ops_x86_hvm; -- 2.5.0 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |