From: Hongyang Yang <yanghy@cn.fujitsu.com>
To: Andrew Cooper <andrew.cooper3@citrix.com>,
Xen-devel <xen-devel@lists.xen.org>
Cc: Frediano Ziglio <frediano.ziglio@citrix.com>,
David Vrabel <david.vrabel@citrix.com>
Subject: Re: [PATCH v5 RFC 13/14] tools/libxc: noarch save code
Date: Wed, 18 Jun 2014 14:59:06 +0800 [thread overview]
Message-ID: <53A138BA.5000702@cn.fujitsu.com> (raw)
In-Reply-To: <1402510482-21099-14-git-send-email-andrew.cooper3@citrix.com>
On 06/12/2014 02:14 AM, Andrew Cooper wrote:
> Signed-off-by: Andrew Cooper <andrew.cooper3@citrix.com>
> Signed-off-by: Frediano Ziglio <frediano.ziglio@citrix.com>
> Signed-off-by: David Vrabel <david.vrabel@citrix.com>
> ---
> tools/libxc/saverestore/save.c | 545 +++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 544 insertions(+), 1 deletion(-)
>
> diff --git a/tools/libxc/saverestore/save.c b/tools/libxc/saverestore/save.c
> index f6ad734..9ad43a5 100644
> --- a/tools/libxc/saverestore/save.c
> +++ b/tools/libxc/saverestore/save.c
> @@ -1,11 +1,554 @@
> +#include <assert.h>
> +#include <arpa/inet.h>
> +
> #include "common.h"
>
> +/*
> + * Writes an Image header and Domain header into the stream.
> + */
> +static int write_headers(struct context *ctx, uint16_t guest_type)
> +{
> + xc_interface *xch = ctx->xch;
...snip...
> +/*
> + * Send all domain memory. This is the heart of the live migration loop.
> + */
> +static int send_domain_memory(struct context *ctx)
> +{
> + xc_interface *xch = ctx->xch;
> + DECLARE_HYPERCALL_BUFFER(unsigned long, to_send);
> + xc_shadow_op_stats_t stats = { -1, -1 };
> + unsigned pages_written;
> + unsigned x, max_iter = 5, dirty_threshold = 50;
> + xen_pfn_t p;
> + int rc = -1;
> +
> + to_send = xc_hypercall_buffer_alloc_pages(
> + xch, to_send, NRPAGES(bitmap_size(ctx->save.p2m_size)));
> +
> + ctx->save.batch_pfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.batch_pfns));
> + ctx->save.deferred_pages = calloc(1, bitmap_size(ctx->save.p2m_size));
> +
> + if ( !ctx->save.batch_pfns || !to_send || !ctx->save.deferred_pages )
> + {
> + ERROR("Unable to allocate memory for to_{send,fix}/batch bitmaps");
> + goto out;
> + }
> +
> + if ( xc_shadow_control(xch, ctx->domid,
> + XEN_DOMCTL_SHADOW_OP_ENABLE_LOGDIRTY,
> + NULL, 0, NULL, 0, NULL) < 0 )
> + {
> + PERROR("Failed to enable logdirty");
> + goto out;
> + }
> +
> + for ( x = 0, pages_written = 0; x < max_iter ; ++x )
> + {
> + if ( x == 0 )
> + {
> + /* First iteration, send all pages. */
> + memset(to_send, 0xff, bitmap_size(ctx->save.p2m_size));
> + }
> + else
> + {
> + /* Else consult the dirty bitmap. */
> + if ( xc_shadow_control(
> + xch, ctx->domid, XEN_DOMCTL_SHADOW_OP_CLEAN,
> + HYPERCALL_BUFFER(to_send), ctx->save.p2m_size,
> + NULL, 0, &stats) != ctx->save.p2m_size )
> + {
> + PERROR("Failed to retrieve logdirty bitmap");
> + rc = -1;
> + goto out;
> + }
> + else
> + DPRINTF(" Wrote %u pages; stats: faults %"PRIu32", dirty %"PRIu32,
> + pages_written, stats.fault_count, stats.dirty_count);
> + pages_written = 0;
> +
> + if ( stats.dirty_count < dirty_threshold )
> + break;
> + }
> +
> + DPRINTF("Iteration %u", x);
> +
> + for ( p = 0 ; p < ctx->save.p2m_size; ++p )
> + {
> + if ( test_bit(p, to_send) )
> + {
> + rc = add_to_batch(ctx, p);
> + if ( rc )
> + goto out;
> + ++pages_written;
> + }
> + }
> +
> + rc = flush_batch(ctx);
> + if ( rc )
> + goto out;
> + }
> +
> + rc = pause_domain(ctx);
> + if ( rc )
> + goto out;
> +
> + if ( xc_shadow_control(
> + xch, ctx->domid, XEN_DOMCTL_SHADOW_OP_CLEAN,
> + HYPERCALL_BUFFER(to_send), ctx->save.p2m_size,
> + NULL, 0, &stats) != ctx->save.p2m_size )
> + {
> + PERROR("Failed to retrieve logdirty bitmap");
> + rc = -1;
> + goto out;
> + }
> +
> + for ( p = 0, pages_written = 0 ; p < ctx->save.p2m_size; ++p )
> + {
> + if ( test_bit(p, to_send) || test_bit(p, ctx->save.deferred_pages) )
> + {
> + rc = add_to_batch(ctx, p);
> + if ( rc )
> + goto out;
> + ++pages_written;
> + }
> + }
> +
> + rc = flush_batch(ctx);
> + if ( rc )
> + goto out;
> +
> + DPRINTF(" Wrote %u pages", pages_written);
> + IPRINTF("Sent all pages");
> +
> + out:
> + xc_hypercall_buffer_free_pages(xch, to_send,
> + NRPAGES(bitmap_size(ctx->save.p2m_size)));
> + free(ctx->save.deferred_pages);
> + free(ctx->save.batch_pfns);
> + return rc;
> +}
> +
> +/*
> + * Save a domain.
> + */
> +static int save(struct context *ctx, uint16_t guest_type)
> +{
> + xc_interface *xch = ctx->xch;
> + int rc, saved_rc = 0, saved_errno = 0;
> +
> + IPRINTF("Saving domain %d, type %s",
> + ctx->domid, dhdr_type_to_str(guest_type));
> +
> + rc = ctx->save.ops.setup(ctx);
> + if ( rc )
> + goto err;
> +
> + rc = write_headers(ctx, guest_type);
> + if ( rc )
> + goto err;
> +
> + rc = ctx->save.ops.start_of_stream(ctx);
> + if ( rc )
> + goto err;
> +
> + rc = send_domain_memory(ctx);
> + if ( rc )
> + goto err;
> +
> + /* Refresh domain information now it has paused. */
> + if ( (xc_domain_getinfo(xch, ctx->domid, 1, &ctx->dominfo) != 1) ||
> + (ctx->dominfo.domid != ctx->domid) )
> + {
> + PERROR("Unable to refresh domain information");
> + rc = -1;
> + goto err;
> + }
> + else if ( (!ctx->dominfo.shutdown ||
> + ctx->dominfo.shutdown_reason != SHUTDOWN_suspend ) &&
> + !ctx->dominfo.paused )
> + {
> + ERROR("Domain has not been suspended");
> + rc = -1;
> + goto err;
> + }
> +
> + rc = ctx->save.ops.end_of_stream(ctx);
> + if ( rc )
> + goto err;
> +
> + rc = write_end_record(ctx);
> + if ( rc )
> + goto err;
> +
> + xc_shadow_control(xch, ctx->domid, XEN_DOMCTL_SHADOW_OP_OFF,
> + NULL, 0, NULL, 0, NULL);
If migration failed because log-dirty already been enabled or there's err after
we enabled log-dirty, we should off shadow op. otherwise we will always fail
when migration, so this op should under error path. The following patch fix it.
diff --git a/tools/libxc/saverestore/save.c b/tools/libxc/saverestore/save.c
index 9ad43a5..6e9d325 100644
--- a/tools/libxc/saverestore/save.c
+++ b/tools/libxc/saverestore/save.c
@@ -474,9 +474,6 @@ static int save(struct context *ctx, uint16_t guest_type)
if ( rc )
goto err;
- xc_shadow_control(xch, ctx->domid, XEN_DOMCTL_SHADOW_OP_OFF,
- NULL, 0, NULL, 0, NULL);
-
IPRINTF("Save successful");
goto done;
@@ -490,6 +487,9 @@ static int save(struct context *ctx, uint16_t guest_type)
if ( rc )
PERROR("Failed to clean up");
+ xc_shadow_control(xch, ctx->domid, XEN_DOMCTL_SHADOW_OP_OFF,
+ NULL, 0, NULL, 0, NULL);
+
if ( saved_rc )
{
rc = saved_rc;
> +
> + IPRINTF("Save successful");
> + goto done;
> +
> + err:
> + saved_errno = errno;
> + saved_rc = rc;
> + PERROR("Save failed");
> +
> + done:
> + rc = ctx->save.ops.cleanup(ctx);
> + if ( rc )
> + PERROR("Failed to clean up");
> +
> + if ( saved_rc )
> + {
> + rc = saved_rc;
> + errno = saved_errno;
> + }
> +
> + return rc;
> +};
> +
> int xc_domain_save2(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters,
> uint32_t max_factor, uint32_t flags,
> struct save_callbacks* callbacks, int hvm)
> {
> + struct context ctx =
> + {
> + .xch = xch,
> + .fd = io_fd,
> + };
> +
> + /* GCC 4.4 (of CentOS 6.x vintage) can' t initialise anonymous unions :( */
> + ctx.save.callbacks = callbacks;
> +
> IPRINTF("In experimental %s", __func__);
> - return -1;
> +
> + if ( xc_domain_getinfo(xch, dom, 1, &ctx.dominfo) != 1 )
> + {
> + PERROR("Failed to get domain info");
> + return -1;
> + }
> +
> + if ( ctx.dominfo.domid != dom )
> + {
> + ERROR("Domain %d does not exist", dom);
> + return -1;
> + }
> +
> + ctx.domid = dom;
> + IPRINTF("Saving domain %d", dom);
> +
> + ctx.save.p2m_size = xc_domain_maximum_gpfn(xch, dom) + 1;
> + if ( ctx.save.p2m_size > ~XEN_DOMCTL_PFINFO_LTAB_MASK )
> + {
> + errno = E2BIG;
> + ERROR("Cannot save this big a guest");
> + return -1;
> + }
> +
> + if ( ctx.dominfo.hvm )
> + {
> + ctx.ops = common_ops_x86_hvm;
> + ctx.save.ops = save_ops_x86_hvm;
> + return save(&ctx, DHDR_TYPE_X86_HVM);
> + }
> + else
> + {
> + ctx.ops = common_ops_x86_pv;
> + ctx.save.ops = save_ops_x86_pv;
> + return save(&ctx, DHDR_TYPE_X86_PV);
> + }
> }
>
> /*
>
--
Thanks,
Yang.
next prev parent reply other threads:[~2014-06-18 6:59 UTC|newest]
Thread overview: 76+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-11 18:14 [PATCH v5 0/14] Migration Stream v2 Andrew Cooper
2014-06-11 18:14 ` [PATCH v5 RFC 01/14] docs: libxc migration stream specification Andrew Cooper
2014-06-12 9:45 ` David Vrabel
2014-06-12 15:26 ` David Vrabel
2014-06-17 15:20 ` Ian Campbell
2014-06-17 17:42 ` Andrew Cooper
2014-06-17 16:40 ` Ian Campbell
2014-06-17 18:04 ` Andrew Cooper
2014-06-19 9:13 ` Hongyang Yang
2014-06-19 9:36 ` Andrew Cooper
2014-06-19 10:23 ` Hongyang Yang
2014-06-19 10:44 ` Andrew Cooper
2014-06-22 14:36 ` Shriram Rajagopalan
2014-06-22 16:01 ` Andrew Cooper
2014-06-11 18:14 ` [PATCH v5 RFC 02/14] scripts: Scripts for inspection/valdiation of legacy and new streams Andrew Cooper
2014-06-12 9:48 ` David Vrabel
2014-06-11 18:14 ` [PATCH v5 RFC 03/14] [HACK] tools/libxc: save/restore v2 framework Andrew Cooper
2014-06-17 16:00 ` Ian Campbell
2014-06-17 16:17 ` Andrew Cooper
2014-06-17 16:47 ` Ian Campbell
2014-06-11 18:14 ` [PATCH v5 RFC 04/14] tools/libxc: C implementation of stream format Andrew Cooper
2014-06-12 9:52 ` David Vrabel
2014-06-12 15:31 ` David Vrabel
2014-06-17 15:55 ` Ian Campbell
2014-06-11 18:14 ` [PATCH v5 RFC 05/14] tools/libxc: noarch common code Andrew Cooper
2014-06-12 9:55 ` David Vrabel
2014-06-17 16:10 ` Ian Campbell
2014-06-17 16:28 ` Andrew Cooper
2014-06-17 16:53 ` Ian Campbell
2014-06-17 18:26 ` Andrew Cooper
2014-06-18 9:19 ` Ian Campbell
2014-06-11 18:14 ` [PATCH v5 RFC 06/14] tools/libxc: x86 " Andrew Cooper
2014-06-12 9:57 ` David Vrabel
2014-06-17 16:11 ` Ian Campbell
2014-06-11 18:14 ` [PATCH v5 RFC 07/14] tools/libxc: x86 PV " Andrew Cooper
2014-06-12 9:59 ` David Vrabel
2014-06-11 18:14 ` [PATCH v5 RFC 08/14] tools/libxc: x86 PV save code Andrew Cooper
2014-06-12 10:04 ` David Vrabel
2014-06-11 18:14 ` [PATCH v5 RFC 09/14] tools/libxc: x86 PV restore code Andrew Cooper
2014-06-12 10:08 ` David Vrabel
2014-06-12 15:49 ` David Vrabel
2014-06-12 17:01 ` Andrew Cooper
2014-06-17 16:22 ` Ian Campbell
2014-06-11 18:14 ` [PATCH v5 RFC 10/14] tools/libxc: x86 HVM common code Andrew Cooper
2014-06-12 10:11 ` David Vrabel
2014-06-17 16:22 ` Ian Campbell
2014-06-11 18:14 ` [PATCH v5 RFC 11/14] tools/libxc: x86 HVM save code Andrew Cooper
2014-06-12 10:12 ` David Vrabel
2014-06-12 15:55 ` David Vrabel
2014-06-12 17:07 ` Andrew Cooper
2014-06-17 16:25 ` Ian Campbell
2014-06-11 18:14 ` [PATCH v5 RFC 12/14] tools/libxc: x86 HVM restore code Andrew Cooper
2014-06-12 10:14 ` David Vrabel
2014-06-11 18:14 ` [PATCH v5 RFC 13/14] tools/libxc: noarch save code Andrew Cooper
2014-06-12 10:24 ` David Vrabel
2014-06-17 16:28 ` Ian Campbell
2014-06-17 16:38 ` David Vrabel
2014-06-17 16:54 ` Ian Campbell
2014-06-18 6:59 ` Hongyang Yang [this message]
2014-06-18 7:08 ` Hongyang Yang
2014-06-19 2:48 ` Wen Congyang
2014-06-19 9:19 ` Andrew Cooper
2014-06-22 14:02 ` Shriram Rajagopalan
2014-06-11 18:14 ` [PATCH v5 RFC 14/14] tools/libxc: noarch restore code Andrew Cooper
2014-06-12 10:27 ` David Vrabel
2014-06-12 16:05 ` David Vrabel
2014-06-12 17:16 ` Andrew Cooper
2014-06-19 6:16 ` Hongyang Yang
2014-06-19 9:00 ` Andrew Cooper
2014-06-12 3:17 ` [PATCH v5 0/14] Migration Stream v2 Hongyang Yang
2014-06-12 13:27 ` Andrew Cooper
2014-06-12 13:49 ` Wei Liu
2014-06-12 14:18 ` Andrew Cooper
2014-06-12 14:27 ` Wei Liu
2014-06-12 9:38 ` David Vrabel
2014-06-17 15:57 ` Ian Campbell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=53A138BA.5000702@cn.fujitsu.com \
--to=yanghy@cn.fujitsu.com \
--cc=andrew.cooper3@citrix.com \
--cc=david.vrabel@citrix.com \
--cc=frediano.ziglio@citrix.com \
--cc=xen-devel@lists.xen.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.