|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v4 15/16] libs/guest: finalize PoC
From: Frediano Ziglio <frediano.ziglio@xxxxxxxxxx>
Remove now unused map_errs array.
Test and restore verification code.
Report correctly errors from writev_exact.
Allocate verification buffer using hypercall buffer to avoid errors
using hypercall.
Signed-off-by: Frediano Ziglio <frediano.ziglio@xxxxxxxxxx>
---
tools/libs/guest/xg_sr_common.h | 4 +-
tools/libs/guest/xg_sr_restore.c | 48 +++++++++++++++---
tools/libs/guest/xg_sr_save.c | 83 +++++++++++++++++++++-----------
3 files changed, 100 insertions(+), 35 deletions(-)
diff --git a/tools/libs/guest/xg_sr_common.h b/tools/libs/guest/xg_sr_common.h
index 0e0e279ae1..cd562f028a 100644
--- a/tools/libs/guest/xg_sr_common.h
+++ b/tools/libs/guest/xg_sr_common.h
@@ -214,7 +214,6 @@ struct xc_sr_context_save_buffers
xen_pfn_t batch_pfns[MAX_BATCH_SIZE];
xen_pfn_t mfns[MAX_BATCH_SIZE];
xen_pfn_t types[MAX_BATCH_SIZE];
- int errors[MAX_BATCH_SIZE];
void *local_pages[MAX_BATCH_SIZE];
struct iovec iov[MAX_BATCH_SIZE + 2]; /* Headers + data. */
uint64_t rec_pfns[MAX_BATCH_SIZE];
@@ -255,8 +254,8 @@ struct xc_sr_context
unsigned long *deferred_pages;
unsigned long nr_deferred_pages;
xc_hypercall_buffer_t dirty_bitmap_hbuf;
+ xc_hypercall_buffer_t dest_buf;
struct xc_sr_context_save_buffers *buffers;
- void *dest_buf;
} save;
struct /* Restore data. */
@@ -267,6 +266,7 @@ struct xc_sr_context
int send_back_fd;
unsigned long p2m_size;
xc_hypercall_buffer_t dirty_bitmap_hbuf;
+ xc_hypercall_buffer_t verify_buf;
/* From Image Header. */
uint32_t format_version;
diff --git a/tools/libs/guest/xg_sr_restore.c b/tools/libs/guest/xg_sr_restore.c
index b589f0397d..b2df36c6f6 100644
--- a/tools/libs/guest/xg_sr_restore.c
+++ b/tools/libs/guest/xg_sr_restore.c
@@ -257,15 +257,15 @@ static int process_page_data(struct xc_sr_context *ctx,
unsigned int count,
{
xc_interface *xch = ctx->xch;
xen_pfn_t *mfns = malloc(count * sizeof(*mfns));
- int *map_errs = malloc(count * sizeof(*map_errs));
int rc;
unsigned nr_pages;
+ void *const source = page_data;
- if ( !mfns || !map_errs )
+ if ( !mfns )
{
rc = -1;
ERROR("Failed to allocate %zu bytes to process page data",
- count * (sizeof(*mfns) + sizeof(*map_errs)));
+ count * sizeof(*mfns));
goto err;
}
@@ -309,17 +309,37 @@ static int process_page_data(struct xc_sr_context *ctx,
unsigned int count,
}
if ( !ctx->restore.verify )
{
- rc = xg_foreignmemory_copy_to(xch, ctx->domid, nr_pages, mfns,
page_data);
+ rc = xg_foreignmemory_copy_to(xch, ctx->domid, nr_pages, mfns, source);
if ( rc < 0 )
goto err;
}
+ else
+ {
+ DECLARE_HYPERCALL_BUFFER_SHADOW(uint8_t, verify_buf,
+ &ctx->restore.verify_buf);
+
+ rc = xg_foreignmemory_copy_from(xch, ctx->domid, nr_pages, verify_buf,
mfns);
+ if ( rc < 0 )
+ goto err;
+
+ void *guest_page = verify_buf;
+ page_data = source;
+ for ( unsigned i = 0; i < nr_pages; ++i )
+ {
+ /* Verify mode - compare incoming data to what we already have. */
+ if ( memcmp(guest_page, page_data, PAGE_SIZE) )
+ ERROR("verify pfn %#"PRIpfn" failed (type %#"PRIx32")",
+ pfns[i], types[i] >> XEN_DOMCTL_PFINFO_LTAB_SHIFT);
+
+ guest_page += PAGE_SIZE;
+ page_data += PAGE_SIZE;
+ }
+ }
done:
rc = 0;
err:
-
- free(map_errs);
free(mfns);
return rc;
@@ -709,6 +729,18 @@ static int setup(struct xc_sr_context *ctx)
int rc;
DECLARE_HYPERCALL_BUFFER_SHADOW(unsigned long, dirty_bitmap,
&ctx->restore.dirty_bitmap_hbuf);
+ DECLARE_HYPERCALL_BUFFER_SHADOW(uint8_t, verify_buf,
+ &ctx->restore.verify_buf);
+
+ verify_buf = xc_hypercall_buffer_alloc_pages(
+ xch, verify_buf, MAX_BATCH_SIZE);
+
+ if ( !verify_buf )
+ {
+ ERROR("Unable to allocate memory for test buffer");
+ rc = -1;
+ goto err;
+ }
if ( ctx->stream_type == XC_STREAM_COLO )
{
@@ -757,6 +789,8 @@ static void cleanup(struct xc_sr_context *ctx)
unsigned int i;
DECLARE_HYPERCALL_BUFFER_SHADOW(unsigned long, dirty_bitmap,
&ctx->restore.dirty_bitmap_hbuf);
+ DECLARE_HYPERCALL_BUFFER_SHADOW(uint8_t, verify_buf,
+ &ctx->restore.verify_buf);
for ( i = 0; i < ctx->restore.buffered_rec_num; i++ )
free(ctx->restore.buffered_records[i].data);
@@ -765,6 +799,8 @@ static void cleanup(struct xc_sr_context *ctx)
xc_hypercall_buffer_free_pages(
xch, dirty_bitmap, NRPAGES(bitmap_size(ctx->restore.p2m_size)));
+ xc_hypercall_buffer_free_pages(xch, verify_buf, MAX_BATCH_SIZE);
+
free(ctx->restore.buffered_records);
free(ctx->restore.populated_pfns);
diff --git a/tools/libs/guest/xg_sr_save.c b/tools/libs/guest/xg_sr_save.c
index ae61f97a47..514ca4be63 100644
--- a/tools/libs/guest/xg_sr_save.c
+++ b/tools/libs/guest/xg_sr_save.c
@@ -88,7 +88,7 @@ static int write_batch(struct xc_sr_context *ctx)
xc_interface *xch = ctx->xch;
xen_pfn_t *mfns, *types;
void **local_pages;
- int *errors, rc = -1;
+ int rc = -1;
unsigned int i, nr_pages = 0;
unsigned int nr_pfns = ctx->save.nr_batch_pfns;
uint64_t *rec_pfns;
@@ -109,8 +109,6 @@ static int write_batch(struct xc_sr_context *ctx)
mfns = ctx->save.buffers->mfns;
/* Types of the batch pfns. */
types = ctx->save.buffers->types;
- /* Errors from attempting to map the gfns. */
- errors = ctx->save.buffers->errors;
/* Pointers to locally allocated pages. Need freeing. */
local_pages = ctx->save.buffers->local_pages;
memset(local_pages, 0, sizeof(*local_pages) * nr_pfns);
@@ -166,18 +164,54 @@ static int write_batch(struct xc_sr_context *ctx)
iovcnt = 2;
- rc = xg_foreignmemory_copy_from(xch, ctx->domid, nr_pages,
ctx->save.dest_buf, mfns);
- if ( rc < 0 )
- {
- ERROR("xg_foreignmemory_copy_from failed");
- goto err;
- }
-
if ( nr_pages )
{
- iov[iovcnt].iov_base = ctx->save.dest_buf;
- iov[iovcnt].iov_len = nr_pages << XC_PAGE_SHIFT;
- iovcnt++;
+ int p;
+ void *page, *orig_page;
+
+ DECLARE_HYPERCALL_BUFFER_SHADOW(uint8_t, dest_buf,
+ &ctx->save.dest_buf);
+
+ rc = xg_foreignmemory_copy_from(xch, ctx->domid, nr_pages, dest_buf,
mfns);
+ if ( rc < 0 )
+ {
+ ERROR("xg_foreignmemory_copy_from failed");
+ goto err;
+ }
+
+ for ( i = 0, p = 0; i < nr_pfns; ++i )
+ {
+ if ( !page_type_has_stream_data(types[i]) )
+ continue;
+
+ orig_page = page = dest_buf + (p * PAGE_SIZE);
+ rc = ctx->save.ops.normalise_page(ctx, types[i], &page);
+
+ if ( orig_page != page )
+ local_pages[i] = page;
+
+ if ( rc )
+ {
+ if ( rc != -1 || errno != EAGAIN )
+ goto err;
+
+ set_bit(ctx->save.batch_pfns[i], ctx->save.deferred_pages);
+ ++ctx->save.nr_deferred_pages;
+ types[i] = XEN_DOMCTL_PFINFO_XTAB;
+ --nr_pages;
+ }
+ else if ( iov[iovcnt-1].iov_base + iov[iovcnt-1].iov_len == page )
+ {
+ iov[iovcnt-1].iov_len += PAGE_SIZE;
+ }
+ else
+ {
+ iov[iovcnt].iov_base = page;
+ iov[iovcnt].iov_len = PAGE_SIZE;
+ iovcnt++;
+ }
+ ++p;
+ }
}
hdrs.rec.length += nr_pages * PAGE_SIZE;
@@ -188,6 +222,7 @@ static int write_batch(struct xc_sr_context *ctx)
if ( writev_exact(ctx->fd, iov, iovcnt) )
{
PERROR("Failed to write page data to stream");
+ rc = -1;
goto err;
}
@@ -717,30 +752,23 @@ static int setup(struct xc_sr_context *ctx)
{
xc_interface *xch = ctx->xch;
int rc;
- const unsigned dest_buf_len = MAX_BATCH_SIZE * XC_PAGE_SIZE;
DECLARE_HYPERCALL_BUFFER_SHADOW(unsigned long, dirty_bitmap,
&ctx->save.dirty_bitmap_hbuf);
+ DECLARE_HYPERCALL_BUFFER_SHADOW(uint8_t, dest_buf,
+ &ctx->save.dest_buf);
rc = ctx->save.ops.setup(ctx);
if ( rc )
goto err;
+ dest_buf = xc_hypercall_buffer_alloc_pages(
+ xch, dest_buf, MAX_BATCH_SIZE);
dirty_bitmap = xc_hypercall_buffer_alloc_pages(
xch, dirty_bitmap, NRPAGES(bitmap_size(ctx->save.p2m_size)));
ctx->save.deferred_pages = bitmap_alloc(ctx->save.p2m_size);
ctx->save.buffers = calloc(1, sizeof(*ctx->save.buffers));
- ctx->save.dest_buf = NULL;
-
- rc = posix_memalign(&ctx->save.dest_buf, XC_PAGE_SIZE, dest_buf_len);
- if ( rc )
- {
- ERROR("Unable to allocate %u bytes of buffer", dest_buf_len);
- errno = rc;
- rc = -1;
- goto err;
- }
- if ( !dirty_bitmap || !ctx->save.deferred_pages || !ctx->save.buffers)
+ if ( !dirty_bitmap || !ctx->save.deferred_pages || !ctx->save.buffers ||
!dest_buf )
{
ERROR("Unable to allocate memory for dirty bitmaps, deferred pages"
" and various batch buffers");
@@ -761,7 +789,8 @@ static void cleanup(struct xc_sr_context *ctx)
xc_interface *xch = ctx->xch;
DECLARE_HYPERCALL_BUFFER_SHADOW(unsigned long, dirty_bitmap,
&ctx->save.dirty_bitmap_hbuf);
-
+ DECLARE_HYPERCALL_BUFFER_SHADOW(uint8_t, dest_buf,
+ &ctx->save.dest_buf);
xc_shadow_control(xch, ctx->domid, XEN_DOMCTL_SHADOW_OP_OFF,
NULL, 0);
@@ -771,9 +800,9 @@ static void cleanup(struct xc_sr_context *ctx)
xc_hypercall_buffer_free_pages(xch, dirty_bitmap,
NRPAGES(bitmap_size(ctx->save.p2m_size)));
+ xc_hypercall_buffer_free_pages(xch, dest_buf, MAX_BATCH_SIZE);
free(ctx->save.deferred_pages);
free(ctx->save.buffers);
- free(ctx->save.dest_buf);
}
/*
--
2.54.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |