aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/libxl/libxl.c94
-rw-r--r--tools/libxl/libxl.h22
-rw-r--r--tools/libxl/libxl_dom.c121
-rw-r--r--tools/libxl/libxl_internal.h45
-rw-r--r--tools/libxl/libxl_save_callout.c11
-rw-r--r--tools/libxl/xl_cmdimpl.c9
6 files changed, 214 insertions, 88 deletions
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 205c1e61de..4d09b953bf 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -649,32 +649,51 @@ libxl_vminfo * libxl_list_vm(libxl_ctx *ctx, int *nb_vm_out)
return ptr;
}
+static void remus_failover_cb(libxl__egc *egc,
+ libxl__domain_suspend_state *dss, int rc);
+
/* TODO: Explicit Checkpoint acknowledgements via recv_fd. */
int libxl_domain_remus_start(libxl_ctx *ctx, libxl_domain_remus_info *info,
- uint32_t domid, int send_fd, int recv_fd)
+ uint32_t domid, int send_fd, int recv_fd,
+ const libxl_asyncop_how *ao_how)
{
- GC_INIT(ctx);
- libxl_domain_type type = libxl__domain_type(gc, domid);
- int rc = 0;
+ AO_CREATE(ctx, domid, ao_how);
+ libxl__domain_suspend_state *dss;
+ int rc;
+ libxl_domain_type type = libxl__domain_type(gc, domid);
if (type == LIBXL_DOMAIN_TYPE_INVALID) {
rc = ERROR_FAIL;
- goto remus_fail;
+ goto out;
}
- if (info == NULL) {
- LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
- "No remus_info structure supplied for domain %d", domid);
- rc = ERROR_INVAL;
- goto remus_fail;
- }
+ GCNEW(dss);
+ dss->ao = ao;
+ dss->callback = remus_failover_cb;
+ dss->domid = domid;
+ dss->fd = send_fd;
+ /* TODO do something with recv_fd */
+ dss->type = type;
+ dss->live = 1;
+ dss->debug = 0;
+ dss->remus = info;
+
+ assert(info);
/* TBD: Remus setup - i.e. attach qdisc, enable disk buffering, etc */
/* Point of no return */
- rc = libxl__domain_suspend_common(gc, domid, send_fd, type, /* live */ 1,
- /* debug */ 0, info);
+ libxl__domain_suspend(egc, dss);
+ return AO_INPROGRESS;
+
+ out:
+ return AO_ABORT(rc);
+}
+static void remus_failover_cb(libxl__egc *egc,
+ libxl__domain_suspend_state *dss, int rc)
+{
+ STATE_AO_GC(dss->ao);
/*
* With Remus, if we reach this point, it means either
* backup died or some network error occurred preventing us
@@ -684,27 +703,46 @@ int libxl_domain_remus_start(libxl_ctx *ctx, libxl_domain_remus_info *info,
/* TBD: Remus cleanup - i.e. detach qdisc, release other
* resources.
*/
- remus_fail:
- GC_FREE;
- return rc;
+ libxl__ao_complete(egc, ao, rc);
}
-int libxl_domain_suspend(libxl_ctx *ctx, libxl_domain_suspend_info *info,
- uint32_t domid, int fd)
+static void domain_suspend_cb(libxl__egc *egc,
+ libxl__domain_suspend_state *dss, int rc)
{
- GC_INIT(ctx);
+ STATE_AO_GC(dss->ao);
+ libxl__ao_complete(egc,ao,rc);
+
+}
+
+int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd, int flags,
+ const libxl_asyncop_how *ao_how)
+{
+ AO_CREATE(ctx, domid, ao_how);
+ int rc;
+
libxl_domain_type type = libxl__domain_type(gc, domid);
- int live = info != NULL && info->flags & XL_SUSPEND_LIVE;
- int debug = info != NULL && info->flags & XL_SUSPEND_DEBUG;
- int rc = 0;
+ if (type == LIBXL_DOMAIN_TYPE_INVALID) {
+ rc = ERROR_FAIL;
+ goto out_err;
+ }
- rc = libxl__domain_suspend_common(gc, domid, fd, type, live, debug,
- /* No Remus */ NULL);
+ libxl__domain_suspend_state *dss;
+ GCNEW(dss);
- if (!rc && type == LIBXL_DOMAIN_TYPE_HVM)
- rc = libxl__domain_save_device_model(gc, domid, fd);
- GC_FREE;
- return rc;
+ dss->ao = ao;
+ dss->callback = domain_suspend_cb;
+
+ dss->domid = domid;
+ dss->fd = fd;
+ dss->type = type;
+ dss->live = flags & LIBXL_SUSPEND_LIVE;
+ dss->debug = flags & LIBXL_SUSPEND_DEBUG;
+
+ libxl__domain_suspend(egc, dss);
+ return AO_INPROGRESS;
+
+ out_err:
+ return AO_ABORT(rc);
}
int libxl_domain_pause(libxl_ctx *ctx, uint32_t domid)
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index e5d1f97032..371b659434 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -347,13 +347,6 @@ typedef struct libxl__ctx libxl_ctx;
const libxl_version_info* libxl_get_version_info(libxl_ctx *ctx);
-typedef struct {
-#define XL_SUSPEND_DEBUG 1
-#define XL_SUSPEND_LIVE 2
- int flags;
- int (*suspend_callback)(void *, int);
-} libxl_domain_suspend_info;
-
enum {
ERROR_NONSPECIFIC = -1,
ERROR_VERSION = -2,
@@ -514,16 +507,23 @@ int libxl_domain_create_restore(libxl_ctx *ctx, libxl_domain_config *d_config,
void libxl_domain_config_init(libxl_domain_config *d_config);
void libxl_domain_config_dispose(libxl_domain_config *d_config);
-int libxl_domain_remus_start(libxl_ctx *ctx, libxl_domain_remus_info *info,
- uint32_t domid, int send_fd, int recv_fd);
-int libxl_domain_suspend(libxl_ctx *ctx, libxl_domain_suspend_info *info,
- uint32_t domid, int fd);
+
+int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd,
+ int flags, /* LIBXL_SUSPEND_* */
+ const libxl_asyncop_how *ao_how);
+#define LIBXL_SUSPEND_DEBUG 1
+#define LIBXL_SUSPEND_LIVE 2
/* @param suspend_cancel [from xenctrl.h:xc_domain_resume( @param fast )]
* If this parameter is true, use co-operative resume. The guest
* must support this.
*/
int libxl_domain_resume(libxl_ctx *ctx, uint32_t domid, int suspend_cancel);
+
+int libxl_domain_remus_start(libxl_ctx *ctx, libxl_domain_remus_info *info,
+ uint32_t domid, int send_fd, int recv_fd,
+ const libxl_asyncop_how *ao_how);
+
int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid);
int libxl_domain_reboot(libxl_ctx *ctx, uint32_t domid);
int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid);
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index 3bf1e26eda..7f12e036d4 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -17,13 +17,11 @@
#include <glob.h>
-#include <xenctrl.h>
-#include <xc_dom.h>
+#include "libxl_internal.h"
+#include <xc_dom.h>
#include <xen/hvm/hvm_info_table.h>
-#include "libxl_internal.h"
-
libxl_domain_type libxl__domain_type(libxl__gc *gc, uint32_t domid)
{
libxl_ctx *ctx = libxl__gc_owner(gc);
@@ -523,11 +521,18 @@ int libxl__toolstack_restore(uint32_t domid, const uint8_t *buf,
return 0;
}
-static int libxl__domain_suspend_common_switch_qemu_logdirty
+/*==================== Domain suspend (save) ====================*/
+
+static void domain_suspend_done(libxl__egc *egc,
+ libxl__domain_suspend_state *dss, int rc);
+
+/*----- callbacks, called by xc_domain_save -----*/
+
+int libxl__domain_suspend_common_switch_qemu_logdirty
(int domid, unsigned int enable, void *data)
{
libxl__domain_suspend_state *dss = data;
- libxl__gc *gc = dss->gc;
+ STATE_AO_GC(dss->ao);
char *path;
bool rc;
@@ -592,10 +597,10 @@ int libxl__domain_resume_device_model(libxl__gc *gc, uint32_t domid)
return 0;
}
-static int libxl__domain_suspend_common_callback(void *data)
+int libxl__domain_suspend_common_callback(void *data)
{
libxl__domain_suspend_state *dss = data;
- libxl__gc *gc = dss->gc;
+ STATE_AO_GC(dss->ao);
unsigned long hvm_s_state = 0, hvm_pvdrv = 0;
int ret;
char *state = "suspend";
@@ -716,7 +721,7 @@ static int libxl__domain_suspend_common_callback(void *data)
guest_suspended:
if (dss->hvm) {
- ret = libxl__domain_suspend_device_model(dss->gc, dss->domid);
+ ret = libxl__domain_suspend_device_model(gc, dss->domid);
if (ret) {
LOG(ERROR, "libxl__domain_suspend_device_model failed ret=%d", ret);
return 0;
@@ -733,11 +738,11 @@ static inline char *save_helper(libxl__gc *gc, uint32_t domid,
domid, phys_offset, node);
}
-static int libxl__toolstack_save(uint32_t domid, uint8_t **buf,
+int libxl__toolstack_save(uint32_t domid, uint8_t **buf,
uint32_t *len, void *data)
{
libxl__domain_suspend_state *dss = data;
- libxl__gc *gc = dss->gc;
+ STATE_AO_GC(dss->ao);
int i = 0;
char *start_addr = NULL, *size = NULL, *phys_offset = NULL, *name = NULL;
unsigned int num = 0;
@@ -808,6 +813,8 @@ static int libxl__toolstack_save(uint32_t domid, uint8_t **buf,
return 0;
}
+/*----- remus callbacks -----*/
+
static int libxl__remus_domain_suspend_callback(void *data)
{
/* TODO: Issue disk and network checkpoint reqs. */
@@ -817,7 +824,7 @@ static int libxl__remus_domain_suspend_callback(void *data)
static int libxl__remus_domain_resume_callback(void *data)
{
libxl__domain_suspend_state *dss = data;
- libxl__gc *gc = dss->gc;
+ STATE_AO_GC(dss->ao);
/* Resumes the domain and the device model */
if (libxl_domain_resume(CTX, dss->domid, /* Fast Suspend */1))
@@ -830,10 +837,11 @@ static int libxl__remus_domain_resume_callback(void *data)
static int libxl__remus_domain_checkpoint_callback(void *data)
{
libxl__domain_suspend_state *dss = data;
+ STATE_AO_GC(dss->ao);
/* This would go into tailbuf. */
if (dss->hvm &&
- libxl__domain_save_device_model(dss->gc, dss->domid, dss->save_fd))
+ libxl__domain_save_device_model(gc, dss->domid, dss->fd))
return 0;
/* TODO: Wait for disk and memory ack, release network buffer */
@@ -841,17 +849,23 @@ static int libxl__remus_domain_checkpoint_callback(void *data)
return 1;
}
-int libxl__domain_suspend_common(libxl__gc *gc, uint32_t domid, int fd,
- libxl_domain_type type,
- int live, int debug,
- const libxl_domain_remus_info *r_info)
+/*----- main code for suspending, in order of execution -----*/
+
+void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss)
{
+ STATE_AO_GC(dss->ao);
int port;
- struct save_callbacks callbacks[1];
- libxl__domain_suspend_state dss[1];
int rc = ERROR_FAIL;
unsigned long vm_generationid_addr;
+ /* Convenience aliases */
+ const uint32_t domid = dss->domid;
+ const libxl_domain_type type = dss->type;
+ const int live = dss->live;
+ const int debug = dss->debug;
+ const libxl_domain_remus_info *const r_info = dss->remus;
+ struct save_callbacks *const callbacks = &dss->callbacks;
+
switch (type) {
case LIBXL_DOMAIN_TYPE_HVM: {
char *path;
@@ -870,15 +884,13 @@ int libxl__domain_suspend_common(libxl__gc *gc, uint32_t domid, int fd,
dss->hvm = 0;
break;
default:
- return ERROR_INVAL;
+ abort();
}
dss->xcflags = (live) ? XCFLAGS_LIVE : 0
| (debug) ? XCFLAGS_DEBUG : 0
| (dss->hvm) ? XCFLAGS_HVM : 0;
- dss->domid = domid;
- dss->gc = gc;
dss->suspend_eventchn = -1;
dss->guest_responded = 0;
@@ -886,10 +898,7 @@ int libxl__domain_suspend_common(libxl__gc *gc, uint32_t domid, int fd,
dss->interval = r_info->interval;
if (r_info->compression)
dss->xcflags |= XCFLAGS_CHECKPOINT_COMPRESS;
- dss->save_fd = fd;
}
- else
- dss->save_fd = -1;
dss->xce = xc_evtchn_open(NULL, 0);
if (dss->xce == NULL)
@@ -919,10 +928,28 @@ int libxl__domain_suspend_common(libxl__gc *gc, uint32_t domid, int fd,
callbacks->toolstack_save = libxl__toolstack_save;
callbacks->data = dss;
- rc = xc_domain_save(CTX->xch, fd, domid, 0, 0, dss->xcflags, callbacks,
- dss->hvm, vm_generationid_addr);
- if ( rc ) {
- LOGE(ERROR, "saving domain: %s",
+ libxl__xc_domain_save(egc, dss, vm_generationid_addr);
+ return;
+
+ out:
+ domain_suspend_done(egc, dss, rc);
+}
+
+void libxl__xc_domain_save_done(libxl__egc *egc,
+ libxl__domain_suspend_state *dss,
+ int rc, int retval, int errnoval)
+{
+ STATE_AO_GC(dss->ao);
+
+ /* Convenience aliases */
+ const libxl_domain_type type = dss->type;
+ const uint32_t domid = dss->domid;
+
+ if (rc)
+ goto out;
+
+ if (retval) {
+ LOGEV(ERROR, errnoval, "saving domain: %s",
dss->guest_responded ?
"domain responded to suspend request" :
"domain did not respond to suspend request");
@@ -930,16 +957,21 @@ int libxl__domain_suspend_common(libxl__gc *gc, uint32_t domid, int fd,
rc = ERROR_GUEST_TIMEDOUT;
else
rc = ERROR_FAIL;
+ goto out;
}
- if (dss->suspend_eventchn > 0)
- xc_suspend_evtchn_release(CTX->xch, dss->xce, domid,
- dss->suspend_eventchn);
- if (dss->xce != NULL)
- xc_evtchn_close(dss->xce);
+ if (type == LIBXL_DOMAIN_TYPE_HVM) {
+ rc = libxl__domain_suspend_device_model(gc, domid);
+ if (rc) goto out;
+
+ rc = libxl__domain_save_device_model(gc, domid, dss->fd);
+ if (rc) goto out;
+ }
+
+ rc = 0;
out:
- return rc;
+ domain_suspend_done(egc, dss, rc);
}
int libxl__domain_save_device_model(libxl__gc *gc, uint32_t domid, int fd)
@@ -994,6 +1026,25 @@ out:
return rc;
}
+static void domain_suspend_done(libxl__egc *egc,
+ libxl__domain_suspend_state *dss, int rc)
+{
+ STATE_AO_GC(dss->ao);
+
+ /* Convenience aliases */
+ const uint32_t domid = dss->domid;
+
+ if (dss->suspend_eventchn > 0)
+ xc_suspend_evtchn_release(CTX->xch, dss->xce, domid,
+ dss->suspend_eventchn);
+ if (dss->xce != NULL)
+ xc_evtchn_close(dss->xce);
+
+ dss->callback(egc, dss, rc);
+}
+
+/*==================== Miscellaneous ====================*/
+
char *libxl__uuid2string(libxl__gc *gc, const libxl_uuid uuid)
{
char *s = libxl__sprintf(gc, LIBXL_UUID_FMT, LIBXL_UUID_BYTES(uuid));
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 7a3b7f8722..1ee5bd2b09 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1777,16 +1777,28 @@ _hidden int libxl__datacopier_start(libxl__datacopier_state *dc);
typedef struct libxl__domain_suspend_state libxl__domain_suspend_state;
+typedef void libxl__domain_suspend_cb(libxl__egc*,
+ libxl__domain_suspend_state*, int rc);
+
struct libxl__domain_suspend_state {
- libxl__gc *gc;
+ /* set by caller of libxl__domain_suspend */
+ libxl__ao *ao;
+ libxl__domain_suspend_cb *callback;
+
+ uint32_t domid;
+ int fd;
+ libxl_domain_type type;
+ int live;
+ int debug;
+ const libxl_domain_remus_info *remus;
+ /* private */
xc_evtchn *xce; /* event channel handle */
int suspend_eventchn;
- int domid;
int hvm;
- unsigned int xcflags;
+ int xcflags;
int guest_responded;
- int save_fd; /* Migration stream fd (for Remus) */
int interval; /* checkpoint interval (for Remus) */
+ struct save_callbacks callbacks;
};
@@ -1903,10 +1915,27 @@ struct libxl__domain_create_state {
/*----- Domain suspend (save) functions -----*/
-_hidden int libxl__domain_suspend_common(libxl__gc *gc, uint32_t domid, int fd,
- libxl_domain_type type,
- int live, int debug,
- const libxl_domain_remus_info *r_info);
+/* calls dss->callback when done */
+_hidden void libxl__domain_suspend(libxl__egc *egc,
+ libxl__domain_suspend_state *dss);
+
+
+/* calls libxl__xc_domain_suspend_done when done */
+_hidden void libxl__xc_domain_save(libxl__egc*, libxl__domain_suspend_state*,
+ unsigned long vm_generationid_addr);
+/* If rc==0 then retval is the return value from xc_domain_save
+ * and errnoval is the errno value it provided.
+ * If rc!=0, retval and errnoval are undefined. */
+_hidden void libxl__xc_domain_save_done(libxl__egc*,
+ libxl__domain_suspend_state*,
+ int rc, int retval, int errnoval);
+
+_hidden int libxl__domain_suspend_common_callback(void *data);
+_hidden int libxl__domain_suspend_common_switch_qemu_logdirty
+ (int domid, unsigned int enable, void *data);
+_hidden int libxl__toolstack_save(uint32_t domid, uint8_t **buf,
+ uint32_t *len, void *data);
+
/* calls libxl__xc_domain_restore_done when done */
_hidden void libxl__xc_domain_restore(libxl__egc *egc,
diff --git a/tools/libxl/libxl_save_callout.c b/tools/libxl/libxl_save_callout.c
index 2f8db9f0b6..1b481ab6be 100644
--- a/tools/libxl/libxl_save_callout.c
+++ b/tools/libxl/libxl_save_callout.c
@@ -35,3 +35,14 @@ void libxl__xc_domain_restore(libxl__egc *egc, libxl__domain_create_state *dcs,
&state->vm_generationid_addr, &dcs->callbacks);
libxl__xc_domain_restore_done(egc, dcs, 0, r, errno);
}
+
+void libxl__xc_domain_save(libxl__egc *egc, libxl__domain_suspend_state *dss,
+ unsigned long vm_generationid_addr)
+{
+ STATE_AO_GC(dss->ao);
+ int r;
+
+ r = xc_domain_save(CTX->xch, dss->fd, dss->domid, 0, 0, dss->xcflags,
+ &dss->callbacks, dss->hvm, vm_generationid_addr);
+ libxl__xc_domain_save_done(egc, dss, 0, r, errno);
+}
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 4101669dc3..bcdef00e02 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -2826,7 +2826,7 @@ static int save_domain(const char *p, const char *filename, int checkpoint,
save_domain_core_writeconfig(fd, filename, config_data, config_len);
- CHK_ERRNO(libxl_domain_suspend(ctx, NULL, domid, fd));
+ CHK_ERRNO(libxl_domain_suspend(ctx, domid, fd, 0, NULL));
close(fd);
if (checkpoint)
@@ -2988,7 +2988,6 @@ static void migrate_domain(const char *domain_spec, const char *rune,
pid_t child = -1;
int rc;
int send_fd = -1, recv_fd = -1;
- libxl_domain_suspend_info suspinfo;
char *away_domname;
char rc_buf;
uint8_t *config_data;
@@ -3010,9 +3009,7 @@ static void migrate_domain(const char *domain_spec, const char *rune,
xtl_stdiostream_adjust_flags(logger, XTL_STDIOSTREAM_HIDE_PROGRESS, 0);
- memset(&suspinfo, 0, sizeof(suspinfo));
- suspinfo.flags |= XL_SUSPEND_LIVE;
- rc = libxl_domain_suspend(ctx, &suspinfo, domid, send_fd);
+ rc = libxl_domain_suspend(ctx, domid, send_fd, LIBXL_SUSPEND_LIVE, NULL);
if (rc) {
fprintf(stderr, "migration sender: libxl_domain_suspend failed"
" (rc=%d)\n", rc);
@@ -6584,7 +6581,7 @@ int main_remus(int argc, char **argv)
}
/* Point of no return */
- rc = libxl_domain_remus_start(ctx, &r_info, domid, send_fd, recv_fd);
+ rc = libxl_domain_remus_start(ctx, &r_info, domid, send_fd, recv_fd, 0);
/* If we are here, it means backup has failed/domain suspend failed.
* Try to resume the domain and exit gracefully.