xen/libxc-sr-save-guest_data.patch

124 lines
4.5 KiB
Diff

From: Olaf Hering <olaf@aepfle.de>
Date: Fri, 23 Oct 2020 11:40:45 +0200
Subject: libxc sr save guest_data
tools: save: preallocate guest_data array
Remove repeated allocation from migration loop. There will never be
more than MAX_BATCH_SIZE pages to process in a batch.
Allocate the space once.
Because this was allocated with calloc:
Adjust the loop to clear unused entries as needed.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
tools/libs/guest/xg_sr_common.h | 1 +
tools/libs/guest/xg_sr_save.c | 20 +++++++++++---------
2 files changed, 12 insertions(+), 9 deletions(-)
--- a/tools/libs/guest/xg_sr_common.h
+++ b/tools/libs/guest/xg_sr_common.h
@@ -249,6 +249,7 @@ struct xc_sr_context
int *errors;
struct iovec *iov;
uint64_t *rec_pfns;
+ void **guest_data;
unsigned int nr_batch_pfns;
unsigned long *deferred_pages;
unsigned long nr_deferred_pages;
--- a/tools/libs/guest/xg_sr_save.c
+++ b/tools/libs/guest/xg_sr_save.c
@@ -89,7 +89,6 @@ static int write_batch(struct xc_sr_cont
{
xc_interface *xch = ctx->xch;
void *guest_mapping = NULL;
- void **guest_data = NULL;
void **local_pages = NULL;
int rc = -1;
unsigned int i, p, nr_pages = 0, nr_pages_mapped = 0;
@@ -103,12 +102,10 @@ static int write_batch(struct xc_sr_cont
assert(nr_pfns != 0);
- /* Pointers to page data to send. Mapped gfns or local allocations. */
- guest_data = calloc(nr_pfns, sizeof(*guest_data));
/* Pointers to locally allocated pages. Need freeing. */
local_pages = calloc(nr_pfns, sizeof(*local_pages));
- if ( !guest_data || !local_pages )
+ if ( !local_pages )
{
ERROR("Unable to allocate arrays for a batch of %u pages",
nr_pfns);
@@ -165,7 +162,10 @@ static int write_batch(struct xc_sr_cont
for ( i = 0, p = 0; i < nr_pfns; ++i )
{
if ( !page_type_has_stream_data(ctx->save.types[i]) )
+ {
+ ctx->save.guest_data[i] = NULL;
continue;
+ }
if ( ctx->save.errors[p] )
{
@@ -183,6 +183,7 @@ static int write_batch(struct xc_sr_cont
if ( rc )
{
+ ctx->save.guest_data[i] = NULL;
if ( rc == -1 && errno == EAGAIN )
{
set_bit(ctx->save.batch_pfns[i], ctx->save.deferred_pages);
@@ -194,7 +195,7 @@ static int write_batch(struct xc_sr_cont
goto err;
}
else
- guest_data[i] = page;
+ ctx->save.guest_data[i] = page;
rc = -1;
++p;
@@ -232,9 +233,9 @@ static int write_batch(struct xc_sr_cont
{
for ( i = 0; i < nr_pfns; ++i )
{
- if ( guest_data[i] )
+ if ( ctx->save.guest_data[i] )
{
- ctx->save.iov[iovcnt].iov_base = guest_data[i];
+ ctx->save.iov[iovcnt].iov_base = ctx->save.guest_data[i];
ctx->save.iov[iovcnt].iov_len = PAGE_SIZE;
iovcnt++;
--nr_pages;
@@ -258,7 +259,6 @@ static int write_batch(struct xc_sr_cont
for ( i = 0; local_pages && i < nr_pfns; ++i )
free(local_pages[i]);
free(local_pages);
- free(guest_data);
return rc;
}
@@ -836,11 +836,12 @@ static int setup(struct xc_sr_context *c
ctx->save.errors = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.errors));
ctx->save.iov = malloc((4 + MAX_BATCH_SIZE) * sizeof(*ctx->save.iov));
ctx->save.rec_pfns = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.rec_pfns));
+ ctx->save.guest_data = malloc(MAX_BATCH_SIZE * sizeof(*ctx->save.guest_data));
ctx->save.deferred_pages = bitmap_alloc(ctx->save.p2m_size);
if ( !ctx->save.batch_pfns || !ctx->save.mfns || !ctx->save.types ||
!ctx->save.errors || !ctx->save.iov || !ctx->save.rec_pfns ||
- !dirty_bitmap || !ctx->save.deferred_pages )
+ !ctx->save.guest_data ||!dirty_bitmap || !ctx->save.deferred_pages )
{
ERROR("Unable to allocate memory for dirty bitmaps, batch pfns and"
" deferred pages");
@@ -871,6 +872,7 @@ static void cleanup(struct xc_sr_context
xc_hypercall_buffer_free_pages(xch, dirty_bitmap,
NRPAGES(bitmap_size(ctx->save.p2m_size)));
free(ctx->save.deferred_pages);
+ free(ctx->save.guest_data);
free(ctx->save.rec_pfns);
free(ctx->save.iov);
free(ctx->save.errors);