forked from SLFO-pool/xen
Sync from SUSE:SLFO:Main xen revision 2e30689375849799569c0a388d847125
This commit is contained in:
272
libxc-sr-restore-read_record.patch
Normal file
272
libxc-sr-restore-read_record.patch
Normal file
@@ -0,0 +1,272 @@
|
||||
From: Olaf Hering <olaf@aepfle.de>
|
||||
Date: Mon, 26 Oct 2020 12:19:17 +0100
|
||||
Subject: libxc sr restore read_record
|
||||
|
||||
tools: restore: split record processing
|
||||
|
||||
handle_page_data must be able to read directly into mapped guest memory.
|
||||
This will avoid unneccesary memcpy calls for data which can be consumed verbatim.
|
||||
|
||||
Rearrange the code to allow decisions based on the incoming record.
|
||||
|
||||
This change is preparation for future changes in handle_page_data,
|
||||
no change in behavior is intended.
|
||||
|
||||
Signed-off-by: Olaf Hering <olaf@aepfle.de>
|
||||
Reviewed-by: Juergen Gross <jgross@suse.com>
|
||||
---
|
||||
tools/libs/guest/xg_sr_common.c | 33 ++++++++++++---------
|
||||
tools/libs/guest/xg_sr_common.h | 4 ++-
|
||||
tools/libs/guest/xg_sr_restore.c | 49 ++++++++++++++++++++++----------
|
||||
tools/libs/guest/xg_sr_save.c | 7 ++++-
|
||||
4 files changed, 63 insertions(+), 30 deletions(-)
|
||||
|
||||
--- a/tools/libs/guest/xg_sr_common.c
|
||||
+++ b/tools/libs/guest/xg_sr_common.c
|
||||
@@ -91,26 +91,33 @@ int write_split_record(struct xc_sr_cont
|
||||
return -1;
|
||||
}
|
||||
|
||||
-int read_record(struct xc_sr_context *ctx, int fd, struct xc_sr_record *rec)
|
||||
+int read_record_header(struct xc_sr_context *ctx, int fd, struct xc_sr_rhdr *rhdr)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
- struct xc_sr_rhdr rhdr;
|
||||
- size_t datasz;
|
||||
|
||||
- if ( read_exact(fd, &rhdr, sizeof(rhdr)) )
|
||||
+ if ( read_exact(fd, rhdr, sizeof(*rhdr)) )
|
||||
{
|
||||
PERROR("Failed to read Record Header from stream");
|
||||
return -1;
|
||||
}
|
||||
|
||||
- if ( rhdr.length > REC_LENGTH_MAX )
|
||||
+ if ( rhdr->length > REC_LENGTH_MAX )
|
||||
{
|
||||
- ERROR("Record (0x%08x, %s) length %#x exceeds max (%#x)", rhdr.type,
|
||||
- rec_type_to_str(rhdr.type), rhdr.length, REC_LENGTH_MAX);
|
||||
+ ERROR("Record (0x%08x, %s) length %#x exceeds max (%#x)", rhdr->type,
|
||||
+ rec_type_to_str(rhdr->type), rhdr->length, REC_LENGTH_MAX);
|
||||
return -1;
|
||||
}
|
||||
|
||||
- datasz = ROUNDUP(rhdr.length, REC_ALIGN_ORDER);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+int read_record_data(struct xc_sr_context *ctx, int fd, struct xc_sr_rhdr *rhdr,
|
||||
+ struct xc_sr_record *rec)
|
||||
+{
|
||||
+ xc_interface *xch = ctx->xch;
|
||||
+ size_t datasz;
|
||||
+
|
||||
+ datasz = ROUNDUP(rhdr->length, REC_ALIGN_ORDER);
|
||||
|
||||
if ( datasz )
|
||||
{
|
||||
@@ -119,7 +126,7 @@ int read_record(struct xc_sr_context *ct
|
||||
if ( !rec->data )
|
||||
{
|
||||
ERROR("Unable to allocate %zu bytes for record data (0x%08x, %s)",
|
||||
- datasz, rhdr.type, rec_type_to_str(rhdr.type));
|
||||
+ datasz, rhdr->type, rec_type_to_str(rhdr->type));
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -128,18 +135,18 @@ int read_record(struct xc_sr_context *ct
|
||||
free(rec->data);
|
||||
rec->data = NULL;
|
||||
PERROR("Failed to read %zu bytes of data for record (0x%08x, %s)",
|
||||
- datasz, rhdr.type, rec_type_to_str(rhdr.type));
|
||||
+ datasz, rhdr->type, rec_type_to_str(rhdr->type));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
rec->data = NULL;
|
||||
|
||||
- rec->type = rhdr.type;
|
||||
- rec->length = rhdr.length;
|
||||
+ rec->type = rhdr->type;
|
||||
+ rec->length = rhdr->length;
|
||||
|
||||
return 0;
|
||||
-};
|
||||
+}
|
||||
|
||||
static void __attribute__((unused)) build_assertions(void)
|
||||
{
|
||||
--- a/tools/libs/guest/xg_sr_common.h
|
||||
+++ b/tools/libs/guest/xg_sr_common.h
|
||||
@@ -458,7 +458,9 @@ static inline int write_record(struct xc
|
||||
*
|
||||
* On failure, the contents of the record structure are undefined.
|
||||
*/
|
||||
-int read_record(struct xc_sr_context *ctx, int fd, struct xc_sr_record *rec);
|
||||
+int read_record_header(struct xc_sr_context *ctx, int fd, struct xc_sr_rhdr *rhdr);
|
||||
+int read_record_data(struct xc_sr_context *ctx, int fd, struct xc_sr_rhdr *rhdr,
|
||||
+ struct xc_sr_record *rec);
|
||||
|
||||
/*
|
||||
* This would ideally be private in restore.c, but is needed by
|
||||
--- a/tools/libs/guest/xg_sr_restore.c
|
||||
+++ b/tools/libs/guest/xg_sr_restore.c
|
||||
@@ -453,7 +453,7 @@ static int send_checkpoint_dirty_pfn_lis
|
||||
return rc;
|
||||
}
|
||||
|
||||
-static int process_record(struct xc_sr_context *ctx, struct xc_sr_record *rec);
|
||||
+static int process_buffered_record(struct xc_sr_context *ctx, struct xc_sr_record *rec);
|
||||
static int handle_checkpoint(struct xc_sr_context *ctx)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
@@ -492,7 +492,7 @@ static int handle_checkpoint(struct xc_s
|
||||
|
||||
for ( i = 0; i < ctx->restore.buffered_rec_num; i++ )
|
||||
{
|
||||
- rc = process_record(ctx, &ctx->restore.buffered_records[i]);
|
||||
+ rc = process_buffered_record(ctx, &ctx->restore.buffered_records[i]);
|
||||
if ( rc )
|
||||
goto err;
|
||||
}
|
||||
@@ -553,10 +553,11 @@ static int handle_checkpoint(struct xc_s
|
||||
return rc;
|
||||
}
|
||||
|
||||
-static int buffer_record(struct xc_sr_context *ctx, struct xc_sr_record *rec)
|
||||
+static int buffer_record(struct xc_sr_context *ctx, struct xc_sr_rhdr *rhdr)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
unsigned int new_alloc_num;
|
||||
+ struct xc_sr_record rec;
|
||||
struct xc_sr_record *p;
|
||||
|
||||
if ( ctx->restore.buffered_rec_num >= ctx->restore.allocated_rec_num )
|
||||
@@ -574,8 +575,13 @@ static int buffer_record(struct xc_sr_co
|
||||
ctx->restore.allocated_rec_num = new_alloc_num;
|
||||
}
|
||||
|
||||
+ if ( read_record_data(ctx, ctx->fd, rhdr, &rec) )
|
||||
+ {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
memcpy(&ctx->restore.buffered_records[ctx->restore.buffered_rec_num++],
|
||||
- rec, sizeof(*rec));
|
||||
+ &rec, sizeof(rec));
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -606,7 +612,7 @@ int handle_static_data_end(struct xc_sr_
|
||||
return rc;
|
||||
}
|
||||
|
||||
-static int process_record(struct xc_sr_context *ctx, struct xc_sr_record *rec)
|
||||
+static int process_buffered_record(struct xc_sr_context *ctx, struct xc_sr_record *rec)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
int rc = 0;
|
||||
@@ -644,6 +650,19 @@ static int process_record(struct xc_sr_c
|
||||
return rc;
|
||||
}
|
||||
|
||||
+static int process_incoming_record_header(struct xc_sr_context *ctx, struct xc_sr_rhdr *rhdr)
|
||||
+{
|
||||
+ struct xc_sr_record rec;
|
||||
+ int rc;
|
||||
+
|
||||
+ rc = read_record_data(ctx, ctx->fd, rhdr, &rec);
|
||||
+ if ( rc )
|
||||
+ return rc;
|
||||
+
|
||||
+ return process_buffered_record(ctx, &rec);
|
||||
+}
|
||||
+
|
||||
+
|
||||
static int setup(struct xc_sr_context *ctx)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
@@ -740,7 +759,7 @@ static void cleanup(struct xc_sr_context
|
||||
static int restore(struct xc_sr_context *ctx)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
- struct xc_sr_record rec;
|
||||
+ struct xc_sr_rhdr rhdr;
|
||||
int rc, saved_rc = 0, saved_errno = 0;
|
||||
|
||||
IPRINTF("Restoring domain");
|
||||
@@ -751,7 +770,7 @@ static int restore(struct xc_sr_context
|
||||
|
||||
do
|
||||
{
|
||||
- rc = read_record(ctx, ctx->fd, &rec);
|
||||
+ rc = read_record_header(ctx, ctx->fd, &rhdr);
|
||||
if ( rc )
|
||||
{
|
||||
if ( ctx->restore.buffer_all_records )
|
||||
@@ -761,25 +780,25 @@ static int restore(struct xc_sr_context
|
||||
}
|
||||
|
||||
if ( ctx->restore.buffer_all_records &&
|
||||
- rec.type != REC_TYPE_END &&
|
||||
- rec.type != REC_TYPE_CHECKPOINT )
|
||||
+ rhdr.type != REC_TYPE_END &&
|
||||
+ rhdr.type != REC_TYPE_CHECKPOINT )
|
||||
{
|
||||
- rc = buffer_record(ctx, &rec);
|
||||
+ rc = buffer_record(ctx, &rhdr);
|
||||
if ( rc )
|
||||
goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
- rc = process_record(ctx, &rec);
|
||||
+ rc = process_incoming_record_header(ctx, &rhdr);
|
||||
if ( rc == RECORD_NOT_PROCESSED )
|
||||
{
|
||||
- if ( rec.type & REC_TYPE_OPTIONAL )
|
||||
+ if ( rhdr.type & REC_TYPE_OPTIONAL )
|
||||
DPRINTF("Ignoring optional record %#x (%s)",
|
||||
- rec.type, rec_type_to_str(rec.type));
|
||||
+ rhdr.type, rec_type_to_str(rhdr.type));
|
||||
else
|
||||
{
|
||||
ERROR("Mandatory record %#x (%s) not handled",
|
||||
- rec.type, rec_type_to_str(rec.type));
|
||||
+ rhdr.type, rec_type_to_str(rhdr.type));
|
||||
rc = -1;
|
||||
goto err;
|
||||
}
|
||||
@@ -790,7 +809,7 @@ static int restore(struct xc_sr_context
|
||||
goto err;
|
||||
}
|
||||
|
||||
- } while ( rec.type != REC_TYPE_END );
|
||||
+ } while ( rhdr.type != REC_TYPE_END );
|
||||
|
||||
remus_failover:
|
||||
if ( ctx->stream_type == XC_STREAM_COLO )
|
||||
--- a/tools/libs/guest/xg_sr_save.c
|
||||
+++ b/tools/libs/guest/xg_sr_save.c
|
||||
@@ -590,6 +590,7 @@ static int send_memory_live(struct xc_sr
|
||||
static int colo_merge_secondary_dirty_bitmap(struct xc_sr_context *ctx)
|
||||
{
|
||||
xc_interface *xch = ctx->xch;
|
||||
+ struct xc_sr_rhdr rhdr;
|
||||
struct xc_sr_record rec;
|
||||
uint64_t *pfns = NULL;
|
||||
uint64_t pfn;
|
||||
@@ -598,7 +599,11 @@ static int colo_merge_secondary_dirty_bi
|
||||
DECLARE_HYPERCALL_BUFFER_SHADOW(unsigned long, dirty_bitmap,
|
||||
&ctx->save.dirty_bitmap_hbuf);
|
||||
|
||||
- rc = read_record(ctx, ctx->save.recv_fd, &rec);
|
||||
+ rc = read_record_header(ctx, ctx->save.recv_fd, &rhdr);
|
||||
+ if ( rc )
|
||||
+ goto err;
|
||||
+
|
||||
+ rc = read_record_data(ctx, ctx->save.recv_fd, &rhdr, &rec);
|
||||
if ( rc )
|
||||
goto err;
|
||||
|
Reference in New Issue
Block a user