|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH Remus v1 7/8] tools/libxc: implement Remus checkpointed restore
With Remus, the restore flow should be:
the first full migration stream -> { periodically restore stream }
on failover:
stream_complete()
Signed-off-by: Yang Hongyang <yanghy@xxxxxxxxxxxxxx>
---
tools/libxc/xc_sr_common.h | 3 ++
tools/libxc/xc_sr_restore.c | 108 +++++++++++++++++++++++++++++++++++++++++---
2 files changed, 104 insertions(+), 7 deletions(-)
diff --git a/tools/libxc/xc_sr_common.h b/tools/libxc/xc_sr_common.h
index 1aab5aa..4da0a19 100644
--- a/tools/libxc/xc_sr_common.h
+++ b/tools/libxc/xc_sr_common.h
@@ -195,6 +195,9 @@ struct xc_sr_context
struct xc_sr_restore_ops ops;
struct restore_callbacks *callbacks;
+ /* Whether it is a checkpointed stream */
+ bool checkpointed;
+
/* From Image Header. */
uint32_t format_version;
diff --git a/tools/libxc/xc_sr_restore.c b/tools/libxc/xc_sr_restore.c
index 8022c3d..fceb5c7 100644
--- a/tools/libxc/xc_sr_restore.c
+++ b/tools/libxc/xc_sr_restore.c
@@ -3,6 +3,15 @@
#include "xc_sr_common.h"
/*
+ * With Remus, we buffer the records sent by primary at checkpoint,
+ * in case the primary will fail, we can recover from the last
+ * checkpoint state.
+ * This should be enough because primary only send dirty pages at
+ * checkpoint.
+ */
+#define MAX_RECORDS 1024
+
+/*
* Read and validate the Image and Domain headers.
*/
static int read_headers(struct xc_sr_context *ctx)
@@ -519,8 +528,11 @@ extern int read_qemu(struct xc_sr_context *ctx);
static int restore(struct xc_sr_context *ctx)
{
xc_interface *xch = ctx->xch;
- struct xc_sr_record rec;
- int rc, saved_rc = 0, saved_errno = 0;
+ struct xc_sr_record *rec;
+ int rc, saved_rc = 0, saved_errno = 0, i;
+ struct xc_sr_record *records[MAX_RECORDS];
+
+ memset(records, 0, MAX_RECORDS*sizeof(void *));
IPRINTF("Restoring domain");
@@ -537,17 +549,29 @@ static int restore(struct xc_sr_context *ctx)
goto err;
}
+ rec = malloc(sizeof(struct xc_sr_record));
+ if (!rec)
+ {
+ ERROR("Unable to allocate memory for record");
+ rc = -1;
+ goto err;
+ }
do
{
- rc = read_record(ctx, &rec);
- if ( rc )
+ rc = read_record(ctx, rec);
+ if ( rc ) {
+ free(rec);
goto err;
+ }
- rc = process_record(ctx, &rec);
- if ( rc )
+ rc = process_record(ctx, rec);
+ if ( rc ) {
+ free(rec);
goto err;
+ }
- } while ( rec.type != REC_TYPE_END );
+ } while ( rec->type != REC_TYPE_END );
+ free(rec);
#ifdef XG_LIBXL_HVM_COMPAT
if ( ctx->dominfo.hvm )
@@ -557,7 +581,69 @@ static int restore(struct xc_sr_context *ctx)
goto err;
}
#endif
+ /*
+ * If it is a live migration, this is the end of the live migration
+ * stream
+ * With Remus, we will enter a loop to receive the stream periodically
+ * sent by primary.
+ */
+
+ while ( ctx->restore.checkpointed )
+ {
+ i = 0;
+ do
+ {
+ /* Buffer records */
+ if ( i >= MAX_RECORDS )
+ {
+ ERROR("There are too many records");
+ rc = -1;
+ goto err;
+ }
+ rec = malloc(sizeof(struct xc_sr_record));
+ if (!rec)
+ {
+ ERROR("Unable to allocate memory for record");
+ rc = -1;
+ goto err;
+ }
+ rc = read_record(ctx, rec);
+ if ( rc )
+ goto err_buf;
+
+ records[i++] = rec;
+ } while ( rec->type != REC_TYPE_END );
+#ifdef XG_LIBXL_HVM_COMPAT
+ if ( ctx->dominfo.hvm )
+ {
+ rc = read_qemu(ctx);
+ if ( rc )
+ goto err_buf;
+ }
+#endif
+ IPRINTF("All records buffered");
+
+ i = 0;
+ rec = records[i++];
+ while (rec)
+ {
+ rc = process_record(ctx, rec);
+ free(rec);
+ records[i-1] = NULL;
+ if ( rc )
+ goto err;
+
+ rec = records[i++];
+ }
+ IPRINTF("All records processed");
+ }
+
+ err_buf:
+ /*
+ * With Remus, if we reach here, there must be some error on primary,
+ * failover from the last checkpoint state.
+ */
rc = ctx->restore.ops.stream_complete(ctx);
if ( rc )
goto err;
@@ -571,6 +657,13 @@ static int restore(struct xc_sr_context *ctx)
PERROR("Restore failed");
done:
+ for ( i = 0; i < MAX_RECORDS; i++)
+ {
+ if ( records[i] ) {
+ free(records[i]->data);
+ free(records[i]);
+ }
+ }
free(ctx->restore.populated_pfns);
rc = ctx->restore.ops.cleanup(ctx);
if ( rc )
@@ -605,6 +698,7 @@ int xc_domain_restore2(xc_interface *xch, int io_fd,
uint32_t dom,
ctx.restore.xenstore_evtchn = store_evtchn;
ctx.restore.xenstore_domid = store_domid;
ctx.restore.callbacks = callbacks;
+ ctx.restore.checkpointed = checkpointed_stream;
IPRINTF("In experimental %s", __func__);
DPRINTF("fd %d, dom %u, hvm %u, pae %u, superpages %d"
--
1.9.1
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |