[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH Remus v1 1/8] tools/libxc: adjust the memory allocation for migration



On 07/05/15 07:37, Yang Hongyang wrote:
> Move the memory allocation before the concrete live/nolive save
> in order to avoid the free/alloc memory loop when using Remus.
>
> Signed-off-by: Yang Hongyang <yanghy@xxxxxxxxxxxxxx>
> ---
>  tools/libxc/xc_sr_save.c | 53 
> +++++++++++++++++++-----------------------------
>  1 file changed, 21 insertions(+), 32 deletions(-)
>
> diff --git a/tools/libxc/xc_sr_save.c b/tools/libxc/xc_sr_save.c
> index 5d9c267..7fed668 100644
> --- a/tools/libxc/xc_sr_save.c
> +++ b/tools/libxc/xc_sr_save.c
> @@ -3,6 +3,8 @@
>  
>  #include "xc_sr_common.h"
>  
> +DECLARE_HYPERCALL_BUFFER(unsigned long, to_send);

This unfortunately causes an issue when concurrent calls to
xc_domain_save() in the same process.  While this is a highly
ill-advised action, I did try to avoid breaking it.

Please move this declaration into the ctx.save union.

> +
>  /*
>   * Writes an Image header and Domain header into the stream.
>   */
> @@ -475,25 +477,11 @@ static int update_progress_string(struct xc_sr_context 
> *ctx,
>  static int send_domain_memory_live(struct xc_sr_context *ctx)
>  {
>      xc_interface *xch = ctx->xch;
> -    DECLARE_HYPERCALL_BUFFER(unsigned long, to_send);
>      xc_shadow_op_stats_t stats = { 0, ctx->save.p2m_size };
>      char *progress_str = NULL;
>      unsigned x;
>      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;
> -    }
> -
>      rc = enable_logdirty(ctx);
>      if ( rc )
>          goto out;
> @@ -593,10 +581,6 @@ static int send_domain_memory_live(struct xc_sr_context 
> *ctx)
>    out:
>      xc_set_progress_prefix(xch, NULL);
>      free(progress_str);
> -    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;
>  }
>  
> @@ -609,17 +593,6 @@ static int send_domain_memory_nonlive(struct 
> xc_sr_context *ctx)
>      xc_interface *xch = ctx->xch;
>      int rc = -1;
>  
> -    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 || !ctx->save.deferred_pages )
> -    {
> -        PERROR("Failed to allocate memory for nonlive tracking structures");
> -        errno = ENOMEM;
> -        goto err;
> -    }
> -
>      rc = suspend_domain(ctx);
>      if ( rc )
>          goto err;
> @@ -631,9 +604,6 @@ static int send_domain_memory_nonlive(struct 
> xc_sr_context *ctx)
>          goto err;
>  
>   err:
> -    free(ctx->save.deferred_pages);
> -    free(ctx->save.batch_pfns);
> -
>      return rc;
>  }
>  
> @@ -645,6 +615,20 @@ static int save(struct xc_sr_context *ctx, uint16_t 
> guest_type)
>      xc_interface *xch = ctx->xch;
>      int rc, saved_rc = 0, saved_errno = 0;
>  
> +    to_send = xc_hypercall_buffer_alloc_pages(
> +                        xch, to_send, 
> NRPAGES(bitmap_size(ctx->save.p2m_size)));

This allocation only needs to be made if ctx->save.live is set.  For
plain suspend and resume, logdirty handling is not required.

> +    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");
> +        rc = -1;
> +        errno = ENOMEM;
> +        goto err;
> +    }
> +

Instead of complicating save() like this, could you introduce two new
static functions setup() and cleanup() which subsume the
ctx->save.ops.{setup,cleanup}() calls and also do these allocations and
free.

I think the SHADOW_OP_OFF hypercall can also be moved into the cleanup()
function.

~Andrew

>      IPRINTF("Saving domain %d, type %s",
>              ctx->domid, dhdr_type_to_str(guest_type));
>  
> @@ -704,6 +688,11 @@ static int save(struct xc_sr_context *ctx, uint16_t 
> guest_type)
>      if ( rc )
>          PERROR("Failed to clean up");
>  
> +    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);
> +
>      if ( saved_rc )
>      {
>          rc = saved_rc;


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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.