xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Jennifer Herbert <Jennifer.Herbert@citrix.com>
To: Joshua Otto <jtotto@uwaterloo.ca>, xen-devel@lists.xenproject.org
Cc: wei.liu2@citrix.com, andrew.cooper3@citrix.com,
	ian.jackson@eu.citrix.com, czylin@uwaterloo.ca,
	imhy.yang@gmail.com, hjarmstr@uwaterloo.ca
Subject: Re: [PATCH RFC 07/20] migration: defer precopy policy to libxl
Date: Wed, 29 Mar 2017 19:54:15 +0100	[thread overview]
Message-ID: <58DC02D7.2030701@citrix.com> (raw)
In-Reply-To: <1490605592-12189-8-git-send-email-jtotto@uwaterloo.ca>

Hi,

I would like to encourage this patch - as I have use for it outside
of your postcopy work.

Some things people will comment on:
You've used 'unsigned' without the int keyword, which people don't like.
Also on line 324, your missing space between 'if (' and 
'ctx->save.policy_decision'.

Also, I'm not a fan of your CONSULT_POLICY macro, which you've defined at
a odd point in your function, and I think could be done more elegantly.
Worst of all ... its a macro - which I think should generally be avoided 
unless
there is little choice.   I'm sure you could write a helper function to 
replace this.

Cheers,

-jenny

On 27/03/17 10:06, Joshua Otto wrote:
> The precopy phase of the xc_domain_save() live migration algorithm has
> historically been implemented to run until either a) (almost) no pages
> are dirty or b) some fixed, hard-coded maximum number of precopy
> iterations has been exceeded.  This policy and its implementation are
> less than ideal for a few reasons:
> - the logic of the policy is intertwined with the control flow of the
>    mechanism of the precopy stage
> - it can't take into account facts external to the immediate
>    migration context, such as interactive user input or the passage of
>    wall-clock time
> - it does not permit the user to change their mind, over time, about
>    what to do at the end of the precopy (they get an unconditional
>    transition into the stop-and-copy phase of the migration)
>
> To permit users to implement arbitrary higher-level policies governing
> when the live migration precopy phase should end, and what should be
> done next:
> - add a precopy_policy() callback to the xc_domain_save() user-supplied
>    callbacks
> - during the precopy phase of live migrations, consult this policy after
>    each batch of pages transmitted and take the dictated action, which
>    may be to a) abort the migration entirely, b) continue with the
>    precopy, or c) proceed to the stop-and-copy phase.
> - provide an implementation of the old policy as such a callback in
>    libxl and plumb it through the IPC machinery to libxc, effectively
>    maintaing the old policy for now
>
> Signed-off-by: Joshua Otto <jtotto@uwaterloo.ca>
> ---
>   tools/libxc/include/xenguest.h     |  23 ++++-
>   tools/libxc/xc_nomigrate.c         |   3 +-
>   tools/libxc/xc_sr_common.h         |   7 +-
>   tools/libxc/xc_sr_save.c           | 194 ++++++++++++++++++++++++++-----------
>   tools/libxl/libxl_dom_save.c       |  20 ++++
>   tools/libxl/libxl_save_callout.c   |   3 +-
>   tools/libxl/libxl_save_helper.c    |   7 +-
>   tools/libxl/libxl_save_msgs_gen.pl |   4 +-
>   8 files changed, 189 insertions(+), 72 deletions(-)
>
> diff --git a/tools/libxc/include/xenguest.h b/tools/libxc/include/xenguest.h
> index aa8cc8b..30ffb6f 100644
> --- a/tools/libxc/include/xenguest.h
> +++ b/tools/libxc/include/xenguest.h
> @@ -39,6 +39,14 @@
>    */
>   struct xenevtchn_handle;
>   
> +/* For save's precopy_policy(). */
> +struct precopy_stats
> +{
> +    unsigned iteration;
> +    unsigned total_written;
> +    long dirty_count; /* -1 if unknown */
> +};
> +
>   /* callbacks provided by xc_domain_save */
>   struct save_callbacks {
>       /* Called after expiration of checkpoint interval,
> @@ -46,6 +54,17 @@ struct save_callbacks {
>        */
>       int (*suspend)(void* data);
>   
> +    /* Called after every batch of page data sent during the precopy phase of a
> +     * live migration to ask the caller what to do next based on the current
> +     * state of the precopy migration.
> +     */
> +#define XGS_POLICY_ABORT          (-1) /* Abandon the migration entirely and
> +                                        * tidy up. */
> +#define XGS_POLICY_CONTINUE_PRECOPY 0  /* Remain in the precopy phase. */
> +#define XGS_POLICY_STOP_AND_COPY    1  /* Immediately suspend and transmit the
> +                                        * remaining dirty pages. */
> +    int (*precopy_policy)(struct precopy_stats stats, void *data);
> +
>       /* Called after the guest's dirty pages have been
>        *  copied into an output buffer.
>        * Callback function resumes the guest & the device model,
> @@ -100,8 +119,8 @@ typedef enum {
>    *        doesn't use checkpointing
>    * @return 0 on success, -1 on failure
>    */
> -int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters,
> -                   uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
> +int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom,
> +                   uint32_t flags /* XCFLAGS_xxx */,
>                      struct save_callbacks* callbacks, int hvm,
>                      xc_migration_stream_t stream_type, int recv_fd);
>   
> diff --git a/tools/libxc/xc_nomigrate.c b/tools/libxc/xc_nomigrate.c
> index 15c838f..2af64e4 100644
> --- a/tools/libxc/xc_nomigrate.c
> +++ b/tools/libxc/xc_nomigrate.c
> @@ -20,8 +20,7 @@
>   #include <xenctrl.h>
>   #include <xenguest.h>
>   
> -int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t max_iters,
> -                   uint32_t max_factor, uint32_t flags,
> +int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom, uint32_t flags,
>                      struct save_callbacks* callbacks, int hvm,
>                      xc_migration_stream_t stream_type, int recv_fd)
>   {
> diff --git a/tools/libxc/xc_sr_common.h b/tools/libxc/xc_sr_common.h
> index b1aa88e..a9160bd 100644
> --- a/tools/libxc/xc_sr_common.h
> +++ b/tools/libxc/xc_sr_common.h
> @@ -198,12 +198,11 @@ struct xc_sr_context
>               /* Further debugging information in the stream. */
>               bool debug;
>   
> -            /* Parameters for tweaking live migration. */
> -            unsigned max_iterations;
> -            unsigned dirty_threshold;
> -
>               unsigned long p2m_size;
>   
> +            struct precopy_stats stats;
> +            int policy_decision;
> +
>               xen_pfn_t *batch_pfns;
>               unsigned nr_batch_pfns;
>               unsigned long *deferred_pages;
> diff --git a/tools/libxc/xc_sr_save.c b/tools/libxc/xc_sr_save.c
> index 797aec5..eb95334 100644
> --- a/tools/libxc/xc_sr_save.c
> +++ b/tools/libxc/xc_sr_save.c
> @@ -271,13 +271,29 @@ static int write_batch(struct xc_sr_context *ctx)
>   }
>   
>   /*
> + * Test if the batch is full.
> + */
> +static bool batch_full(struct xc_sr_context *ctx)
> +{
> +    return ctx->save.nr_batch_pfns == MAX_BATCH_SIZE;
> +}
> +
> +/*
> + * Test if the batch is empty.
> + */
> +static bool batch_empty(struct xc_sr_context *ctx)
> +{
> +    return ctx->save.nr_batch_pfns == 0;
> +}
> +
> +/*
>    * Flush a batch of pfns into the stream.
>    */
>   static int flush_batch(struct xc_sr_context *ctx)
>   {
>       int rc = 0;
>   
> -    if ( ctx->save.nr_batch_pfns == 0 )
> +    if ( batch_empty(ctx) )
>           return rc;
>   
>       rc = write_batch(ctx);
> @@ -293,19 +309,12 @@ static int flush_batch(struct xc_sr_context *ctx)
>   }
>   
>   /*
> - * Add a single pfn to the batch, flushing the batch if full.
> + * Add a single pfn to the batch.
>    */
> -static int add_to_batch(struct xc_sr_context *ctx, xen_pfn_t pfn)
> +static void add_to_batch(struct xc_sr_context *ctx, xen_pfn_t pfn)
>   {
> -    int rc = 0;
> -
> -    if ( ctx->save.nr_batch_pfns == MAX_BATCH_SIZE )
> -        rc = flush_batch(ctx);
> -
> -    if ( rc == 0 )
> -        ctx->save.batch_pfns[ctx->save.nr_batch_pfns++] = pfn;
> -
> -    return rc;
> +    assert(ctx->save.nr_batch_pfns < MAX_BATCH_SIZE);
> +    ctx->save.batch_pfns[ctx->save.nr_batch_pfns++] = pfn;
>   }
>   
>   /*
> @@ -352,10 +361,15 @@ static int suspend_domain(struct xc_sr_context *ctx)
>    * Send a subset of pages in the guests p2m, according to the dirty bitmap.
>    * Used for each subsequent iteration of the live migration loop.
>    *
> + * During the precopy stage of a live migration, test the user-supplied
> + * policy function after each batch of pages and cut off the operation
> + * early if indicated.  Unless aborting, the dirty pages remaining in this round
> + * are transferred into the deferred_pages bitmap.
> + *
>    * Bitmap is bounded by p2m_size.
>    */
>   static int send_dirty_pages(struct xc_sr_context *ctx,
> -                            unsigned long entries)
> +                            unsigned long entries, bool precopy)
>   {
>       xc_interface *xch = ctx->xch;
>       xen_pfn_t p;
> @@ -364,31 +378,57 @@ static int send_dirty_pages(struct xc_sr_context *ctx,
>       DECLARE_HYPERCALL_BUFFER_SHADOW(unsigned long, dirty_bitmap,
>                                       &ctx->save.dirty_bitmap_hbuf);
>   
> -    for ( p = 0, written = 0; p < ctx->save.p2m_size; ++p )
> +    int (*precopy_policy)(struct precopy_stats, void *) =
> +        ctx->save.callbacks->precopy_policy;
> +    void *data = ctx->save.callbacks->data;
> +
> +    assert(batch_empty(ctx));
> +    for ( p = 0, written = 0; p < ctx->save.p2m_size; )
>       {
> -        if ( !test_bit(p, dirty_bitmap) )
> -            continue;
> +        if ( ctx->save.live && precopy )
> +        {
> +            ctx->save.policy_decision = precopy_policy(ctx->save.stats, data);
> +            if ( ctx->save.policy_decision == XGS_POLICY_ABORT )
> +            {
> +                return -1;
> +            }
> +            else if ( ctx->save.policy_decision != XGS_POLICY_CONTINUE_PRECOPY )
> +            {
> +                /* Any outstanding dirty pages are now deferred until the next
> +                 * phase of the migration. */
> +                bitmap_or(ctx->save.deferred_pages, dirty_bitmap,
> +                          ctx->save.p2m_size);
> +                if ( entries > written )
> +                    ctx->save.nr_deferred_pages += entries - written;
> +
> +                goto done;
> +            }
> +        }
>   
> -        rc = add_to_batch(ctx, p);
> +        for ( ; p < ctx->save.p2m_size && !batch_full(ctx); ++p )
> +        {
> +            if ( test_and_clear_bit(p, dirty_bitmap) )
> +            {
> +                add_to_batch(ctx, p);
> +                ++written;
> +                ++ctx->save.stats.total_written;
> +            }
> +        }
> +
> +        rc = flush_batch(ctx);
>           if ( rc )
>               return rc;
>   
> -        /* Update progress every 4MB worth of memory sent. */
> -        if ( (written & ((1U << (22 - 12)) - 1)) == 0 )
> -            xc_report_progress_step(xch, written, entries);
> -
> -        ++written;
> +        /* Update progress after every batch (4MB) worth of memory sent. */
> +        xc_report_progress_step(xch, written, entries);
>       }
>   
> -    rc = flush_batch(ctx);
> -    if ( rc )
> -        return rc;
> -
>       if ( written > entries )
>           DPRINTF("Bitmap contained more entries than expected...");
>   
>       xc_report_progress_step(xch, entries, entries);
>   
> + done:
>       return ctx->save.ops.check_vm_state(ctx);
>   }
>   
> @@ -396,14 +436,14 @@ static int send_dirty_pages(struct xc_sr_context *ctx,
>    * Send all pages in the guests p2m.  Used as the first iteration of the live
>    * migration loop, and for a non-live save.
>    */
> -static int send_all_pages(struct xc_sr_context *ctx)
> +static int send_all_pages(struct xc_sr_context *ctx, bool precopy)
>   {
>       DECLARE_HYPERCALL_BUFFER_SHADOW(unsigned long, dirty_bitmap,
>                                       &ctx->save.dirty_bitmap_hbuf);
>   
>       bitmap_set(dirty_bitmap, ctx->save.p2m_size);
>   
> -    return send_dirty_pages(ctx, ctx->save.p2m_size);
> +    return send_dirty_pages(ctx, ctx->save.p2m_size, precopy);
>   }
>   
>   static int enable_logdirty(struct xc_sr_context *ctx)
> @@ -446,8 +486,7 @@ static int update_progress_string(struct xc_sr_context *ctx,
>       xc_interface *xch = ctx->xch;
>       char *new_str = NULL;
>   
> -    if ( asprintf(&new_str, "Frames iteration %u of %u",
> -                  iter, ctx->save.max_iterations) == -1 )
> +    if ( asprintf(&new_str, "Frames iteration %u", iter) == -1 )
>       {
>           PERROR("Unable to allocate new progress string");
>           return -1;
> @@ -468,20 +507,47 @@ static int send_memory_live(struct xc_sr_context *ctx)
>       xc_interface *xch = ctx->xch;
>       xc_shadow_op_stats_t stats = { 0, ctx->save.p2m_size };
>       char *progress_str = NULL;
> -    unsigned x;
>       int rc;
>   
> +    DECLARE_HYPERCALL_BUFFER_SHADOW(unsigned long, dirty_bitmap,
> +                                    &ctx->save.dirty_bitmap_hbuf);
> +
> +    int (*precopy_policy)(struct precopy_stats, void *) =
> +        ctx->save.callbacks->precopy_policy;
> +    void *data = ctx->save.callbacks->data;
> +
>       rc = update_progress_string(ctx, &progress_str, 0);
>       if ( rc )
>           goto out;
>   
> -    rc = send_all_pages(ctx);
> +#define CONSULT_POLICY                                                        \
> +    do {                                                                      \
> +        if ( ctx->save.policy_decision == XGS_POLICY_ABORT )                  \
> +        {                                                                     \
> +            rc = -1;                                                          \
> +            goto out;                                                         \
> +        }                                                                     \
> +        else if ( ctx->save.policy_decision != XGS_POLICY_CONTINUE_PRECOPY )  \
> +        {                                                                     \
> +            rc = 0;                                                           \
> +            goto out;                                                         \
> +        }                                                                     \
> +    } while (0)
> +
> +    ctx->save.stats = (struct precopy_stats)
> +        {
> +            .iteration     = 0,
> +            .total_written = 0,
> +            .dirty_count   = -1
> +        };
> +    rc = send_all_pages(ctx, /* precopy */ true);
>       if ( rc )
>           goto out;
>   
> -    for ( x = 1;
> -          ((x < ctx->save.max_iterations) &&
> -           (stats.dirty_count > ctx->save.dirty_threshold)); ++x )
> +    /* send_all_pages() has updated the stats */
> +    CONSULT_POLICY;
> +
> +    for ( ctx->save.stats.iteration = 1; ; ++ctx->save.stats.iteration )
>       {
>           if ( xc_shadow_control(
>                    xch, ctx->domid, XEN_DOMCTL_SHADOW_OP_CLEAN,
> @@ -493,18 +559,42 @@ static int send_memory_live(struct xc_sr_context *ctx)
>               goto out;
>           }
>   
> -        if ( stats.dirty_count == 0 )
> -            break;
> +        /* Check the new dirty_count against the policy. */
> +        ctx->save.stats.dirty_count = stats.dirty_count;
> +        ctx->save.policy_decision = precopy_policy(ctx->save.stats, data);
> +        if ( ctx->save.policy_decision == XGS_POLICY_ABORT )
> +        {
> +            rc = -1;
> +            goto out;
> +        }
> +        else if (ctx->save.policy_decision != XGS_POLICY_CONTINUE_PRECOPY )
> +        {
> +            bitmap_or(ctx->save.deferred_pages, dirty_bitmap,
> +                      ctx->save.p2m_size);
> +            ctx->save.nr_deferred_pages += stats.dirty_count;
> +            rc = 0;
> +            goto out;
> +        }
> +
> +        /* After this point we won't know how many pages are really dirty until
> +         * the next iteration. */
> +        ctx->save.stats.dirty_count = -1;
>   
> -        rc = update_progress_string(ctx, &progress_str, x);
> +        rc = update_progress_string(ctx, &progress_str,
> +                                    ctx->save.stats.iteration);
>           if ( rc )
>               goto out;
>   
> -        rc = send_dirty_pages(ctx, stats.dirty_count);
> +        rc = send_dirty_pages(ctx, stats.dirty_count, /* precopy */ true);
>           if ( rc )
>               goto out;
> +
> +        /* send_dirty_pages() has updated the stats */
> +        CONSULT_POLICY;
>       }
>   
> +#undef CONSULT_POLICY
> +
>    out:
>       xc_set_progress_prefix(xch, NULL);
>       free(progress_str);
> @@ -595,7 +685,7 @@ static int suspend_and_send_dirty(struct xc_sr_context *ctx)
>       if ( ctx->save.live )
>       {
>           rc = update_progress_string(ctx, &progress_str,
> -                                    ctx->save.max_iterations);
> +                                    ctx->save.stats.iteration);
>           if ( rc )
>               goto out;
>       }
> @@ -614,7 +704,8 @@ static int suspend_and_send_dirty(struct xc_sr_context *ctx)
>           }
>       }
>   
> -    rc = send_dirty_pages(ctx, stats.dirty_count + ctx->save.nr_deferred_pages);
> +    rc = send_dirty_pages(ctx, stats.dirty_count + ctx->save.nr_deferred_pages,
> +                          /* precopy */ false);
>       if ( rc )
>           goto out;
>   
> @@ -645,7 +736,7 @@ static int verify_frames(struct xc_sr_context *ctx)
>           goto out;
>   
>       xc_set_progress_prefix(xch, "Frames verify");
> -    rc = send_all_pages(ctx);
> +    rc = send_all_pages(ctx, /* precopy */ false);
>       if ( rc )
>           goto out;
>   
> @@ -719,7 +810,7 @@ static int send_domain_memory_nonlive(struct xc_sr_context *ctx)
>   
>       xc_set_progress_prefix(xch, "Frames");
>   
> -    rc = send_all_pages(ctx);
> +    rc = send_all_pages(ctx, /* precopy */ false);
>       if ( rc )
>           goto err;
>   
> @@ -910,8 +1001,7 @@ static int save(struct xc_sr_context *ctx, uint16_t guest_type)
>   };
>   
>   int xc_domain_save(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,
> +                   uint32_t flags, struct save_callbacks* callbacks, int hvm,
>                      xc_migration_stream_t stream_type, int recv_fd)
>   {
>       struct xc_sr_context ctx =
> @@ -932,25 +1022,17 @@ int xc_domain_save(xc_interface *xch, int io_fd, uint32_t dom,
>              stream_type == XC_MIG_STREAM_REMUS ||
>              stream_type == XC_MIG_STREAM_COLO);
>   
> -    /*
> -     * TODO: Find some time to better tweak the live migration algorithm.
> -     *
> -     * These parameters are better than the legacy algorithm especially for
> -     * busy guests.
> -     */
> -    ctx.save.max_iterations = 5;
> -    ctx.save.dirty_threshold = 50;
> -
>       /* Sanity checks for callbacks. */
>       if ( hvm )
>           assert(callbacks->switch_qemu_logdirty);
> +    if ( ctx.save.live )
> +        assert(callbacks->precopy_policy);
>       if ( ctx.save.checkpointed )
>           assert(callbacks->checkpoint && callbacks->aftercopy);
>       if ( ctx.save.checkpointed == XC_MIG_STREAM_COLO )
>           assert(callbacks->wait_checkpoint);
>   
> -    DPRINTF("fd %d, dom %u, max_iters %u, max_factor %u, flags %u, hvm %d",
> -            io_fd, dom, max_iters, max_factor, flags, hvm);
> +    DPRINTF("fd %d, dom %u, flags %u, hvm %d", io_fd, dom, flags, hvm);
>   
>       if ( xc_domain_getinfo(xch, dom, 1, &ctx.dominfo) != 1 )
>       {
> diff --git a/tools/libxl/libxl_dom_save.c b/tools/libxl/libxl_dom_save.c
> index 77fe30e..6d28cce 100644
> --- a/tools/libxl/libxl_dom_save.c
> +++ b/tools/libxl/libxl_dom_save.c
> @@ -328,6 +328,25 @@ int libxl__save_emulator_xenstore_data(libxl__domain_save_state *dss,
>       return rc;
>   }
>   
> +/*
> + * This is the live migration precopy policy - it's called periodically during
> + * the precopy phase of live migrations, and is responsible for deciding when
> + * the precopy phase should terminate and what should be done next.
> + *
> + * The policy implemented here behaves identically to the policy previously
> + * hard-coded into xc_domain_save() - it proceeds to the stop-and-copy phase of
> + * the live migration when there are either fewer than 50 dirty pages, or more
> + * than 5 precopy rounds have completed.
> + */
> +static int libxl__save_live_migration_simple_precopy_policy(
> +    struct precopy_stats stats, void *user)
> +{
> +    return ((stats.dirty_count >= 0 && stats.dirty_count < 50) ||
> +            stats.iteration >= 5)
> +        ? XGS_POLICY_STOP_AND_COPY
> +        : XGS_POLICY_CONTINUE_PRECOPY;
> +}
> +
>   /*----- main code for saving, in order of execution -----*/
>   
>   void libxl__domain_save(libxl__egc *egc, libxl__domain_save_state *dss)
> @@ -401,6 +420,7 @@ void libxl__domain_save(libxl__egc *egc, libxl__domain_save_state *dss)
>       if (dss->checkpointed_stream == LIBXL_CHECKPOINTED_STREAM_NONE)
>           callbacks->suspend = libxl__domain_suspend_callback;
>   
> +    callbacks->precopy_policy = libxl__save_live_migration_simple_precopy_policy;
>       callbacks->switch_qemu_logdirty = libxl__domain_suspend_common_switch_qemu_logdirty;
>   
>       dss->sws.ao  = dss->ao;
> diff --git a/tools/libxl/libxl_save_callout.c b/tools/libxl/libxl_save_callout.c
> index 46b892c..026b572 100644
> --- a/tools/libxl/libxl_save_callout.c
> +++ b/tools/libxl/libxl_save_callout.c
> @@ -89,8 +89,7 @@ void libxl__xc_domain_save(libxl__egc *egc, libxl__domain_save_state *dss,
>           libxl__srm_callout_enumcallbacks_save(&shs->callbacks.save.a);
>   
>       const unsigned long argnums[] = {
> -        dss->domid, 0, 0, dss->xcflags, dss->hvm,
> -        cbflags, dss->checkpointed_stream,
> +        dss->domid, dss->xcflags, dss->hvm, cbflags, dss->checkpointed_stream,
>       };
>   
>       shs->ao = ao;
> diff --git a/tools/libxl/libxl_save_helper.c b/tools/libxl/libxl_save_helper.c
> index d3def6b..0241a6b 100644
> --- a/tools/libxl/libxl_save_helper.c
> +++ b/tools/libxl/libxl_save_helper.c
> @@ -251,8 +251,6 @@ int main(int argc, char **argv)
>           io_fd =                             atoi(NEXTARG);
>           recv_fd =                           atoi(NEXTARG);
>           uint32_t dom =                      strtoul(NEXTARG,0,10);
> -        uint32_t max_iters =                strtoul(NEXTARG,0,10);
> -        uint32_t max_factor =               strtoul(NEXTARG,0,10);
>           uint32_t flags =                    strtoul(NEXTARG,0,10);
>           int hvm =                           atoi(NEXTARG);
>           unsigned cbflags =                  strtoul(NEXTARG,0,10);
> @@ -264,9 +262,8 @@ int main(int argc, char **argv)
>           startup("save");
>           setup_signals(save_signal_handler);
>   
> -        r = xc_domain_save(xch, io_fd, dom, max_iters, max_factor, flags,
> -                           &helper_save_callbacks, hvm, stream_type,
> -                           recv_fd);
> +        r = xc_domain_save(xch, io_fd, dom, flags, &helper_save_callbacks, hvm,
> +                           stream_type, recv_fd);
>           complete(r);
>   
>       } else if (!strcmp(mode,"--restore-domain")) {
> diff --git a/tools/libxl/libxl_save_msgs_gen.pl b/tools/libxl/libxl_save_msgs_gen.pl
> index 27845bb..50c97b4 100755
> --- a/tools/libxl/libxl_save_msgs_gen.pl
> +++ b/tools/libxl/libxl_save_msgs_gen.pl
> @@ -33,6 +33,7 @@ our @msgs = (
>                                                 'xen_pfn_t', 'console_gfn'] ],
>       [  9, 'srW',    "complete",              [qw(int retval
>                                                    int errnoval)] ],
> +    [ 10, 'scxW',   "precopy_policy", ['struct precopy_stats', 'stats'] ]
>   );
>   
>   #----------------------------------------
> @@ -141,7 +142,8 @@ static void bytes_put(unsigned char *const buf, int *len,
>   
>   END
>   
> -foreach my $simpletype (qw(int uint16_t uint32_t unsigned), 'unsigned long', 'xen_pfn_t') {
> +foreach my $simpletype (qw(int uint16_t uint32_t unsigned),
> +                        'unsigned long', 'xen_pfn_t', 'struct precopy_stats') {
>       my $typeid = typeid($simpletype);
>       $out_body{'callout'} .= <<END;
>   static int ${typeid}_get(const unsigned char **msg,


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

  reply	other threads:[~2017-03-29 18:54 UTC|newest]

Thread overview: 53+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-03-27  9:06 [PATCH RFC 00/20] Add postcopy live migration support Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 01/20] tools: rename COLO 'postcopy' to 'aftercopy' Joshua Otto
2017-03-28 16:34   ` Wei Liu
2017-04-11  6:19     ` Zhang Chen
2017-03-27  9:06 ` [PATCH RFC 02/20] libxc/xc_sr: parameterise write_record() on fd Joshua Otto
2017-03-28 18:53   ` Andrew Cooper
2017-03-31 14:19   ` Wei Liu
2017-03-27  9:06 ` [PATCH RFC 03/20] libxc/xc_sr_restore.c: use write_record() in send_checkpoint_dirty_pfn_list() Joshua Otto
2017-03-28 18:56   ` Andrew Cooper
2017-03-31 14:19   ` Wei Liu
2017-03-27  9:06 ` [PATCH RFC 04/20] libxc/xc_sr_save.c: add WRITE_TRIVIAL_RECORD_FN() Joshua Otto
2017-03-28 19:03   ` Andrew Cooper
2017-03-30  4:28     ` Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 05/20] libxc/xc_sr: factor out filter_pages() Joshua Otto
2017-03-28 19:27   ` Andrew Cooper
2017-03-30  4:42     ` Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 06/20] libxc/xc_sr: factor helpers out of handle_page_data() Joshua Otto
2017-03-28 19:52   ` Andrew Cooper
2017-03-30  4:49     ` Joshua Otto
2017-04-12 15:16       ` Wei Liu
2017-03-27  9:06 ` [PATCH RFC 07/20] migration: defer precopy policy to libxl Joshua Otto
2017-03-29 18:54   ` Jennifer Herbert [this message]
2017-03-30  5:28     ` Joshua Otto
2017-03-29 20:18   ` Andrew Cooper
2017-03-30  5:19     ` Joshua Otto
2017-04-12 15:16       ` Wei Liu
2017-04-18 17:56         ` Ian Jackson
2017-03-27  9:06 ` [PATCH RFC 08/20] libxl/migration: add precopy tuning parameters Joshua Otto
2017-03-29 21:08   ` Andrew Cooper
2017-03-30  6:03     ` Joshua Otto
2017-04-12 15:37       ` Wei Liu
2017-04-27 22:51         ` Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 09/20] libxc/xc_sr_save: introduce save batch types Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 10/20] libxc/xc_sr_save.c: initialise rec.data before free() Joshua Otto
2017-03-28 19:59   ` Andrew Cooper
2017-03-29 17:47     ` Wei Liu
2017-03-27  9:06 ` [PATCH RFC 11/20] libxc/migration: correct hvm record ordering specification Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 12/20] libxc/migration: specify postcopy live migration Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 13/20] libxc/migration: add try_read_record() Joshua Otto
2017-04-12 15:16   ` Wei Liu
2017-03-27  9:06 ` [PATCH RFC 14/20] libxc/migration: implement the sender side of postcopy live migration Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 15/20] libxc/migration: implement the receiver " Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 16/20] libxl/libxl_stream_write.c: track callback chains with an explicit phase Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 17/20] libxl/libxl_stream_read.c: " Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 18/20] libxl/migration: implement the sender side of postcopy live migration Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 19/20] libxl/migration: implement the receiver " Joshua Otto
2017-03-27  9:06 ` [PATCH RFC 20/20] tools: expose postcopy live migration support in libxl and xl Joshua Otto
2017-03-28 14:41 ` [PATCH RFC 00/20] Add postcopy live migration support Wei Liu
2017-03-30  4:13   ` Joshua Otto
2017-03-31 14:19     ` Wei Liu
2017-03-29 22:50 ` Andrew Cooper
2017-03-31  4:51   ` Joshua Otto
2017-04-12 15:38     ` Wei Liu

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=58DC02D7.2030701@citrix.com \
    --to=jennifer.herbert@citrix.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=czylin@uwaterloo.ca \
    --cc=hjarmstr@uwaterloo.ca \
    --cc=ian.jackson@eu.citrix.com \
    --cc=imhy.yang@gmail.com \
    --cc=jtotto@uwaterloo.ca \
    --cc=wei.liu2@citrix.com \
    --cc=xen-devel@lists.xenproject.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).