* [PATCH v1 1/5] libxl/save: Refactor libxl__domain_suspend_state
2015-05-20 10:01 [PATCH v1 0/5] Misc cleanups for libxl Yang Hongyang
@ 2015-05-20 10:01 ` Yang Hongyang
2015-06-02 14:40 ` Ian Campbell
2015-05-20 10:01 ` [PATCH v1 2/5] tools/libxl: move domain suspend codes into a separate file Yang Hongyang
` (5 subsequent siblings)
6 siblings, 1 reply; 23+ messages in thread
From: Yang Hongyang @ 2015-05-20 10:01 UTC (permalink / raw)
To: xen-devel
Cc: wei.liu2, ian.campbell, wency, andrew.cooper3, yunhong.jiang,
ian.jackson, rshriram
Currently struct libxl__domain_suspend_state contains 2 type of states,
one is save state, another is suspend state. This patch separate it out.
Also rename libxl__domain_suspend() to libxl__domain_save() since it
actually do the save domain work.
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
CC: Ian Campbell <Ian.Campbell@citrix.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Andrew Cooper <andrew.cooper3@citrix.com>
---
tools/libxl/libxl.c | 18 +++---
tools/libxl/libxl_dom.c | 126 +++++++++++++++++++++------------------
tools/libxl/libxl_internal.h | 45 ++++++++------
tools/libxl/libxl_netbuffer.c | 2 +-
tools/libxl/libxl_save_callout.c | 2 +-
5 files changed, 108 insertions(+), 85 deletions(-)
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index a6eb2df..7259061 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -830,7 +830,7 @@ static void libxl__remus_setup_done(libxl__egc *egc,
static void libxl__remus_setup_failed(libxl__egc *egc,
libxl__remus_devices_state *rds, int rc);
static void remus_failover_cb(libxl__egc *egc,
- libxl__domain_suspend_state *dss, int rc);
+ libxl__domain_save_state *dss, int rc);
/* TODO: Explicit Checkpoint acknowledgements via recv_fd. */
int libxl_domain_remus_start(libxl_ctx *ctx, libxl_domain_remus_info *info,
@@ -838,7 +838,7 @@ int libxl_domain_remus_start(libxl_ctx *ctx, libxl_domain_remus_info *info,
const libxl_asyncop_how *ao_how)
{
AO_CREATE(ctx, domid, ao_how);
- libxl__domain_suspend_state *dss;
+ libxl__domain_save_state *dss;
int rc;
libxl_domain_type type = libxl__domain_type(gc, domid);
@@ -907,11 +907,11 @@ int libxl_domain_remus_start(libxl_ctx *ctx, libxl_domain_remus_info *info,
static void libxl__remus_setup_done(libxl__egc *egc,
libxl__remus_devices_state *rds, int rc)
{
- libxl__domain_suspend_state *dss = CONTAINER_OF(rds, *dss, rds);
+ libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
STATE_AO_GC(dss->ao);
if (!rc) {
- libxl__domain_suspend(egc, dss);
+ libxl__domain_save(egc, dss);
return;
}
@@ -924,7 +924,7 @@ static void libxl__remus_setup_done(libxl__egc *egc,
static void libxl__remus_setup_failed(libxl__egc *egc,
libxl__remus_devices_state *rds, int rc)
{
- libxl__domain_suspend_state *dss = CONTAINER_OF(rds, *dss, rds);
+ libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
STATE_AO_GC(dss->ao);
if (rc)
@@ -935,7 +935,7 @@ static void libxl__remus_setup_failed(libxl__egc *egc,
}
static void remus_failover_cb(libxl__egc *egc,
- libxl__domain_suspend_state *dss, int rc)
+ libxl__domain_save_state *dss, int rc)
{
STATE_AO_GC(dss->ao);
/*
@@ -947,7 +947,7 @@ static void remus_failover_cb(libxl__egc *egc,
}
static void domain_suspend_cb(libxl__egc *egc,
- libxl__domain_suspend_state *dss, int rc)
+ libxl__domain_save_state *dss, int rc)
{
STATE_AO_GC(dss->ao);
libxl__ao_complete(egc,ao,rc);
@@ -966,7 +966,7 @@ int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd, int flags,
goto out_err;
}
- libxl__domain_suspend_state *dss;
+ libxl__domain_save_state *dss;
GCNEW(dss);
dss->ao = ao;
@@ -978,7 +978,7 @@ int libxl_domain_suspend(libxl_ctx *ctx, uint32_t domid, int fd, int flags,
dss->live = flags & LIBXL_SUSPEND_LIVE;
dss->debug = flags & LIBXL_SUSPEND_DEBUG;
- libxl__domain_suspend(egc, dss);
+ libxl__domain_save(egc, dss);
return AO_INPROGRESS;
out_err:
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index a0c9850..1f64285 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -1103,8 +1103,8 @@ int libxl__toolstack_restore(uint32_t domid, const uint8_t *buf,
/*==================== Domain suspend (save) ====================*/
-static void domain_suspend_done(libxl__egc *egc,
- libxl__domain_suspend_state *dss, int rc);
+static void domain_save_done(libxl__egc *egc,
+ libxl__domain_save_state *dss, int rc);
static void domain_suspend_callback_common_done(libxl__egc *egc,
libxl__domain_suspend_state *dss, int ok);
@@ -1123,7 +1123,7 @@ static void switch_logdirty_timeout(libxl__egc *egc, libxl__ev_time *ev,
static void switch_logdirty_xswatch(libxl__egc *egc, libxl__ev_xswatch*,
const char *watch_path, const char *event_path);
static void switch_logdirty_done(libxl__egc *egc,
- libxl__domain_suspend_state *dss, int ok);
+ libxl__domain_save_state *dss, int ok);
static void logdirty_init(libxl__logdirty_switch *lds)
{
@@ -1137,7 +1137,7 @@ static void domain_suspend_switch_qemu_xen_traditional_logdirty
libxl__save_helper_state *shs)
{
libxl__egc *egc = shs->egc;
- libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs);
+ libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
libxl__logdirty_switch *lds = &dss->logdirty;
STATE_AO_GC(dss->ao);
int rc;
@@ -1209,7 +1209,7 @@ static void domain_suspend_switch_qemu_xen_logdirty
libxl__save_helper_state *shs)
{
libxl__egc *egc = shs->egc;
- libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs);
+ libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
STATE_AO_GC(dss->ao);
int rc;
@@ -1227,7 +1227,7 @@ void libxl__domain_suspend_common_switch_qemu_logdirty
{
libxl__save_helper_state *shs = user;
libxl__egc *egc = shs->egc;
- libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs);
+ libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
STATE_AO_GC(dss->ao);
switch (libxl__device_model_version_running(gc, domid)) {
@@ -1246,7 +1246,7 @@ void libxl__domain_suspend_common_switch_qemu_logdirty
static void switch_logdirty_timeout(libxl__egc *egc, libxl__ev_time *ev,
const struct timeval *requested_abs)
{
- libxl__domain_suspend_state *dss = CONTAINER_OF(ev, *dss, logdirty.timeout);
+ libxl__domain_save_state *dss = CONTAINER_OF(ev, *dss, logdirty.timeout);
STATE_AO_GC(dss->ao);
LOG(ERROR,"logdirty switch: wait for device model timed out");
switch_logdirty_done(egc,dss,-1);
@@ -1255,7 +1255,7 @@ static void switch_logdirty_timeout(libxl__egc *egc, libxl__ev_time *ev,
static void switch_logdirty_xswatch(libxl__egc *egc, libxl__ev_xswatch *watch,
const char *watch_path, const char *event_path)
{
- libxl__domain_suspend_state *dss =
+ libxl__domain_save_state *dss =
CONTAINER_OF(watch, *dss, logdirty.watch);
libxl__logdirty_switch *lds = &dss->logdirty;
STATE_AO_GC(dss->ao);
@@ -1310,7 +1310,7 @@ static void switch_logdirty_xswatch(libxl__egc *egc, libxl__ev_xswatch *watch,
}
static void switch_logdirty_done(libxl__egc *egc,
- libxl__domain_suspend_state *dss,
+ libxl__domain_save_state *dss,
int broke)
{
STATE_AO_GC(dss->ao);
@@ -1762,16 +1762,18 @@ static void libxl__domain_suspend_callback(void *data)
{
libxl__save_helper_state *shs = data;
libxl__egc *egc = shs->egc;
- libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs);
+ libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
+ libxl__domain_suspend_state *dss2 = &dss->dss;
- dss->callback_common_done = domain_suspend_callback_common_done;
- domain_suspend_callback_common(egc, dss);
+ dss2->callback_common_done = domain_suspend_callback_common_done;
+ domain_suspend_callback_common(egc, dss2);
}
static void domain_suspend_callback_common_done(libxl__egc *egc,
libxl__domain_suspend_state *dss, int ok)
{
- libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, ok);
+ libxl__domain_save_state *dsvs = CONTAINER_OF(dss, *dsvs, dss);
+ libxl__xc_domain_saverestore_async_callback_done(egc, &dsvs->shs, ok);
}
/*----- remus callbacks -----*/
@@ -1788,25 +1790,28 @@ static void libxl__remus_domain_suspend_callback(void *data)
{
libxl__save_helper_state *shs = data;
libxl__egc *egc = shs->egc;
- libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs);
+ libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
+ libxl__domain_suspend_state *dss2 = &dss->dss;
- dss->callback_common_done = remus_domain_suspend_callback_common_done;
- domain_suspend_callback_common(egc, dss);
+ dss2->callback_common_done = remus_domain_suspend_callback_common_done;
+ domain_suspend_callback_common(egc, dss2);
}
static void remus_domain_suspend_callback_common_done(libxl__egc *egc,
libxl__domain_suspend_state *dss, int ok)
{
+ libxl__domain_save_state *dsvs = CONTAINER_OF(dss, *dsvs, dss);
+
if (!ok)
goto out;
- libxl__remus_devices_state *const rds = &dss->rds;
+ libxl__remus_devices_state *const rds = &dsvs->rds;
rds->callback = remus_devices_postsuspend_cb;
libxl__remus_devices_postsuspend(egc, rds);
return;
out:
- libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, ok);
+ libxl__xc_domain_saverestore_async_callback_done(egc, &dsvs->shs, ok);
}
static void remus_devices_postsuspend_cb(libxl__egc *egc,
@@ -1814,7 +1819,7 @@ static void remus_devices_postsuspend_cb(libxl__egc *egc,
int rc)
{
int ok = 0;
- libxl__domain_suspend_state *dss = CONTAINER_OF(rds, *dss, rds);
+ libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
if (rc)
goto out;
@@ -1829,7 +1834,7 @@ static void libxl__remus_domain_resume_callback(void *data)
{
libxl__save_helper_state *shs = data;
libxl__egc *egc = shs->egc;
- libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs);
+ libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
STATE_AO_GC(dss->ao);
libxl__remus_devices_state *const rds = &dss->rds;
@@ -1842,7 +1847,7 @@ static void remus_devices_preresume_cb(libxl__egc *egc,
int rc)
{
int ok = 0;
- libxl__domain_suspend_state *dss = CONTAINER_OF(rds, *dss, rds);
+ libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
STATE_AO_GC(dss->ao);
if (rc)
@@ -1862,7 +1867,7 @@ out:
/*----- remus asynchronous checkpoint callback -----*/
static void remus_checkpoint_dm_saved(libxl__egc *egc,
- libxl__domain_suspend_state *dss, int rc);
+ libxl__domain_save_state *dss, int rc);
static void remus_devices_commit_cb(libxl__egc *egc,
libxl__remus_devices_state *rds,
int rc);
@@ -1872,7 +1877,7 @@ static void remus_next_checkpoint(libxl__egc *egc, libxl__ev_time *ev,
static void libxl__remus_domain_checkpoint_callback(void *data)
{
libxl__save_helper_state *shs = data;
- libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs);
+ libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
libxl__egc *egc = dss->shs.egc;
STATE_AO_GC(dss->ao);
@@ -1885,7 +1890,7 @@ static void libxl__remus_domain_checkpoint_callback(void *data)
}
static void remus_checkpoint_dm_saved(libxl__egc *egc,
- libxl__domain_suspend_state *dss, int rc)
+ libxl__domain_save_state *dss, int rc)
{
/* Convenience aliases */
libxl__remus_devices_state *const rds = &dss->rds;
@@ -1910,7 +1915,7 @@ static void remus_devices_commit_cb(libxl__egc *egc,
libxl__remus_devices_state *rds,
int rc)
{
- libxl__domain_suspend_state *dss = CONTAINER_OF(rds, *dss, rds);
+ libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
STATE_AO_GC(dss->ao);
@@ -1944,7 +1949,7 @@ out:
static void remus_next_checkpoint(libxl__egc *egc, libxl__ev_time *ev,
const struct timeval *requested_abs)
{
- libxl__domain_suspend_state *dss =
+ libxl__domain_save_state *dss =
CONTAINER_OF(ev, *dss, checkpoint_timeout);
STATE_AO_GC(dss->ao);
@@ -1957,9 +1962,9 @@ static void remus_next_checkpoint(libxl__egc *egc, libxl__ev_time *ev,
libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, 1);
}
-/*----- main code for suspending, in order of execution -----*/
+/*----- main code for saving, in order of execution -----*/
-void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss)
+void libxl__domain_save(libxl__egc *egc, libxl__domain_save_state *dss)
{
STATE_AO_GC(dss->ao);
int port;
@@ -1973,20 +1978,23 @@ void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss)
const libxl_domain_remus_info *const r_info = dss->remus;
libxl__srm_save_autogen_callbacks *const callbacks =
&dss->shs.callbacks.save.a;
+ libxl__domain_suspend_state *dss2 = &dss->dss;
logdirty_init(&dss->logdirty);
- libxl__xswait_init(&dss->pvcontrol);
- libxl__ev_evtchn_init(&dss->guest_evtchn);
- libxl__ev_xswatch_init(&dss->guest_watch);
- libxl__ev_time_init(&dss->guest_timeout);
+ libxl__xswait_init(&dss2->pvcontrol);
+ libxl__ev_evtchn_init(&dss2->guest_evtchn);
+ libxl__ev_xswatch_init(&dss2->guest_watch);
+ libxl__ev_time_init(&dss2->guest_timeout);
switch (type) {
case LIBXL_DOMAIN_TYPE_HVM: {
dss->hvm = 1;
+ dss2->hvm = 1;
break;
}
case LIBXL_DOMAIN_TYPE_PV:
dss->hvm = 0;
+ dss2->hvm = 0;
break;
default:
abort();
@@ -1996,10 +2004,12 @@ void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss)
| (debug ? XCFLAGS_DEBUG : 0)
| (dss->hvm ? XCFLAGS_HVM : 0);
- dss->guest_evtchn.port = -1;
- dss->guest_evtchn_lockfd = -1;
- dss->guest_responded = 0;
- dss->dm_savefile = libxl__device_model_savefile(gc, domid);
+ dss2->guest_evtchn.port = -1;
+ dss2->guest_evtchn_lockfd = -1;
+ dss2->guest_responded = 0;
+ dss2->dm_savefile = libxl__device_model_savefile(gc, domid);
+ dss2->domid = domid;
+ dss2->ao = ao;
if (r_info != NULL) {
dss->interval = r_info->interval;
@@ -2008,17 +2018,17 @@ void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss)
dss->xcflags |= XCFLAGS_CHECKPOINT_COMPRESS;
}
- port = xs_suspend_evtchn_port(dss->domid);
+ port = xs_suspend_evtchn_port(dss2->domid);
if (port >= 0) {
rc = libxl__ctx_evtchn_init(gc);
if (rc) goto out;
- dss->guest_evtchn.port =
+ dss2->guest_evtchn.port =
xc_suspend_evtchn_init_exclusive(CTX->xch, CTX->xce,
- dss->domid, port, &dss->guest_evtchn_lockfd);
+ dss2->domid, port, &dss2->guest_evtchn_lockfd);
- if (dss->guest_evtchn.port < 0) {
+ if (dss2->guest_evtchn.port < 0) {
LOG(WARN, "Suspend event channel initialization failed");
rc = ERROR_FAIL;
goto out;
@@ -2040,27 +2050,28 @@ void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss)
return;
out:
- domain_suspend_done(egc, dss, rc);
+ domain_save_done(egc, dss, rc);
}
void libxl__xc_domain_save_done(libxl__egc *egc, void *dss_void,
int rc, int retval, int errnoval)
{
- libxl__domain_suspend_state *dss = dss_void;
+ libxl__domain_save_state *dss = dss_void;
STATE_AO_GC(dss->ao);
/* Convenience aliases */
const libxl_domain_type type = dss->type;
+ libxl__domain_suspend_state *dss2 = &dss->dss;
if (rc)
goto out;
if (retval) {
LOGEV(ERROR, errnoval, "saving domain: %s",
- dss->guest_responded ?
+ dss2->guest_responded ?
"domain responded to suspend request" :
"domain did not respond to suspend request");
- if ( !dss->guest_responded )
+ if ( !dss2->guest_responded )
rc = ERROR_GUEST_TIMEDOUT;
else
rc = ERROR_FAIL;
@@ -2068,24 +2079,24 @@ void libxl__xc_domain_save_done(libxl__egc *egc, void *dss_void,
}
if (type == LIBXL_DOMAIN_TYPE_HVM) {
- rc = libxl__domain_suspend_device_model(gc, dss);
+ rc = libxl__domain_suspend_device_model(gc, dss2);
if (rc) goto out;
- libxl__domain_save_device_model(egc, dss, domain_suspend_done);
+ libxl__domain_save_device_model(egc, dss, domain_save_done);
return;
}
rc = 0;
out:
- domain_suspend_done(egc, dss, rc);
+ domain_save_done(egc, dss, rc);
}
static void save_device_model_datacopier_done(libxl__egc *egc,
libxl__datacopier_state *dc, int onwrite, int errnoval);
void libxl__domain_save_device_model(libxl__egc *egc,
- libxl__domain_suspend_state *dss,
+ libxl__domain_save_state *dss,
libxl__save_device_model_cb *callback)
{
STATE_AO_GC(dss->ao);
@@ -2096,7 +2107,7 @@ void libxl__domain_save_device_model(libxl__egc *egc,
dss->save_dm_callback = callback;
/* Convenience aliases */
- const char *const filename = dss->dm_savefile;
+ const char *const filename = dss->dss.dm_savefile;
const int fd = dss->fd;
libxl__datacopier_state *dc = &dss->save_dm_datacopier;
@@ -2148,12 +2159,12 @@ void libxl__domain_save_device_model(libxl__egc *egc,
static void save_device_model_datacopier_done(libxl__egc *egc,
libxl__datacopier_state *dc, int onwrite, int errnoval)
{
- libxl__domain_suspend_state *dss =
+ libxl__domain_save_state *dss =
CONTAINER_OF(dc, *dss, save_dm_datacopier);
STATE_AO_GC(dss->ao);
/* Convenience aliases */
- const char *const filename = dss->dm_savefile;
+ const char *const filename = dss->dss.dm_savefile;
int our_rc = 0;
int rc;
@@ -2177,19 +2188,20 @@ static void remus_teardown_done(libxl__egc *egc,
libxl__remus_devices_state *rds,
int rc);
-static void domain_suspend_done(libxl__egc *egc,
- libxl__domain_suspend_state *dss, int rc)
+static void domain_save_done(libxl__egc *egc,
+ libxl__domain_save_state *dss, int rc)
{
STATE_AO_GC(dss->ao);
/* Convenience aliases */
const uint32_t domid = dss->domid;
+ libxl__domain_suspend_state *dss2 = &dss->dss;
- libxl__ev_evtchn_cancel(gc, &dss->guest_evtchn);
+ libxl__ev_evtchn_cancel(gc, &dss2->guest_evtchn);
- if (dss->guest_evtchn.port > 0)
+ if (dss2->guest_evtchn.port > 0)
xc_suspend_evtchn_release(CTX->xch, CTX->xce, domid,
- dss->guest_evtchn.port, &dss->guest_evtchn_lockfd);
+ dss2->guest_evtchn.port, &dss2->guest_evtchn_lockfd);
if (!dss->remus) {
dss->callback(egc, dss, rc);
@@ -2212,7 +2224,7 @@ static void remus_teardown_done(libxl__egc *egc,
libxl__remus_devices_state *rds,
int rc)
{
- libxl__domain_suspend_state *dss = CONTAINER_OF(rds, *dss, rds);
+ libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
STATE_AO_GC(dss->ao);
if (rc)
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 8aaa1ad..f86fc89 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -2818,11 +2818,12 @@ _hidden int libxl__netbuffer_enabled(libxl__gc *gc);
/*----- Domain suspend (save) state structure -----*/
typedef struct libxl__domain_suspend_state libxl__domain_suspend_state;
+typedef struct libxl__domain_save_state libxl__domain_save_state;
-typedef void libxl__domain_suspend_cb(libxl__egc*,
- libxl__domain_suspend_state*, int rc);
+typedef void libxl__domain_save_cb(libxl__egc*,
+ libxl__domain_save_state*, int rc);
typedef void libxl__save_device_model_cb(libxl__egc*,
- libxl__domain_suspend_state*, int rc);
+ libxl__domain_save_state*, int rc);
typedef struct libxl__logdirty_switch {
const char *cmd;
@@ -2833,9 +2834,27 @@ typedef struct libxl__logdirty_switch {
} libxl__logdirty_switch;
struct libxl__domain_suspend_state {
+ /* set by caller of domain_suspend_callback_common */
+ libxl__ao *ao;
+
+ uint32_t domid;
+ int hvm;
+ /* private */
+ libxl__ev_evtchn guest_evtchn;
+ int guest_evtchn_lockfd;
+ int guest_responded;
+ libxl__xswait_state pvcontrol;
+ libxl__ev_xswatch guest_watch;
+ libxl__ev_time guest_timeout;
+ const char *dm_savefile;
+ void (*callback_common_done)(libxl__egc*,
+ struct libxl__domain_suspend_state*, int ok);
+};
+
+struct libxl__domain_save_state {
/* set by caller of libxl__domain_suspend */
libxl__ao *ao;
- libxl__domain_suspend_cb *callback;
+ libxl__domain_save_cb *callback;
uint32_t domid;
int fd;
@@ -2844,22 +2863,14 @@ struct libxl__domain_suspend_state {
int debug;
const libxl_domain_remus_info *remus;
/* private */
- libxl__ev_evtchn guest_evtchn;
- int guest_evtchn_lockfd;
+ libxl__domain_suspend_state dss;
int hvm;
int xcflags;
- int guest_responded;
- libxl__xswait_state pvcontrol;
- libxl__ev_xswatch guest_watch;
- libxl__ev_time guest_timeout;
- const char *dm_savefile;
libxl__remus_devices_state rds;
libxl__ev_time checkpoint_timeout; /* used for Remus checkpoint */
int interval; /* checkpoint interval (for Remus) */
libxl__save_helper_state shs;
libxl__logdirty_switch logdirty;
- void (*callback_common_done)(libxl__egc*,
- struct libxl__domain_suspend_state*, int ok);
/* private for libxl__domain_save_device_model */
libxl__save_device_model_cb *save_dm_callback;
libxl__datacopier_state save_dm_datacopier;
@@ -3135,12 +3146,12 @@ struct libxl__domain_create_state {
/*----- Domain suspend (save) functions -----*/
/* calls dss->callback when done */
-_hidden void libxl__domain_suspend(libxl__egc *egc,
- libxl__domain_suspend_state *dss);
+_hidden void libxl__domain_save(libxl__egc *egc,
+ libxl__domain_save_state *dss);
/* calls libxl__xc_domain_suspend_done when done */
-_hidden void libxl__xc_domain_save(libxl__egc*, libxl__domain_suspend_state*);
+_hidden void libxl__xc_domain_save(libxl__egc*, libxl__domain_save_state*);
/* 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. */
@@ -3175,7 +3186,7 @@ _hidden void libxl__xc_domain_restore_done(libxl__egc *egc, void *dcs_void,
_hidden int libxl__domain_suspend_device_model(libxl__gc *gc,
libxl__domain_suspend_state *dss);
_hidden void libxl__domain_save_device_model(libxl__egc *egc,
- libxl__domain_suspend_state *dss,
+ libxl__domain_save_state *dss,
libxl__save_device_model_cb *callback);
_hidden const char *libxl__device_model_savefile(libxl__gc *gc, uint32_t domid);
diff --git a/tools/libxl/libxl_netbuffer.c b/tools/libxl/libxl_netbuffer.c
index edc6843..71c6531 100644
--- a/tools/libxl/libxl_netbuffer.c
+++ b/tools/libxl/libxl_netbuffer.c
@@ -41,7 +41,7 @@ int libxl__netbuffer_enabled(libxl__gc *gc)
int init_subkind_nic(libxl__remus_devices_state *rds)
{
int rc, ret;
- libxl__domain_suspend_state *dss = CONTAINER_OF(rds, *dss, rds);
+ libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
STATE_AO_GC(rds->ao);
diff --git a/tools/libxl/libxl_save_callout.c b/tools/libxl/libxl_save_callout.c
index 40b25e4..cd342b9 100644
--- a/tools/libxl/libxl_save_callout.c
+++ b/tools/libxl/libxl_save_callout.c
@@ -74,7 +74,7 @@ void libxl__xc_domain_restore(libxl__egc *egc, libxl__domain_create_state *dcs,
argnums, ARRAY_SIZE(argnums));
}
-void libxl__xc_domain_save(libxl__egc *egc, libxl__domain_suspend_state *dss)
+void libxl__xc_domain_save(libxl__egc *egc, libxl__domain_save_state *dss)
{
STATE_AO_GC(dss->ao);
int r, rc, toolstack_data_fd = -1;
--
1.9.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH v1 1/5] libxl/save: Refactor libxl__domain_suspend_state
2015-05-20 10:01 ` [PATCH v1 1/5] libxl/save: Refactor libxl__domain_suspend_state Yang Hongyang
@ 2015-06-02 14:40 ` Ian Campbell
2015-06-02 16:10 ` Yang Hongyang
0 siblings, 1 reply; 23+ messages in thread
From: Ian Campbell @ 2015-06-02 14:40 UTC (permalink / raw)
To: Yang Hongyang
Cc: wei.liu2, wency, andrew.cooper3, yunhong.jiang, ian.jackson,
xen-devel, rshriram
On Wed, 2015-05-20 at 18:01 +0800, Yang Hongyang wrote:
> @@ -1762,16 +1762,18 @@ static void libxl__domain_suspend_callback(void *data)
> {
> libxl__save_helper_state *shs = data;
> libxl__egc *egc = shs->egc;
> - libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs);
> + libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
> + libxl__domain_suspend_state *dss2 = &dss->dss;
With dss now being ambiguously save vs suspend I don't think adding a 2
suffix to one of the usages is the right answer.
I think in contexts where you are dealing with both that *save_state and
*suspend_state are the way to go for the local variables. I'm afraid
this will make the change noisier, sorry.
I'm afraid I think that the dss member of struct
libxl__domain_save_state will therefore also need to be called
suspend_state too.
I think we can tolerate using dss in contexts where there is only one of
the two structs in active use, just to avoid even more noise.
Alternatively if there is another name for either "save" or "suspend"
which doesn't start with an s (or conflict with some other type) perhaps
we could go with that. I can't think of one off hand.
Another name might also help because the semantic difference between
suspend and save is something I have to think about every time. Is there
a split along live/dead lines which we could use here perhaps?
> static void domain_suspend_callback_common_done(libxl__egc *egc,
> libxl__domain_suspend_state *dss, int ok)
> {
> - libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, ok);
> + libxl__domain_save_state *dsvs = CONTAINER_OF(dss, *dsvs, dss);
I suppose dsvs is a bit better then dss2. Maybe that's the answer, if
used consistently.
Ian.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v1 1/5] libxl/save: Refactor libxl__domain_suspend_state
2015-06-02 14:40 ` Ian Campbell
@ 2015-06-02 16:10 ` Yang Hongyang
2015-06-03 9:24 ` Ian Campbell
0 siblings, 1 reply; 23+ messages in thread
From: Yang Hongyang @ 2015-06-02 16:10 UTC (permalink / raw)
To: Ian Campbell
Cc: wei.liu2, wency, andrew.cooper3, yunhong.jiang, ian.jackson,
xen-devel, rshriram
On 06/02/2015 10:40 PM, Ian Campbell wrote:
> On Wed, 2015-05-20 at 18:01 +0800, Yang Hongyang wrote:
>> @@ -1762,16 +1762,18 @@ static void libxl__domain_suspend_callback(void *data)
>> {
>> libxl__save_helper_state *shs = data;
>> libxl__egc *egc = shs->egc;
>> - libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs);
>> + libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
>> + libxl__domain_suspend_state *dss2 = &dss->dss;
>
> With dss now being ambiguously save vs suspend I don't think adding a 2
> suffix to one of the usages is the right answer.
>
> I think in contexts where you are dealing with both that *save_state and
> *suspend_state are the way to go for the local variables. I'm afraid
> this will make the change noisier, sorry.
>
> I'm afraid I think that the dss member of struct
> libxl__domain_save_state will therefore also need to be called
> suspend_state too.
>
> I think we can tolerate using dss in contexts where there is only one of
> the two structs in active use, just to avoid even more noise.
>
> Alternatively if there is another name for either "save" or "suspend"
> which doesn't start with an s (or conflict with some other type) perhaps
> we could go with that. I can't think of one off hand.
>
> Another name might also help because the semantic difference between
> suspend and save is something I have to think about every time. Is there
> a split along live/dead lines which we could use here perhaps?
>
>
>> static void domain_suspend_callback_common_done(libxl__egc *egc,
>> libxl__domain_suspend_state *dss, int ok)
>> {
>> - libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, ok);
>> + libxl__domain_save_state *dsvs = CONTAINER_OF(dss, *dsvs, dss);
>
> I suppose dsvs is a bit better then dss2. Maybe that's the answer, if
> used consistently.
If use dsvs to represent save_state consistently, the modification of the
code will be too much. I'm thinking of using "dsps" stands for
domain_suspend_state, is it ok?
>
> Ian.
>
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v1 1/5] libxl/save: Refactor libxl__domain_suspend_state
2015-06-02 16:10 ` Yang Hongyang
@ 2015-06-03 9:24 ` Ian Campbell
2015-06-03 9:50 ` Yang Hongyang
2015-06-03 10:03 ` Yang Hongyang
0 siblings, 2 replies; 23+ messages in thread
From: Ian Campbell @ 2015-06-03 9:24 UTC (permalink / raw)
To: Yang Hongyang, Ian Jackson
Cc: wei.liu2, wency, andrew.cooper3, yunhong.jiang, xen-devel,
rshriram
On Wed, 2015-06-03 at 00:10 +0800, Yang Hongyang wrote:
> On 06/02/2015 10:40 PM, Ian Campbell wrote:
> > On Wed, 2015-05-20 at 18:01 +0800, Yang Hongyang wrote:
> >> @@ -1762,16 +1762,18 @@ static void libxl__domain_suspend_callback(void *data)
> >> {
> >> libxl__save_helper_state *shs = data;
> >> libxl__egc *egc = shs->egc;
> >> - libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs);
> >> + libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
> >> + libxl__domain_suspend_state *dss2 = &dss->dss;
> >
> > With dss now being ambiguously save vs suspend I don't think adding a 2
> > suffix to one of the usages is the right answer.
> >
> > I think in contexts where you are dealing with both that *save_state and
> > *suspend_state are the way to go for the local variables. I'm afraid
> > this will make the change noisier, sorry.
> >
> > I'm afraid I think that the dss member of struct
> > libxl__domain_save_state will therefore also need to be called
> > suspend_state too.
> >
> > I think we can tolerate using dss in contexts where there is only one of
> > the two structs in active use, just to avoid even more noise.
> >
> > Alternatively if there is another name for either "save" or "suspend"
> > which doesn't start with an s (or conflict with some other type) perhaps
> > we could go with that. I can't think of one off hand.
> >
> > Another name might also help because the semantic difference between
> > suspend and save is something I have to think about every time. Is there
> > a split along live/dead lines which we could use here perhaps?
> >
> >
> >> static void domain_suspend_callback_common_done(libxl__egc *egc,
> >> libxl__domain_suspend_state *dss, int ok)
> >> {
> >> - libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, ok);
> >> + libxl__domain_save_state *dsvs = CONTAINER_OF(dss, *dsvs, dss);
> >
> > I suppose dsvs is a bit better then dss2. Maybe that's the answer, if
> > used consistently.
>
> If use dsvs to represent save_state consistently, the modification of the
> code will be too much. I'm thinking of using "dsps" stands for
> domain_suspend_state, is it ok?
So in some contexts you would have "dss" (existing save state) and
"dsps" (new suspend state), which is potentially confusing so I think it
would be worth renaming dss to dsvs in at least those places, it's
mechanical so although noisy it's not too bad.
Ian (J) is the main author if this code (and therefore chose the
existing names), it might be worth giving him a chance to object or
suggest an alternative.
Ian.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v1 1/5] libxl/save: Refactor libxl__domain_suspend_state
2015-06-03 9:24 ` Ian Campbell
@ 2015-06-03 9:50 ` Yang Hongyang
2015-06-03 10:03 ` Yang Hongyang
1 sibling, 0 replies; 23+ messages in thread
From: Yang Hongyang @ 2015-06-03 9:50 UTC (permalink / raw)
To: Ian Campbell, Ian Jackson
Cc: wei.liu2, wency, andrew.cooper3, yunhong.jiang, xen-devel,
rshriram
On 06/03/2015 05:24 PM, Ian Campbell wrote:
> On Wed, 2015-06-03 at 00:10 +0800, Yang Hongyang wrote:
>> On 06/02/2015 10:40 PM, Ian Campbell wrote:
>>> On Wed, 2015-05-20 at 18:01 +0800, Yang Hongyang wrote:
>>>> @@ -1762,16 +1762,18 @@ static void libxl__domain_suspend_callback(void *data)
>>>> {
>>>> libxl__save_helper_state *shs = data;
>>>> libxl__egc *egc = shs->egc;
>>>> - libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs);
>>>> + libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
>>>> + libxl__domain_suspend_state *dss2 = &dss->dss;
>>>
>>> With dss now being ambiguously save vs suspend I don't think adding a 2
>>> suffix to one of the usages is the right answer.
>>>
>>> I think in contexts where you are dealing with both that *save_state and
>>> *suspend_state are the way to go for the local variables. I'm afraid
>>> this will make the change noisier, sorry.
>>>
>>> I'm afraid I think that the dss member of struct
>>> libxl__domain_save_state will therefore also need to be called
>>> suspend_state too.
>>>
>>> I think we can tolerate using dss in contexts where there is only one of
>>> the two structs in active use, just to avoid even more noise.
>>>
>>> Alternatively if there is another name for either "save" or "suspend"
>>> which doesn't start with an s (or conflict with some other type) perhaps
>>> we could go with that. I can't think of one off hand.
>>>
>>> Another name might also help because the semantic difference between
>>> suspend and save is something I have to think about every time. Is there
>>> a split along live/dead lines which we could use here perhaps?
>>>
>>>
>>>> static void domain_suspend_callback_common_done(libxl__egc *egc,
>>>> libxl__domain_suspend_state *dss, int ok)
>>>> {
>>>> - libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, ok);
>>>> + libxl__domain_save_state *dsvs = CONTAINER_OF(dss, *dsvs, dss);
>>>
>>> I suppose dsvs is a bit better then dss2. Maybe that's the answer, if
>>> used consistently.
>>
>> If use dsvs to represent save_state consistently, the modification of the
>> code will be too much. I'm thinking of using "dsps" stands for
>> domain_suspend_state, is it ok?
>
> So in some contexts you would have "dss" (existing save state) and
> "dsps" (new suspend state), which is potentially confusing so I think it
> would be worth renaming dss to dsvs in at least those places, it's
> mechanical so although noisy it's not too bad.
>
> Ian (J) is the main author if this code (and therefore chose the
> existing names), it might be worth giving him a chance to object or
> suggest an alternative.
OK, thanks
>
> Ian.
>
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v1 1/5] libxl/save: Refactor libxl__domain_suspend_state
2015-06-03 9:24 ` Ian Campbell
2015-06-03 9:50 ` Yang Hongyang
@ 2015-06-03 10:03 ` Yang Hongyang
1 sibling, 0 replies; 23+ messages in thread
From: Yang Hongyang @ 2015-06-03 10:03 UTC (permalink / raw)
To: Ian Campbell, Ian Jackson
Cc: wei.liu2, wency, andrew.cooper3, yunhong.jiang, xen-devel,
rshriram
On 06/03/2015 05:24 PM, Ian Campbell wrote:
> On Wed, 2015-06-03 at 00:10 +0800, Yang Hongyang wrote:
>> On 06/02/2015 10:40 PM, Ian Campbell wrote:
>>> On Wed, 2015-05-20 at 18:01 +0800, Yang Hongyang wrote:
>>>> @@ -1762,16 +1762,18 @@ static void libxl__domain_suspend_callback(void *data)
>>>> {
>>>> libxl__save_helper_state *shs = data;
>>>> libxl__egc *egc = shs->egc;
>>>> - libxl__domain_suspend_state *dss = CONTAINER_OF(shs, *dss, shs);
>>>> + libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
>>>> + libxl__domain_suspend_state *dss2 = &dss->dss;
>>>
>>> With dss now being ambiguously save vs suspend I don't think adding a 2
>>> suffix to one of the usages is the right answer.
>>>
>>> I think in contexts where you are dealing with both that *save_state and
>>> *suspend_state are the way to go for the local variables. I'm afraid
>>> this will make the change noisier, sorry.
>>>
>>> I'm afraid I think that the dss member of struct
>>> libxl__domain_save_state will therefore also need to be called
>>> suspend_state too.
>>>
>>> I think we can tolerate using dss in contexts where there is only one of
>>> the two structs in active use, just to avoid even more noise.
>>>
>>> Alternatively if there is another name for either "save" or "suspend"
>>> which doesn't start with an s (or conflict with some other type) perhaps
>>> we could go with that. I can't think of one off hand.
>>>
>>> Another name might also help because the semantic difference between
>>> suspend and save is something I have to think about every time. Is there
>>> a split along live/dead lines which we could use here perhaps?
>>>
>>>
>>>> static void domain_suspend_callback_common_done(libxl__egc *egc,
>>>> libxl__domain_suspend_state *dss, int ok)
>>>> {
>>>> - libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, ok);
>>>> + libxl__domain_save_state *dsvs = CONTAINER_OF(dss, *dsvs, dss);
>>>
>>> I suppose dsvs is a bit better then dss2. Maybe that's the answer, if
>>> used consistently.
>>
>> If use dsvs to represent save_state consistently, the modification of the
>> code will be too much. I'm thinking of using "dsps" stands for
>> domain_suspend_state, is it ok?
>
> So in some contexts you would have "dss" (existing save state) and
> "dsps" (new suspend state), which is potentially confusing so I think it
> would be worth renaming dss to dsvs in at least those places, it's
> mechanical so although noisy it's not too bad.
Ah, my thought was use "dsps" consistently, that is all placees that
using libxl__domain_suspend_state will be renamed to dsps.(after
moving the suspend code into libxl_dom_suspend.c, dsps mostly appears
there).It did confuse one if he is familiar with the old code. But I think
it will make the code clearer for new readers. Anyway, let's wait for
Ian (J)'s comment.
>
> Ian (J) is the main author if this code (and therefore chose the
> existing names), it might be worth giving him a chance to object or
> suggest an alternative.
>
> Ian.
>
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v1 2/5] tools/libxl: move domain suspend codes into a separate file
2015-05-20 10:01 [PATCH v1 0/5] Misc cleanups for libxl Yang Hongyang
2015-05-20 10:01 ` [PATCH v1 1/5] libxl/save: Refactor libxl__domain_suspend_state Yang Hongyang
@ 2015-05-20 10:01 ` Yang Hongyang
2015-06-02 14:44 ` Ian Campbell
2015-06-02 14:45 ` Ian Campbell
2015-05-20 10:01 ` [PATCH v1 3/5] tools/libxl: move remus codes into libxl_remus.c Yang Hongyang
` (4 subsequent siblings)
6 siblings, 2 replies; 23+ messages in thread
From: Yang Hongyang @ 2015-05-20 10:01 UTC (permalink / raw)
To: xen-devel
Cc: wei.liu2, ian.campbell, wency, andrew.cooper3, yunhong.jiang,
ian.jackson, rshriram
move domain suspend codes into a separate file libxl_dom_suspend.c
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
CC: Ian Campbell <Ian.Campbell@citrix.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Andrew Cooper <andrew.cooper3@citrix.com>
---
tools/libxl/Makefile | 3 +-
tools/libxl/libxl_dom.c | 376 +------------------------------------
tools/libxl/libxl_dom_suspend.c | 400 ++++++++++++++++++++++++++++++++++++++++
tools/libxl/libxl_internal.h | 6 +
4 files changed, 412 insertions(+), 373 deletions(-)
create mode 100644 tools/libxl/libxl_dom_suspend.c
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index 1b16598..21558b0 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -95,7 +95,8 @@ LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \
libxl_internal.o libxl_utils.o libxl_uuid.o \
libxl_json.o libxl_aoutils.o libxl_numa.o libxl_vnuma.o \
libxl_save_callout.o _libxl_save_msgs_callout.o \
- libxl_qmp.o libxl_event.o libxl_fork.o $(LIBXL_OBJS-y)
+ libxl_qmp.o libxl_event.o libxl_fork.o libxl_dom_suspend.o \
+ $(LIBXL_OBJS-y)
LIBXL_OBJS += libxl_genid.o
LIBXL_OBJS += _libxl_types.o libxl_flask.o _libxl_types_internal.o
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index 1f64285..1681a12 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -1101,13 +1101,6 @@ int libxl__toolstack_restore(uint32_t domid, const uint8_t *buf,
return 0;
}
-/*==================== Domain suspend (save) ====================*/
-
-static void domain_save_done(libxl__egc *egc,
- libxl__domain_save_state *dss, int rc);
-static void domain_suspend_callback_common_done(libxl__egc *egc,
- libxl__domain_suspend_state *dss, int ok);
-
/*----- complicated callback, called by xc_domain_save -----*/
/*
@@ -1322,352 +1315,6 @@ static void switch_logdirty_done(libxl__egc *egc,
libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, broke);
}
-/*----- callbacks, called by xc_domain_save -----*/
-
-int libxl__domain_suspend_device_model(libxl__gc *gc,
- libxl__domain_suspend_state *dss)
-{
- int ret = 0;
- uint32_t const domid = dss->domid;
- const char *const filename = dss->dm_savefile;
-
- switch (libxl__device_model_version_running(gc, domid)) {
- case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL: {
- LOG(DEBUG, "Saving device model state to %s", filename);
- libxl__qemu_traditional_cmd(gc, domid, "save");
- libxl__wait_for_device_model_deprecated(gc, domid, "paused", NULL, NULL, NULL);
- break;
- }
- case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
- if (libxl__qmp_stop(gc, domid))
- return ERROR_FAIL;
- /* Save DM state into filename */
- ret = libxl__qmp_save(gc, domid, filename);
- if (ret)
- unlink(filename);
- break;
- default:
- return ERROR_INVAL;
- }
-
- return ret;
-}
-
-int libxl__domain_resume_device_model(libxl__gc *gc, uint32_t domid)
-{
-
- switch (libxl__device_model_version_running(gc, domid)) {
- case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL: {
- libxl__qemu_traditional_cmd(gc, domid, "continue");
- libxl__wait_for_device_model_deprecated(gc, domid, "running", NULL, NULL, NULL);
- break;
- }
- case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
- if (libxl__qmp_resume(gc, domid))
- return ERROR_FAIL;
- break;
- default:
- return ERROR_INVAL;
- }
-
- return 0;
-}
-
-static void domain_suspend_common_wait_guest(libxl__egc *egc,
- libxl__domain_suspend_state *dss);
-static void domain_suspend_common_guest_suspended(libxl__egc *egc,
- libxl__domain_suspend_state *dss);
-
-static void domain_suspend_common_pvcontrol_suspending(libxl__egc *egc,
- libxl__xswait_state *xswa, int rc, const char *state);
-static void domain_suspend_common_wait_guest_evtchn(libxl__egc *egc,
- libxl__ev_evtchn *evev);
-static void suspend_common_wait_guest_watch(libxl__egc *egc,
- libxl__ev_xswatch *xsw, const char *watch_path, const char *event_path);
-static void suspend_common_wait_guest_check(libxl__egc *egc,
- libxl__domain_suspend_state *dss);
-static void suspend_common_wait_guest_timeout(libxl__egc *egc,
- libxl__ev_time *ev, const struct timeval *requested_abs);
-
-static void domain_suspend_common_failed(libxl__egc *egc,
- libxl__domain_suspend_state *dss);
-static void domain_suspend_common_done(libxl__egc *egc,
- libxl__domain_suspend_state *dss,
- bool ok);
-
-static bool domain_suspend_pvcontrol_acked(const char *state) {
- /* any value other than "suspend", including ENOENT (i.e. !state), is OK */
- if (!state) return 1;
- return strcmp(state,"suspend");
-}
-
-/* calls dss->callback_common_done when done */
-static void domain_suspend_callback_common(libxl__egc *egc,
- libxl__domain_suspend_state *dss)
-{
- STATE_AO_GC(dss->ao);
- uint64_t hvm_s_state = 0, hvm_pvdrv = 0;
- int ret, rc;
-
- /* Convenience aliases */
- const uint32_t domid = dss->domid;
-
- if (dss->hvm) {
- xc_hvm_param_get(CTX->xch, domid, HVM_PARAM_CALLBACK_IRQ, &hvm_pvdrv);
- xc_hvm_param_get(CTX->xch, domid, HVM_PARAM_ACPI_S_STATE, &hvm_s_state);
- }
-
- if ((hvm_s_state == 0) && (dss->guest_evtchn.port >= 0)) {
- LOG(DEBUG, "issuing %s suspend request via event channel",
- dss->hvm ? "PVHVM" : "PV");
- ret = xc_evtchn_notify(CTX->xce, dss->guest_evtchn.port);
- if (ret < 0) {
- LOG(ERROR, "xc_evtchn_notify failed ret=%d", ret);
- goto err;
- }
-
- dss->guest_evtchn.callback = domain_suspend_common_wait_guest_evtchn;
- rc = libxl__ev_evtchn_wait(gc, &dss->guest_evtchn);
- if (rc) goto err;
-
- rc = libxl__ev_time_register_rel(gc, &dss->guest_timeout,
- suspend_common_wait_guest_timeout,
- 60*1000);
- if (rc) goto err;
-
- return;
- }
-
- if (dss->hvm && (!hvm_pvdrv || hvm_s_state)) {
- LOG(DEBUG, "Calling xc_domain_shutdown on HVM domain");
- ret = xc_domain_shutdown(CTX->xch, domid, SHUTDOWN_suspend);
- if (ret < 0) {
- LOGE(ERROR, "xc_domain_shutdown failed");
- goto err;
- }
- /* The guest does not (need to) respond to this sort of request. */
- dss->guest_responded = 1;
- domain_suspend_common_wait_guest(egc, dss);
- return;
- }
-
- LOG(DEBUG, "issuing %s suspend request via XenBus control node",
- dss->hvm ? "PVHVM" : "PV");
-
- libxl__domain_pvcontrol_write(gc, XBT_NULL, domid, "suspend");
-
- dss->pvcontrol.path = libxl__domain_pvcontrol_xspath(gc, domid);
- if (!dss->pvcontrol.path) goto err;
-
- dss->pvcontrol.ao = ao;
- dss->pvcontrol.what = "guest acknowledgement of suspend request";
- dss->pvcontrol.timeout_ms = 60 * 1000;
- dss->pvcontrol.callback = domain_suspend_common_pvcontrol_suspending;
- libxl__xswait_start(gc, &dss->pvcontrol);
- return;
-
- err:
- domain_suspend_common_failed(egc, dss);
-}
-
-static void domain_suspend_common_wait_guest_evtchn(libxl__egc *egc,
- libxl__ev_evtchn *evev)
-{
- libxl__domain_suspend_state *dss = CONTAINER_OF(evev, *dss, guest_evtchn);
- STATE_AO_GC(dss->ao);
- /* If we should be done waiting, suspend_common_wait_guest_check
- * will end up calling domain_suspend_common_guest_suspended or
- * domain_suspend_common_failed, both of which cancel the evtchn
- * wait. So re-enable it now. */
- libxl__ev_evtchn_wait(gc, &dss->guest_evtchn);
- suspend_common_wait_guest_check(egc, dss);
-}
-
-static void domain_suspend_common_pvcontrol_suspending(libxl__egc *egc,
- libxl__xswait_state *xswa, int rc, const char *state)
-{
- libxl__domain_suspend_state *dss = CONTAINER_OF(xswa, *dss, pvcontrol);
- STATE_AO_GC(dss->ao);
- xs_transaction_t t = 0;
-
- if (!rc && !domain_suspend_pvcontrol_acked(state))
- /* keep waiting */
- return;
-
- libxl__xswait_stop(gc, &dss->pvcontrol);
-
- if (rc == ERROR_TIMEDOUT) {
- /*
- * Guest appears to not be responding. Cancel the suspend
- * request.
- *
- * We re-read the suspend node and clear it within a
- * transaction in order to handle the case where we race
- * against the guest catching up and acknowledging the request
- * at the last minute.
- */
- for (;;) {
- rc = libxl__xs_transaction_start(gc, &t);
- if (rc) goto err;
-
- rc = libxl__xs_read_checked(gc, t, xswa->path, &state);
- if (rc) goto err;
-
- if (domain_suspend_pvcontrol_acked(state))
- /* last minute ack */
- break;
-
- rc = libxl__xs_write_checked(gc, t, xswa->path, "");
- if (rc) goto err;
-
- rc = libxl__xs_transaction_commit(gc, &t);
- if (!rc) {
- LOG(ERROR,
- "guest didn't acknowledge suspend, cancelling request");
- goto err;
- }
- if (rc<0) goto err;
- }
- } else if (rc) {
- /* some error in xswait's read of xenstore, already logged */
- goto err;
- }
-
- assert(domain_suspend_pvcontrol_acked(state));
- LOG(DEBUG, "guest acknowledged suspend request");
-
- libxl__xs_transaction_abort(gc, &t);
- dss->guest_responded = 1;
- domain_suspend_common_wait_guest(egc,dss);
- return;
-
- err:
- libxl__xs_transaction_abort(gc, &t);
- domain_suspend_common_failed(egc, dss);
- return;
-}
-
-static void domain_suspend_common_wait_guest(libxl__egc *egc,
- libxl__domain_suspend_state *dss)
-{
- STATE_AO_GC(dss->ao);
- int rc;
-
- LOG(DEBUG, "wait for the guest to suspend");
-
- rc = libxl__ev_xswatch_register(gc, &dss->guest_watch,
- suspend_common_wait_guest_watch,
- "@releaseDomain");
- if (rc) goto err;
-
- rc = libxl__ev_time_register_rel(gc, &dss->guest_timeout,
- suspend_common_wait_guest_timeout,
- 60*1000);
- if (rc) goto err;
- return;
-
- err:
- domain_suspend_common_failed(egc, dss);
-}
-
-static void suspend_common_wait_guest_watch(libxl__egc *egc,
- libxl__ev_xswatch *xsw, const char *watch_path, const char *event_path)
-{
- libxl__domain_suspend_state *dss = CONTAINER_OF(xsw, *dss, guest_watch);
- suspend_common_wait_guest_check(egc, dss);
-}
-
-static void suspend_common_wait_guest_check(libxl__egc *egc,
- libxl__domain_suspend_state *dss)
-{
- STATE_AO_GC(dss->ao);
- xc_domaininfo_t info;
- int ret;
- int shutdown_reason;
-
- /* Convenience aliases */
- const uint32_t domid = dss->domid;
-
- ret = xc_domain_getinfolist(CTX->xch, domid, 1, &info);
- if (ret < 0) {
- LOGE(ERROR, "unable to check for status of guest %"PRId32"", domid);
- goto err;
- }
-
- if (!(ret == 1 && info.domain == domid)) {
- LOGE(ERROR, "guest %"PRId32" we were suspending has been destroyed",
- domid);
- goto err;
- }
-
- if (!(info.flags & XEN_DOMINF_shutdown))
- /* keep waiting */
- return;
-
- shutdown_reason = (info.flags >> XEN_DOMINF_shutdownshift)
- & XEN_DOMINF_shutdownmask;
- if (shutdown_reason != SHUTDOWN_suspend) {
- LOG(DEBUG, "guest %"PRId32" we were suspending has shut down"
- " with unexpected reason code %d", domid, shutdown_reason);
- goto err;
- }
-
- LOG(DEBUG, "guest has suspended");
- domain_suspend_common_guest_suspended(egc, dss);
- return;
-
- err:
- domain_suspend_common_failed(egc, dss);
-}
-
-static void suspend_common_wait_guest_timeout(libxl__egc *egc,
- libxl__ev_time *ev, const struct timeval *requested_abs)
-{
- libxl__domain_suspend_state *dss = CONTAINER_OF(ev, *dss, guest_timeout);
- STATE_AO_GC(dss->ao);
- LOG(ERROR, "guest did not suspend, timed out");
- domain_suspend_common_failed(egc, dss);
-}
-
-static void domain_suspend_common_guest_suspended(libxl__egc *egc,
- libxl__domain_suspend_state *dss)
-{
- STATE_AO_GC(dss->ao);
- int ret;
-
- libxl__ev_evtchn_cancel(gc, &dss->guest_evtchn);
- libxl__ev_xswatch_deregister(gc, &dss->guest_watch);
- libxl__ev_time_deregister(gc, &dss->guest_timeout);
-
- if (dss->hvm) {
- ret = libxl__domain_suspend_device_model(gc, dss);
- if (ret) {
- LOG(ERROR, "libxl__domain_suspend_device_model failed ret=%d", ret);
- domain_suspend_common_failed(egc, dss);
- return;
- }
- }
- domain_suspend_common_done(egc, dss, 1);
-}
-
-static void domain_suspend_common_failed(libxl__egc *egc,
- libxl__domain_suspend_state *dss)
-{
- domain_suspend_common_done(egc, dss, 0);
-}
-
-static void domain_suspend_common_done(libxl__egc *egc,
- libxl__domain_suspend_state *dss,
- bool ok)
-{
- EGC_GC;
- assert(!libxl__xswait_inuse(&dss->pvcontrol));
- libxl__ev_evtchn_cancel(gc, &dss->guest_evtchn);
- libxl__ev_xswatch_deregister(gc, &dss->guest_watch);
- libxl__ev_time_deregister(gc, &dss->guest_timeout);
- dss->callback_common_done(egc, dss, ok);
-}
-
static inline char *physmap_path(libxl__gc *gc, uint32_t dm_domid,
uint32_t domid,
char *phys_offset, char *node)
@@ -1758,24 +1405,6 @@ int libxl__toolstack_save(uint32_t domid, uint8_t **buf,
return 0;
}
-static void libxl__domain_suspend_callback(void *data)
-{
- libxl__save_helper_state *shs = data;
- libxl__egc *egc = shs->egc;
- libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
- libxl__domain_suspend_state *dss2 = &dss->dss;
-
- dss2->callback_common_done = domain_suspend_callback_common_done;
- domain_suspend_callback_common(egc, dss2);
-}
-
-static void domain_suspend_callback_common_done(libxl__egc *egc,
- libxl__domain_suspend_state *dss, int ok)
-{
- libxl__domain_save_state *dsvs = CONTAINER_OF(dss, *dsvs, dss);
- libxl__xc_domain_saverestore_async_callback_done(egc, &dsvs->shs, ok);
-}
-
/*----- remus callbacks -----*/
static void remus_domain_suspend_callback_common_done(libxl__egc *egc,
libxl__domain_suspend_state *dss, int ok);
@@ -1794,7 +1423,7 @@ static void libxl__remus_domain_suspend_callback(void *data)
libxl__domain_suspend_state *dss2 = &dss->dss;
dss2->callback_common_done = remus_domain_suspend_callback_common_done;
- domain_suspend_callback_common(egc, dss2);
+ libxl__domain_suspend(egc, dss2);
}
static void remus_domain_suspend_callback_common_done(libxl__egc *egc,
@@ -1964,6 +1593,9 @@ static void remus_next_checkpoint(libxl__egc *egc, libxl__ev_time *ev,
/*----- main code for saving, in order of execution -----*/
+static void domain_save_done(libxl__egc *egc,
+ libxl__domain_save_state *dss, int rc);
+
void libxl__domain_save(libxl__egc *egc, libxl__domain_save_state *dss)
{
STATE_AO_GC(dss->ao);
diff --git a/tools/libxl/libxl_dom_suspend.c b/tools/libxl/libxl_dom_suspend.c
new file mode 100644
index 0000000..d3c1f39
--- /dev/null
+++ b/tools/libxl/libxl_dom_suspend.c
@@ -0,0 +1,400 @@
+/*
+ * Copyright (C) 2009 Citrix Ltd.
+ * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h" /* must come before any other headers */
+
+#include "libxl_internal.h"
+
+static void domain_suspend_callback_common_done(libxl__egc *egc,
+ libxl__domain_suspend_state *dss, int ok);
+
+/*----- callbacks, called by xc_domain_save -----*/
+
+int libxl__domain_suspend_device_model(libxl__gc *gc,
+ libxl__domain_suspend_state *dss)
+{
+ int ret = 0;
+ uint32_t const domid = dss->domid;
+ const char *const filename = dss->dm_savefile;
+
+ switch (libxl__device_model_version_running(gc, domid)) {
+ case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL: {
+ LOG(DEBUG, "Saving device model state to %s", filename);
+ libxl__qemu_traditional_cmd(gc, domid, "save");
+ libxl__wait_for_device_model_deprecated(gc, domid, "paused", NULL, NULL, NULL);
+ break;
+ }
+ case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
+ if (libxl__qmp_stop(gc, domid))
+ return ERROR_FAIL;
+ /* Save DM state into filename */
+ ret = libxl__qmp_save(gc, domid, filename);
+ if (ret)
+ unlink(filename);
+ break;
+ default:
+ return ERROR_INVAL;
+ }
+
+ return ret;
+}
+
+int libxl__domain_resume_device_model(libxl__gc *gc, uint32_t domid)
+{
+
+ switch (libxl__device_model_version_running(gc, domid)) {
+ case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL: {
+ libxl__qemu_traditional_cmd(gc, domid, "continue");
+ libxl__wait_for_device_model_deprecated(gc, domid, "running", NULL, NULL, NULL);
+ break;
+ }
+ case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
+ if (libxl__qmp_resume(gc, domid))
+ return ERROR_FAIL;
+ break;
+ default:
+ return ERROR_INVAL;
+ }
+
+ return 0;
+}
+
+static void domain_suspend_common_wait_guest(libxl__egc *egc,
+ libxl__domain_suspend_state *dss);
+static void domain_suspend_common_guest_suspended(libxl__egc *egc,
+ libxl__domain_suspend_state *dss);
+
+static void domain_suspend_common_pvcontrol_suspending(libxl__egc *egc,
+ libxl__xswait_state *xswa, int rc, const char *state);
+static void domain_suspend_common_wait_guest_evtchn(libxl__egc *egc,
+ libxl__ev_evtchn *evev);
+static void suspend_common_wait_guest_watch(libxl__egc *egc,
+ libxl__ev_xswatch *xsw, const char *watch_path, const char *event_path);
+static void suspend_common_wait_guest_check(libxl__egc *egc,
+ libxl__domain_suspend_state *dss);
+static void suspend_common_wait_guest_timeout(libxl__egc *egc,
+ libxl__ev_time *ev, const struct timeval *requested_abs);
+
+static void domain_suspend_common_failed(libxl__egc *egc,
+ libxl__domain_suspend_state *dss);
+static void domain_suspend_common_done(libxl__egc *egc,
+ libxl__domain_suspend_state *dss,
+ bool ok);
+static void domain_suspend_callback_common(libxl__egc *egc,
+ libxl__domain_suspend_state *dss);
+
+static bool domain_suspend_pvcontrol_acked(const char *state) {
+ /* any value other than "suspend", including ENOENT (i.e. !state), is OK */
+ if (!state) return 1;
+ return strcmp(state,"suspend");
+}
+
+void libxl__domain_suspend(libxl__egc *egc,
+ libxl__domain_suspend_state *dss)
+{
+ domain_suspend_callback_common(egc, dss);
+}
+
+/* calls dss->callback_common_done when done */
+static void domain_suspend_callback_common(libxl__egc *egc,
+ libxl__domain_suspend_state *dss)
+{
+ STATE_AO_GC(dss->ao);
+ uint64_t hvm_s_state = 0, hvm_pvdrv = 0;
+ int ret, rc;
+
+ /* Convenience aliases */
+ const uint32_t domid = dss->domid;
+
+ if (dss->hvm) {
+ xc_hvm_param_get(CTX->xch, domid, HVM_PARAM_CALLBACK_IRQ, &hvm_pvdrv);
+ xc_hvm_param_get(CTX->xch, domid, HVM_PARAM_ACPI_S_STATE, &hvm_s_state);
+ }
+
+ if ((hvm_s_state == 0) && (dss->guest_evtchn.port >= 0)) {
+ LOG(DEBUG, "issuing %s suspend request via event channel",
+ dss->hvm ? "PVHVM" : "PV");
+ ret = xc_evtchn_notify(CTX->xce, dss->guest_evtchn.port);
+ if (ret < 0) {
+ LOG(ERROR, "xc_evtchn_notify failed ret=%d", ret);
+ goto err;
+ }
+
+ dss->guest_evtchn.callback = domain_suspend_common_wait_guest_evtchn;
+ rc = libxl__ev_evtchn_wait(gc, &dss->guest_evtchn);
+ if (rc) goto err;
+
+ rc = libxl__ev_time_register_rel(gc, &dss->guest_timeout,
+ suspend_common_wait_guest_timeout,
+ 60*1000);
+ if (rc) goto err;
+
+ return;
+ }
+
+ if (dss->hvm && (!hvm_pvdrv || hvm_s_state)) {
+ LOG(DEBUG, "Calling xc_domain_shutdown on HVM domain");
+ ret = xc_domain_shutdown(CTX->xch, domid, SHUTDOWN_suspend);
+ if (ret < 0) {
+ LOGE(ERROR, "xc_domain_shutdown failed");
+ goto err;
+ }
+ /* The guest does not (need to) respond to this sort of request. */
+ dss->guest_responded = 1;
+ domain_suspend_common_wait_guest(egc, dss);
+ return;
+ }
+
+ LOG(DEBUG, "issuing %s suspend request via XenBus control node",
+ dss->hvm ? "PVHVM" : "PV");
+
+ libxl__domain_pvcontrol_write(gc, XBT_NULL, domid, "suspend");
+
+ dss->pvcontrol.path = libxl__domain_pvcontrol_xspath(gc, domid);
+ if (!dss->pvcontrol.path) goto err;
+
+ dss->pvcontrol.ao = ao;
+ dss->pvcontrol.what = "guest acknowledgement of suspend request";
+ dss->pvcontrol.timeout_ms = 60 * 1000;
+ dss->pvcontrol.callback = domain_suspend_common_pvcontrol_suspending;
+ libxl__xswait_start(gc, &dss->pvcontrol);
+ return;
+
+ err:
+ domain_suspend_common_failed(egc, dss);
+}
+
+static void domain_suspend_common_wait_guest_evtchn(libxl__egc *egc,
+ libxl__ev_evtchn *evev)
+{
+ libxl__domain_suspend_state *dss = CONTAINER_OF(evev, *dss, guest_evtchn);
+ STATE_AO_GC(dss->ao);
+ /* If we should be done waiting, suspend_common_wait_guest_check
+ * will end up calling domain_suspend_common_guest_suspended or
+ * domain_suspend_common_failed, both of which cancel the evtchn
+ * wait. So re-enable it now. */
+ libxl__ev_evtchn_wait(gc, &dss->guest_evtchn);
+ suspend_common_wait_guest_check(egc, dss);
+}
+
+static void domain_suspend_common_pvcontrol_suspending(libxl__egc *egc,
+ libxl__xswait_state *xswa, int rc, const char *state)
+{
+ libxl__domain_suspend_state *dss = CONTAINER_OF(xswa, *dss, pvcontrol);
+ STATE_AO_GC(dss->ao);
+ xs_transaction_t t = 0;
+
+ if (!rc && !domain_suspend_pvcontrol_acked(state))
+ /* keep waiting */
+ return;
+
+ libxl__xswait_stop(gc, &dss->pvcontrol);
+
+ if (rc == ERROR_TIMEDOUT) {
+ /*
+ * Guest appears to not be responding. Cancel the suspend
+ * request.
+ *
+ * We re-read the suspend node and clear it within a
+ * transaction in order to handle the case where we race
+ * against the guest catching up and acknowledging the request
+ * at the last minute.
+ */
+ for (;;) {
+ rc = libxl__xs_transaction_start(gc, &t);
+ if (rc) goto err;
+
+ rc = libxl__xs_read_checked(gc, t, xswa->path, &state);
+ if (rc) goto err;
+
+ if (domain_suspend_pvcontrol_acked(state))
+ /* last minute ack */
+ break;
+
+ rc = libxl__xs_write_checked(gc, t, xswa->path, "");
+ if (rc) goto err;
+
+ rc = libxl__xs_transaction_commit(gc, &t);
+ if (!rc) {
+ LOG(ERROR,
+ "guest didn't acknowledge suspend, cancelling request");
+ goto err;
+ }
+ if (rc<0) goto err;
+ }
+ } else if (rc) {
+ /* some error in xswait's read of xenstore, already logged */
+ goto err;
+ }
+
+ assert(domain_suspend_pvcontrol_acked(state));
+ LOG(DEBUG, "guest acknowledged suspend request");
+
+ libxl__xs_transaction_abort(gc, &t);
+ dss->guest_responded = 1;
+ domain_suspend_common_wait_guest(egc,dss);
+ return;
+
+ err:
+ libxl__xs_transaction_abort(gc, &t);
+ domain_suspend_common_failed(egc, dss);
+ return;
+}
+
+static void domain_suspend_common_wait_guest(libxl__egc *egc,
+ libxl__domain_suspend_state *dss)
+{
+ STATE_AO_GC(dss->ao);
+ int rc;
+
+ LOG(DEBUG, "wait for the guest to suspend");
+
+ rc = libxl__ev_xswatch_register(gc, &dss->guest_watch,
+ suspend_common_wait_guest_watch,
+ "@releaseDomain");
+ if (rc) goto err;
+
+ rc = libxl__ev_time_register_rel(gc, &dss->guest_timeout,
+ suspend_common_wait_guest_timeout,
+ 60*1000);
+ if (rc) goto err;
+ return;
+
+ err:
+ domain_suspend_common_failed(egc, dss);
+}
+
+static void suspend_common_wait_guest_watch(libxl__egc *egc,
+ libxl__ev_xswatch *xsw, const char *watch_path, const char *event_path)
+{
+ libxl__domain_suspend_state *dss = CONTAINER_OF(xsw, *dss, guest_watch);
+ suspend_common_wait_guest_check(egc, dss);
+}
+
+static void suspend_common_wait_guest_check(libxl__egc *egc,
+ libxl__domain_suspend_state *dss)
+{
+ STATE_AO_GC(dss->ao);
+ xc_domaininfo_t info;
+ int ret;
+ int shutdown_reason;
+
+ /* Convenience aliases */
+ const uint32_t domid = dss->domid;
+
+ ret = xc_domain_getinfolist(CTX->xch, domid, 1, &info);
+ if (ret < 0) {
+ LOGE(ERROR, "unable to check for status of guest %"PRId32"", domid);
+ goto err;
+ }
+
+ if (!(ret == 1 && info.domain == domid)) {
+ LOGE(ERROR, "guest %"PRId32" we were suspending has been destroyed",
+ domid);
+ goto err;
+ }
+
+ if (!(info.flags & XEN_DOMINF_shutdown))
+ /* keep waiting */
+ return;
+
+ shutdown_reason = (info.flags >> XEN_DOMINF_shutdownshift)
+ & XEN_DOMINF_shutdownmask;
+ if (shutdown_reason != SHUTDOWN_suspend) {
+ LOG(DEBUG, "guest %"PRId32" we were suspending has shut down"
+ " with unexpected reason code %d", domid, shutdown_reason);
+ goto err;
+ }
+
+ LOG(DEBUG, "guest has suspended");
+ domain_suspend_common_guest_suspended(egc, dss);
+ return;
+
+ err:
+ domain_suspend_common_failed(egc, dss);
+}
+
+static void suspend_common_wait_guest_timeout(libxl__egc *egc,
+ libxl__ev_time *ev, const struct timeval *requested_abs)
+{
+ libxl__domain_suspend_state *dss = CONTAINER_OF(ev, *dss, guest_timeout);
+ STATE_AO_GC(dss->ao);
+ LOG(ERROR, "guest did not suspend, timed out");
+ domain_suspend_common_failed(egc, dss);
+}
+
+static void domain_suspend_common_guest_suspended(libxl__egc *egc,
+ libxl__domain_suspend_state *dss)
+{
+ STATE_AO_GC(dss->ao);
+ int ret;
+
+ libxl__ev_evtchn_cancel(gc, &dss->guest_evtchn);
+ libxl__ev_xswatch_deregister(gc, &dss->guest_watch);
+ libxl__ev_time_deregister(gc, &dss->guest_timeout);
+
+ if (dss->hvm) {
+ ret = libxl__domain_suspend_device_model(gc, dss);
+ if (ret) {
+ LOG(ERROR, "libxl__domain_suspend_device_model failed ret=%d", ret);
+ domain_suspend_common_failed(egc, dss);
+ return;
+ }
+ }
+ domain_suspend_common_done(egc, dss, 1);
+}
+
+static void domain_suspend_common_failed(libxl__egc *egc,
+ libxl__domain_suspend_state *dss)
+{
+ domain_suspend_common_done(egc, dss, 0);
+}
+
+static void domain_suspend_common_done(libxl__egc *egc,
+ libxl__domain_suspend_state *dss,
+ bool ok)
+{
+ EGC_GC;
+ assert(!libxl__xswait_inuse(&dss->pvcontrol));
+ libxl__ev_evtchn_cancel(gc, &dss->guest_evtchn);
+ libxl__ev_xswatch_deregister(gc, &dss->guest_watch);
+ libxl__ev_time_deregister(gc, &dss->guest_timeout);
+ dss->callback_common_done(egc, dss, ok);
+}
+
+void libxl__domain_suspend_callback(void *data)
+{
+ libxl__save_helper_state *shs = data;
+ libxl__egc *egc = shs->egc;
+ libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
+ libxl__domain_suspend_state *dss2 = &dss->dss;
+
+ dss2->callback_common_done = domain_suspend_callback_common_done;
+ domain_suspend_callback_common(egc, dss2);
+}
+
+static void domain_suspend_callback_common_done(libxl__egc *egc,
+ libxl__domain_suspend_state *dss, int ok)
+{
+ libxl__domain_save_state *dsvs = CONTAINER_OF(dss, *dsvs, dss);
+ libxl__xc_domain_saverestore_async_callback_done(egc, &dsvs->shs, ok);
+}
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index f86fc89..b2eeb89 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -3191,6 +3191,12 @@ _hidden void libxl__domain_save_device_model(libxl__egc *egc,
_hidden const char *libxl__device_model_savefile(libxl__gc *gc, uint32_t domid);
+void libxl__domain_suspend_callback(void *data);
+
+/* calls dss->callback_common_done when done */
+void libxl__domain_suspend(libxl__egc *egc,
+ libxl__domain_suspend_state *dss);
+
/*
* Convenience macros.
--
1.9.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH v1 2/5] tools/libxl: move domain suspend codes into a separate file
2015-05-20 10:01 ` [PATCH v1 2/5] tools/libxl: move domain suspend codes into a separate file Yang Hongyang
@ 2015-06-02 14:44 ` Ian Campbell
2015-06-02 14:45 ` Ian Campbell
1 sibling, 0 replies; 23+ messages in thread
From: Ian Campbell @ 2015-06-02 14:44 UTC (permalink / raw)
To: Yang Hongyang
Cc: wei.liu2, wency, andrew.cooper3, yunhong.jiang, ian.jackson,
xen-devel, rshriram
On Wed, 2015-05-20 at 18:01 +0800, Yang Hongyang wrote:
> move domain suspend codes into a separate file libxl_dom_suspend.c
Just "code".
> Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
Acked-by: Ian Campbell <Ian.Campbell@citrix.com>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v1 2/5] tools/libxl: move domain suspend codes into a separate file
2015-05-20 10:01 ` [PATCH v1 2/5] tools/libxl: move domain suspend codes into a separate file Yang Hongyang
2015-06-02 14:44 ` Ian Campbell
@ 2015-06-02 14:45 ` Ian Campbell
2015-06-02 16:10 ` Yang Hongyang
1 sibling, 1 reply; 23+ messages in thread
From: Ian Campbell @ 2015-06-02 14:45 UTC (permalink / raw)
To: Yang Hongyang
Cc: wei.liu2, wency, andrew.cooper3, yunhong.jiang, ian.jackson,
xen-devel, rshriram
On Wed, 2015-05-20 at 18:01 +0800, Yang Hongyang wrote:
> diff --git a/tools/libxl/libxl_internal.h
> b/tools/libxl/libxl_internal.h
> index f86fc89..b2eeb89 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -3191,6 +3191,12 @@ _hidden void
> libxl__domain_save_device_model(libxl__egc *egc,
>
> _hidden const char *libxl__device_model_savefile(libxl__gc *gc,
> uint32_t domid);
>
> +void libxl__domain_suspend_callback(void *data);
> +
> +/* calls dss->callback_common_done when done */
> +void libxl__domain_suspend(libxl__egc *egc,
> + libxl__domain_suspend_state *dss);
Please mark these internal functions _hidden like the other examples in
this file.
With that the ack I just sent before I notice this stands.
Ian.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v1 2/5] tools/libxl: move domain suspend codes into a separate file
2015-06-02 14:45 ` Ian Campbell
@ 2015-06-02 16:10 ` Yang Hongyang
0 siblings, 0 replies; 23+ messages in thread
From: Yang Hongyang @ 2015-06-02 16:10 UTC (permalink / raw)
To: Ian Campbell
Cc: wei.liu2, wency, andrew.cooper3, yunhong.jiang, ian.jackson,
xen-devel, rshriram
On 06/02/2015 10:45 PM, Ian Campbell wrote:
> On Wed, 2015-05-20 at 18:01 +0800, Yang Hongyang wrote:
>> diff --git a/tools/libxl/libxl_internal.h
>> b/tools/libxl/libxl_internal.h
>> index f86fc89..b2eeb89 100644
>> --- a/tools/libxl/libxl_internal.h
>> +++ b/tools/libxl/libxl_internal.h
>> @@ -3191,6 +3191,12 @@ _hidden void
>> libxl__domain_save_device_model(libxl__egc *egc,
>>
>> _hidden const char *libxl__device_model_savefile(libxl__gc *gc,
>> uint32_t domid);
>>
>> +void libxl__domain_suspend_callback(void *data);
>> +
>> +/* calls dss->callback_common_done when done */
>> +void libxl__domain_suspend(libxl__egc *egc,
>> + libxl__domain_suspend_state *dss);
>
> Please mark these internal functions _hidden like the other examples in
> this file.
ok.
>
> With that the ack I just sent before I notice this stands.
>
> Ian.
>
>
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v1 3/5] tools/libxl: move remus codes into libxl_remus.c
2015-05-20 10:01 [PATCH v1 0/5] Misc cleanups for libxl Yang Hongyang
2015-05-20 10:01 ` [PATCH v1 1/5] libxl/save: Refactor libxl__domain_suspend_state Yang Hongyang
2015-05-20 10:01 ` [PATCH v1 2/5] tools/libxl: move domain suspend codes into a separate file Yang Hongyang
@ 2015-05-20 10:01 ` Yang Hongyang
2015-06-02 14:46 ` Ian Campbell
2015-05-20 10:01 ` [PATCH v1 4/5] tools/libxl: move toolstack code into libxl_toolstack.c Yang Hongyang
` (3 subsequent siblings)
6 siblings, 1 reply; 23+ messages in thread
From: Yang Hongyang @ 2015-05-20 10:01 UTC (permalink / raw)
To: xen-devel
Cc: wei.liu2, ian.campbell, wency, andrew.cooper3, yunhong.jiang,
ian.jackson, rshriram
move remus codes into libxl_remus.c
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
CC: Ian Campbell <Ian.Campbell@citrix.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Andrew Cooper <andrew.cooper3@citrix.com>
---
tools/libxl/Makefile | 2 +-
tools/libxl/libxl.c | 55 +-------
tools/libxl/libxl_dom.c | 223 ++-----------------------------
tools/libxl/libxl_internal.h | 11 ++
tools/libxl/libxl_remus.c | 306 +++++++++++++++++++++++++++++++++++++++++++
5 files changed, 327 insertions(+), 270 deletions(-)
create mode 100644 tools/libxl/libxl_remus.c
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index 21558b0..a9abdbc 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -56,7 +56,7 @@ else
LIBXL_OBJS-y += libxl_nonetbuffer.o
endif
-LIBXL_OBJS-y += libxl_remus_device.o libxl_remus_disk_drbd.o
+LIBXL_OBJS-y += libxl_remus.o libxl_remus_device.o libxl_remus_disk_drbd.o
LIBXL_OBJS-$(CONFIG_X86) += libxl_cpuid.o libxl_x86.o libxl_psr.o
LIBXL_OBJS-$(CONFIG_ARM) += libxl_nocpuid.o libxl_arm.o
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 7259061..43a4b88 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -825,10 +825,6 @@ out:
return ptr;
}
-static void libxl__remus_setup_done(libxl__egc *egc,
- libxl__remus_devices_state *rds, int rc);
-static void libxl__remus_setup_failed(libxl__egc *egc,
- libxl__remus_devices_state *rds, int rc);
static void remus_failover_cb(libxl__egc *egc,
libxl__domain_save_state *dss, int rc);
@@ -877,63 +873,14 @@ int libxl_domain_remus_start(libxl_ctx *ctx, libxl_domain_remus_info *info,
assert(info);
- /* Convenience aliases */
- libxl__remus_devices_state *const rds = &dss->rds;
-
- if (libxl_defbool_val(info->netbuf)) {
- if (!libxl__netbuffer_enabled(gc)) {
- LOG(ERROR, "Remus: No support for network buffering");
- rc = ERROR_FAIL;
- goto out;
- }
- rds->device_kind_flags |= (1 << LIBXL__DEVICE_KIND_VIF);
- }
-
- if (libxl_defbool_val(info->diskbuf))
- rds->device_kind_flags |= (1 << LIBXL__DEVICE_KIND_VBD);
-
- rds->ao = ao;
- rds->domid = domid;
- rds->callback = libxl__remus_setup_done;
-
/* Point of no return */
- libxl__remus_devices_setup(egc, rds);
+ libxl__remus_setup(egc, dss);
return AO_INPROGRESS;
out:
return AO_ABORT(rc);
}
-static void libxl__remus_setup_done(libxl__egc *egc,
- libxl__remus_devices_state *rds, int rc)
-{
- libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
- STATE_AO_GC(dss->ao);
-
- if (!rc) {
- libxl__domain_save(egc, dss);
- return;
- }
-
- LOG(ERROR, "Remus: failed to setup device for guest with domid %u, rc %d",
- dss->domid, rc);
- rds->callback = libxl__remus_setup_failed;
- libxl__remus_devices_teardown(egc, rds);
-}
-
-static void libxl__remus_setup_failed(libxl__egc *egc,
- libxl__remus_devices_state *rds, int rc)
-{
- libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
- STATE_AO_GC(dss->ao);
-
- if (rc)
- LOG(ERROR, "Remus: failed to teardown device after setup failed"
- " for guest with domid %u, rc %d", dss->domid, rc);
-
- dss->callback(egc, dss, rc);
-}
-
static void remus_failover_cb(libxl__egc *egc,
libxl__domain_save_state *dss, int rc)
{
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index 1681a12..b937d99 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -1405,192 +1405,6 @@ int libxl__toolstack_save(uint32_t domid, uint8_t **buf,
return 0;
}
-/*----- remus callbacks -----*/
-static void remus_domain_suspend_callback_common_done(libxl__egc *egc,
- libxl__domain_suspend_state *dss, int ok);
-static void remus_devices_postsuspend_cb(libxl__egc *egc,
- libxl__remus_devices_state *rds,
- int rc);
-static void remus_devices_preresume_cb(libxl__egc *egc,
- libxl__remus_devices_state *rds,
- int rc);
-
-static void libxl__remus_domain_suspend_callback(void *data)
-{
- libxl__save_helper_state *shs = data;
- libxl__egc *egc = shs->egc;
- libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
- libxl__domain_suspend_state *dss2 = &dss->dss;
-
- dss2->callback_common_done = remus_domain_suspend_callback_common_done;
- libxl__domain_suspend(egc, dss2);
-}
-
-static void remus_domain_suspend_callback_common_done(libxl__egc *egc,
- libxl__domain_suspend_state *dss, int ok)
-{
- libxl__domain_save_state *dsvs = CONTAINER_OF(dss, *dsvs, dss);
-
- if (!ok)
- goto out;
-
- libxl__remus_devices_state *const rds = &dsvs->rds;
- rds->callback = remus_devices_postsuspend_cb;
- libxl__remus_devices_postsuspend(egc, rds);
- return;
-
-out:
- libxl__xc_domain_saverestore_async_callback_done(egc, &dsvs->shs, ok);
-}
-
-static void remus_devices_postsuspend_cb(libxl__egc *egc,
- libxl__remus_devices_state *rds,
- int rc)
-{
- int ok = 0;
- libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
-
- if (rc)
- goto out;
-
- ok = 1;
-
-out:
- libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, ok);
-}
-
-static void libxl__remus_domain_resume_callback(void *data)
-{
- libxl__save_helper_state *shs = data;
- libxl__egc *egc = shs->egc;
- libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
- STATE_AO_GC(dss->ao);
-
- libxl__remus_devices_state *const rds = &dss->rds;
- rds->callback = remus_devices_preresume_cb;
- libxl__remus_devices_preresume(egc, rds);
-}
-
-static void remus_devices_preresume_cb(libxl__egc *egc,
- libxl__remus_devices_state *rds,
- int rc)
-{
- int ok = 0;
- libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
- STATE_AO_GC(dss->ao);
-
- if (rc)
- goto out;
-
- /* Resumes the domain and the device model */
- rc = libxl__domain_resume(gc, dss->domid, /* Fast Suspend */1);
- if (rc)
- goto out;
-
- ok = 1;
-
-out:
- libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, ok);
-}
-
-/*----- remus asynchronous checkpoint callback -----*/
-
-static void remus_checkpoint_dm_saved(libxl__egc *egc,
- libxl__domain_save_state *dss, int rc);
-static void remus_devices_commit_cb(libxl__egc *egc,
- libxl__remus_devices_state *rds,
- int rc);
-static void remus_next_checkpoint(libxl__egc *egc, libxl__ev_time *ev,
- const struct timeval *requested_abs);
-
-static void libxl__remus_domain_checkpoint_callback(void *data)
-{
- libxl__save_helper_state *shs = data;
- libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
- libxl__egc *egc = dss->shs.egc;
- STATE_AO_GC(dss->ao);
-
- /* This would go into tailbuf. */
- if (dss->hvm) {
- libxl__domain_save_device_model(egc, dss, remus_checkpoint_dm_saved);
- } else {
- remus_checkpoint_dm_saved(egc, dss, 0);
- }
-}
-
-static void remus_checkpoint_dm_saved(libxl__egc *egc,
- libxl__domain_save_state *dss, int rc)
-{
- /* Convenience aliases */
- libxl__remus_devices_state *const rds = &dss->rds;
-
- STATE_AO_GC(dss->ao);
-
- if (rc) {
- LOG(ERROR, "Failed to save device model. Terminating Remus..");
- goto out;
- }
-
- rds->callback = remus_devices_commit_cb;
- libxl__remus_devices_commit(egc, rds);
-
- return;
-
-out:
- libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, 0);
-}
-
-static void remus_devices_commit_cb(libxl__egc *egc,
- libxl__remus_devices_state *rds,
- int rc)
-{
- libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
-
- STATE_AO_GC(dss->ao);
-
- if (rc) {
- LOG(ERROR, "Failed to do device commit op."
- " Terminating Remus..");
- goto out;
- }
-
- /*
- * At this point, we have successfully checkpointed the guest and
- * committed it at the backup. We'll come back after the checkpoint
- * interval to checkpoint the guest again. Until then, let the guest
- * continue execution.
- */
-
- /* Set checkpoint interval timeout */
- rc = libxl__ev_time_register_rel(gc, &dss->checkpoint_timeout,
- remus_next_checkpoint,
- dss->interval);
-
- if (rc)
- goto out;
-
- return;
-
-out:
- libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, 0);
-}
-
-static void remus_next_checkpoint(libxl__egc *egc, libxl__ev_time *ev,
- const struct timeval *requested_abs)
-{
- libxl__domain_save_state *dss =
- CONTAINER_OF(ev, *dss, checkpoint_timeout);
-
- STATE_AO_GC(dss->ao);
-
- /*
- * Time to checkpoint the guest again. We return 1 to libxc
- * (xc_domain_save.c). in order to continue executing the infinite loop
- * (suspend, checkpoint, resume) in xc_domain_save().
- */
- libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, 1);
-}
-
/*----- main code for saving, in order of execution -----*/
static void domain_save_done(libxl__egc *egc,
@@ -1816,10 +1630,6 @@ static void save_device_model_datacopier_done(libxl__egc *egc,
dss->save_dm_callback(egc, dss, our_rc);
}
-static void remus_teardown_done(libxl__egc *egc,
- libxl__remus_devices_state *rds,
- int rc);
-
static void domain_save_done(libxl__egc *egc,
libxl__domain_save_state *dss, int rc)
{
@@ -1835,34 +1645,17 @@ static void domain_save_done(libxl__egc *egc,
xc_suspend_evtchn_release(CTX->xch, CTX->xce, domid,
dss2->guest_evtchn.port, &dss2->guest_evtchn_lockfd);
- if (!dss->remus) {
- dss->callback(egc, dss, rc);
+ if (dss->remus) {
+ /*
+ * With Remus, if we reach this point, it means either
+ * backup died or some network error occurred preventing us
+ * from sending checkpoints. Teardown the network buffers and
+ * release netlink resources. This is an async op.
+ */
+ libxl__remus_teardown(egc, dss, rc);
return;
}
- /*
- * With Remus, if we reach this point, it means either
- * backup died or some network error occurred preventing us
- * from sending checkpoints. Teardown the network buffers and
- * release netlink resources. This is an async op.
- */
- LOG(WARN, "Remus: Domain suspend terminated with rc %d,"
- " teardown Remus devices...", rc);
- dss->rds.callback = remus_teardown_done;
- libxl__remus_devices_teardown(egc, &dss->rds);
-}
-
-static void remus_teardown_done(libxl__egc *egc,
- libxl__remus_devices_state *rds,
- int rc)
-{
- libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
- STATE_AO_GC(dss->ao);
-
- if (rc)
- LOG(ERROR, "Remus: failed to teardown device for guest with domid %u,"
- " rc %d", dss->domid, rc);
-
dss->callback(egc, dss, rc);
}
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index b2eeb89..c3d70eb 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -2815,6 +2815,7 @@ _hidden void libxl__remus_devices_commit(libxl__egc *egc,
libxl__remus_devices_state *rds);
_hidden int libxl__netbuffer_enabled(libxl__gc *gc);
+
/*----- Domain suspend (save) state structure -----*/
typedef struct libxl__domain_suspend_state libxl__domain_suspend_state;
@@ -3197,6 +3198,16 @@ void libxl__domain_suspend_callback(void *data);
void libxl__domain_suspend(libxl__egc *egc,
libxl__domain_suspend_state *dss);
+/* Remus callbacks for save */
+void libxl__remus_domain_suspend_callback(void *data);
+void libxl__remus_domain_resume_callback(void *data);
+void libxl__remus_domain_checkpoint_callback(void *data);
+/* Remus setup and teardown*/
+void libxl__remus_setup(libxl__egc *egc, libxl__domain_save_state *dss);
+void libxl__remus_teardown(libxl__egc *egc,
+ libxl__domain_save_state *dss,
+ int rc);
+
/*
* Convenience macros.
diff --git a/tools/libxl/libxl_remus.c b/tools/libxl/libxl_remus.c
new file mode 100644
index 0000000..7eb21e7
--- /dev/null
+++ b/tools/libxl/libxl_remus.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright (C) 2015 FUJITSU LIMITED
+ * Author: Yang Hongyang <yanghy@cn.fujitsu.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2 and later. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h" /* must come before any other headers */
+
+#include "libxl_internal.h"
+
+/*----- Remus setup and teardown -----*/
+
+static void libxl_remus_setup_done(libxl__egc *egc,
+ libxl__remus_devices_state *rds, int rc);
+static void libxl_remus_setup_failed(libxl__egc *egc,
+ libxl__remus_devices_state *rds, int rc);
+void libxl__remus_setup(libxl__egc *egc, libxl__domain_save_state *dss)
+{
+ /* Convenience aliases */
+ libxl__remus_devices_state *const rds = &dss->rds;
+ const libxl_domain_remus_info *const info = dss->remus;
+
+ STATE_AO_GC(dss->ao);
+
+ if (libxl_defbool_val(info->netbuf)) {
+ if (!libxl__netbuffer_enabled(gc)) {
+ LOG(ERROR, "Remus: No support for network buffering");
+ goto out;
+ }
+ rds->device_kind_flags |= (1 << LIBXL__DEVICE_KIND_VIF);
+ }
+
+ if (libxl_defbool_val(info->diskbuf))
+ rds->device_kind_flags |= (1 << LIBXL__DEVICE_KIND_VBD);
+
+ rds->ao = ao;
+ rds->domid = dss->domid;
+ rds->callback = libxl_remus_setup_done;
+
+ libxl__remus_devices_setup(egc, rds);
+ return;
+
+out:
+ libxl_remus_setup_failed(egc, rds, ERROR_FAIL);
+}
+
+static void libxl_remus_setup_done(libxl__egc *egc,
+ libxl__remus_devices_state *rds, int rc)
+{
+ libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
+ STATE_AO_GC(dss->ao);
+
+ if (!rc) {
+ libxl__domain_save(egc, dss);
+ return;
+ }
+
+ LOG(ERROR, "Remus: failed to setup device for guest with domid %u, rc %d",
+ dss->domid, rc);
+ rds->callback = libxl_remus_setup_failed;
+ libxl__remus_devices_teardown(egc, rds);
+}
+
+static void libxl_remus_setup_failed(libxl__egc *egc,
+ libxl__remus_devices_state *rds, int rc)
+{
+ libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
+ STATE_AO_GC(dss->ao);
+
+ if (rc)
+ LOG(ERROR, "Remus: failed to teardown device after setup failed"
+ " for guest with domid %u, rc %d", dss->domid, rc);
+
+ dss->callback(egc, dss, rc);
+}
+
+static void remus_teardown_done(libxl__egc *egc,
+ libxl__remus_devices_state *rds,
+ int rc);
+void libxl__remus_teardown(libxl__egc *egc,
+ libxl__domain_save_state *dss,
+ int rc)
+{
+ EGC_GC;
+
+ LOG(WARN, "Remus: Domain suspend terminated with rc %d,"
+ " teardown Remus devices...", rc);
+ dss->rds.callback = remus_teardown_done;
+ libxl__remus_devices_teardown(egc, &dss->rds);
+}
+
+static void remus_teardown_done(libxl__egc *egc,
+ libxl__remus_devices_state *rds,
+ int rc)
+{
+ libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
+ STATE_AO_GC(dss->ao);
+
+ if (rc)
+ LOG(ERROR, "Remus: failed to teardown device for guest with domid %u,"
+ " rc %d", dss->domid, rc);
+
+ dss->callback(egc, dss, rc);
+}
+
+/*----- remus callbacks -----*/
+static void remus_domain_suspend_callback_common_done(libxl__egc *egc,
+ libxl__domain_suspend_state *dss, int ok);
+static void remus_devices_postsuspend_cb(libxl__egc *egc,
+ libxl__remus_devices_state *rds,
+ int rc);
+static void remus_devices_preresume_cb(libxl__egc *egc,
+ libxl__remus_devices_state *rds,
+ int rc);
+
+void libxl__remus_domain_suspend_callback(void *data)
+{
+ libxl__save_helper_state *shs = data;
+ libxl__egc *egc = shs->egc;
+ libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
+ libxl__domain_suspend_state *dss2 = &dss->dss;
+
+ dss2->callback_common_done = remus_domain_suspend_callback_common_done;
+ libxl__domain_suspend(egc, dss2);
+}
+
+static void remus_domain_suspend_callback_common_done(libxl__egc *egc,
+ libxl__domain_suspend_state *dss, int ok)
+{
+ libxl__domain_save_state *dsvs = CONTAINER_OF(dss, *dsvs, dss);
+
+ if (!ok)
+ goto out;
+
+ libxl__remus_devices_state *const rds = &dsvs->rds;
+ rds->callback = remus_devices_postsuspend_cb;
+ libxl__remus_devices_postsuspend(egc, rds);
+ return;
+
+out:
+ libxl__xc_domain_saverestore_async_callback_done(egc, &dsvs->shs, ok);
+}
+
+static void remus_devices_postsuspend_cb(libxl__egc *egc,
+ libxl__remus_devices_state *rds,
+ int rc)
+{
+ int ok = 0;
+ libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
+
+ if (rc)
+ goto out;
+
+ ok = 1;
+
+out:
+ libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, ok);
+}
+
+void libxl__remus_domain_resume_callback(void *data)
+{
+ libxl__save_helper_state *shs = data;
+ libxl__egc *egc = shs->egc;
+ libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
+ STATE_AO_GC(dss->ao);
+
+ libxl__remus_devices_state *const rds = &dss->rds;
+ rds->callback = remus_devices_preresume_cb;
+ libxl__remus_devices_preresume(egc, rds);
+}
+
+static void remus_devices_preresume_cb(libxl__egc *egc,
+ libxl__remus_devices_state *rds,
+ int rc)
+{
+ int ok = 0;
+ libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
+ STATE_AO_GC(dss->ao);
+
+ if (rc)
+ goto out;
+
+ /* Resumes the domain and the device model */
+ rc = libxl__domain_resume(gc, dss->domid, /* Fast Suspend */1);
+ if (rc)
+ goto out;
+
+ ok = 1;
+
+out:
+ libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, ok);
+}
+
+/*----- remus asynchronous checkpoint callback -----*/
+
+static void remus_checkpoint_dm_saved(libxl__egc *egc,
+ libxl__domain_save_state *dss, int rc);
+static void remus_devices_commit_cb(libxl__egc *egc,
+ libxl__remus_devices_state *rds,
+ int rc);
+static void remus_next_checkpoint(libxl__egc *egc, libxl__ev_time *ev,
+ const struct timeval *requested_abs);
+
+void libxl__remus_domain_checkpoint_callback(void *data)
+{
+ libxl__save_helper_state *shs = data;
+ libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
+ libxl__egc *egc = dss->shs.egc;
+ STATE_AO_GC(dss->ao);
+
+ /* This would go into tailbuf. */
+ if (dss->hvm) {
+ libxl__domain_save_device_model(egc, dss, remus_checkpoint_dm_saved);
+ } else {
+ remus_checkpoint_dm_saved(egc, dss, 0);
+ }
+}
+
+static void remus_checkpoint_dm_saved(libxl__egc *egc,
+ libxl__domain_save_state *dss, int rc)
+{
+ /* Convenience aliases */
+ libxl__remus_devices_state *const rds = &dss->rds;
+
+ STATE_AO_GC(dss->ao);
+
+ if (rc) {
+ LOG(ERROR, "Failed to save device model. Terminating Remus..");
+ goto out;
+ }
+
+ rds->callback = remus_devices_commit_cb;
+ libxl__remus_devices_commit(egc, rds);
+
+ return;
+
+out:
+ libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, 0);
+}
+
+static void remus_devices_commit_cb(libxl__egc *egc,
+ libxl__remus_devices_state *rds,
+ int rc)
+{
+ libxl__domain_save_state *dss = CONTAINER_OF(rds, *dss, rds);
+
+ STATE_AO_GC(dss->ao);
+
+ if (rc) {
+ LOG(ERROR, "Failed to do device commit op."
+ " Terminating Remus..");
+ goto out;
+ }
+
+ /*
+ * At this point, we have successfully checkpointed the guest and
+ * committed it at the backup. We'll come back after the checkpoint
+ * interval to checkpoint the guest again. Until then, let the guest
+ * continue execution.
+ */
+
+ /* Set checkpoint interval timeout */
+ rc = libxl__ev_time_register_rel(gc, &dss->checkpoint_timeout,
+ remus_next_checkpoint,
+ dss->interval);
+
+ if (rc)
+ goto out;
+
+ return;
+
+out:
+ libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, 0);
+}
+
+static void remus_next_checkpoint(libxl__egc *egc, libxl__ev_time *ev,
+ const struct timeval *requested_abs)
+{
+ libxl__domain_save_state *dss =
+ CONTAINER_OF(ev, *dss, checkpoint_timeout);
+
+ STATE_AO_GC(dss->ao);
+
+ /*
+ * Time to checkpoint the guest again. We return 1 to libxc
+ * (xc_domain_save.c). in order to continue executing the infinite loop
+ * (suspend, checkpoint, resume) in xc_domain_save().
+ */
+ libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, 1);
+}
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
1.9.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH v1 3/5] tools/libxl: move remus codes into libxl_remus.c
2015-05-20 10:01 ` [PATCH v1 3/5] tools/libxl: move remus codes into libxl_remus.c Yang Hongyang
@ 2015-06-02 14:46 ` Ian Campbell
2015-06-02 16:13 ` Yang Hongyang
0 siblings, 1 reply; 23+ messages in thread
From: Ian Campbell @ 2015-06-02 14:46 UTC (permalink / raw)
To: Yang Hongyang
Cc: wei.liu2, wency, andrew.cooper3, yunhong.jiang, ian.jackson,
xen-devel, rshriram
On Wed, 2015-05-20 at 18:01 +0800, Yang Hongyang wrote:
> move remus codes into libxl_remus.c
"code"
Apart from dropping some "static" and adding some prototypes to the
header this is purely motion, correct? (I assume this about the last one
too).
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index b2eeb89..c3d70eb 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -2815,6 +2815,7 @@ _hidden void libxl__remus_devices_commit(libxl__egc *egc,
> libxl__remus_devices_state *rds);
> _hidden int libxl__netbuffer_enabled(libxl__gc *gc);
>
> +
Please avoid spurious whitespace changes.
> /*----- Domain suspend (save) state structure -----*/
>
> typedef struct libxl__domain_suspend_state libxl__domain_suspend_state;
> @@ -3197,6 +3198,16 @@ void libxl__domain_suspend_callback(void *data);
> void libxl__domain_suspend(libxl__egc *egc,
> libxl__domain_suspend_state *dss);
>
> +/* Remus callbacks for save */
> +void libxl__remus_domain_suspend_callback(void *data);
> +void libxl__remus_domain_resume_callback(void *data);
> +void libxl__remus_domain_checkpoint_callback(void *data);
> +/* Remus setup and teardown*/
> +void libxl__remus_setup(libxl__egc *egc, libxl__domain_save_state *dss);
> +void libxl__remus_teardown(libxl__egc *egc,
> + libxl__domain_save_state *dss,
> + int rc);
Please mark these all _hidden.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v1 3/5] tools/libxl: move remus codes into libxl_remus.c
2015-06-02 14:46 ` Ian Campbell
@ 2015-06-02 16:13 ` Yang Hongyang
0 siblings, 0 replies; 23+ messages in thread
From: Yang Hongyang @ 2015-06-02 16:13 UTC (permalink / raw)
To: Ian Campbell
Cc: wei.liu2, wency, andrew.cooper3, yunhong.jiang, ian.jackson,
xen-devel, rshriram
On 06/02/2015 10:46 PM, Ian Campbell wrote:
> On Wed, 2015-05-20 at 18:01 +0800, Yang Hongyang wrote:
>> move remus codes into libxl_remus.c
>
> "code"
>
> Apart from dropping some "static" and adding some prototypes to the
> header this is purely motion, correct? (I assume this about the last one
> too).
and add remus setup and teardown func. that's all.
>> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
>> index b2eeb89..c3d70eb 100644
>> --- a/tools/libxl/libxl_internal.h
>> +++ b/tools/libxl/libxl_internal.h
>> @@ -2815,6 +2815,7 @@ _hidden void libxl__remus_devices_commit(libxl__egc *egc,
>> libxl__remus_devices_state *rds);
>> _hidden int libxl__netbuffer_enabled(libxl__gc *gc);
>>
>> +
>
> Please avoid spurious whitespace changes.
fixed.
>
>> /*----- Domain suspend (save) state structure -----*/
>>
>> typedef struct libxl__domain_suspend_state libxl__domain_suspend_state;
>> @@ -3197,6 +3198,16 @@ void libxl__domain_suspend_callback(void *data);
>> void libxl__domain_suspend(libxl__egc *egc,
>> libxl__domain_suspend_state *dss);
>>
>> +/* Remus callbacks for save */
>> +void libxl__remus_domain_suspend_callback(void *data);
>> +void libxl__remus_domain_resume_callback(void *data);
>> +void libxl__remus_domain_checkpoint_callback(void *data);
>> +/* Remus setup and teardown*/
>> +void libxl__remus_setup(libxl__egc *egc, libxl__domain_save_state *dss);
>> +void libxl__remus_teardown(libxl__egc *egc,
>> + libxl__domain_save_state *dss,
>> + int rc);
>
> Please mark these all _hidden.
ok.
>
>
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v1 4/5] tools/libxl: move toolstack code into libxl_toolstack.c
2015-05-20 10:01 [PATCH v1 0/5] Misc cleanups for libxl Yang Hongyang
` (2 preceding siblings ...)
2015-05-20 10:01 ` [PATCH v1 3/5] tools/libxl: move remus codes into libxl_remus.c Yang Hongyang
@ 2015-05-20 10:01 ` Yang Hongyang
2015-06-02 14:48 ` Ian Campbell
2015-05-20 10:01 ` [PATCH v1 5/5] tools/libxl: move domain save codes into libxl_dom_save.c Yang Hongyang
` (2 subsequent siblings)
6 siblings, 1 reply; 23+ messages in thread
From: Yang Hongyang @ 2015-05-20 10:01 UTC (permalink / raw)
To: xen-devel
Cc: wei.liu2, ian.campbell, wency, andrew.cooper3, yunhong.jiang,
ian.jackson, rshriram
move toolstack code into libxl_toolstack.c
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
CC: Ian Campbell <Ian.Campbell@citrix.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Andrew Cooper <andrew.cooper3@citrix.com>
---
tools/libxl/Makefile | 2 +-
tools/libxl/libxl_dom.c | 171 ------------------------------------
tools/libxl/libxl_toolstack.c | 196 ++++++++++++++++++++++++++++++++++++++++++
3 files changed, 197 insertions(+), 172 deletions(-)
create mode 100644 tools/libxl/libxl_toolstack.c
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index a9abdbc..48f2cbb 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -96,7 +96,7 @@ LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \
libxl_json.o libxl_aoutils.o libxl_numa.o libxl_vnuma.o \
libxl_save_callout.o _libxl_save_msgs_callout.o \
libxl_qmp.o libxl_event.o libxl_fork.o libxl_dom_suspend.o \
- $(LIBXL_OBJS-y)
+ libxl_toolstack.o $(LIBXL_OBJS-y)
LIBXL_OBJS += libxl_genid.o
LIBXL_OBJS += _libxl_types.o libxl_flask.o _libxl_types_internal.o
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index b937d99..1caf21c 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -1020,87 +1020,6 @@ int libxl__qemu_traditional_cmd(libxl__gc *gc, uint32_t domid,
return libxl__xs_write(gc, XBT_NULL, path, "%s", cmd);
}
-struct libxl__physmap_info {
- uint64_t phys_offset;
- uint64_t start_addr;
- uint64_t size;
- uint32_t namelen;
- char name[];
-};
-
-#define TOOLSTACK_SAVE_VERSION 1
-
-static inline char *restore_helper(libxl__gc *gc, uint32_t dm_domid,
- uint32_t domid,
- uint64_t phys_offset, char *node)
-{
- return libxl__device_model_xs_path(gc, dm_domid, domid,
- "/physmap/%"PRIx64"/%s",
- phys_offset, node);
-}
-
-int libxl__toolstack_restore(uint32_t domid, const uint8_t *buf,
- uint32_t size, void *user)
-{
- libxl__save_helper_state *shs = user;
- libxl__domain_create_state *dcs = CONTAINER_OF(shs, *dcs, shs);
- STATE_AO_GC(dcs->ao);
- int i, ret;
- const uint8_t *ptr = buf;
- uint32_t count = 0, version = 0;
- struct libxl__physmap_info* pi;
- char *xs_path;
- uint32_t dm_domid;
-
- LOG(DEBUG,"domain=%"PRIu32" toolstack data size=%"PRIu32, domid, size);
-
- if (size < sizeof(version) + sizeof(count)) {
- LOG(ERROR, "wrong size");
- return -1;
- }
-
- memcpy(&version, ptr, sizeof(version));
- ptr += sizeof(version);
-
- if (version != TOOLSTACK_SAVE_VERSION) {
- LOG(ERROR, "wrong version");
- return -1;
- }
-
- memcpy(&count, ptr, sizeof(count));
- ptr += sizeof(count);
-
- if (size < sizeof(version) + sizeof(count) +
- count * (sizeof(struct libxl__physmap_info))) {
- LOG(ERROR, "wrong size");
- return -1;
- }
-
- dm_domid = libxl_get_stubdom_id(CTX, domid);
- for (i = 0; i < count; i++) {
- pi = (struct libxl__physmap_info*) ptr;
- ptr += sizeof(struct libxl__physmap_info) + pi->namelen;
-
- xs_path = restore_helper(gc, dm_domid, domid,
- pi->phys_offset, "start_addr");
- ret = libxl__xs_write(gc, 0, xs_path, "%"PRIx64, pi->start_addr);
- if (ret)
- return -1;
- xs_path = restore_helper(gc, dm_domid, domid, pi->phys_offset, "size");
- ret = libxl__xs_write(gc, 0, xs_path, "%"PRIx64, pi->size);
- if (ret)
- return -1;
- if (pi->namelen > 0) {
- xs_path = restore_helper(gc, dm_domid, domid,
- pi->phys_offset, "name");
- ret = libxl__xs_write(gc, 0, xs_path, "%s", pi->name);
- if (ret)
- return -1;
- }
- }
- return 0;
-}
-
/*----- complicated callback, called by xc_domain_save -----*/
/*
@@ -1315,96 +1234,6 @@ static void switch_logdirty_done(libxl__egc *egc,
libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, broke);
}
-static inline char *physmap_path(libxl__gc *gc, uint32_t dm_domid,
- uint32_t domid,
- char *phys_offset, char *node)
-{
- return libxl__device_model_xs_path(gc, dm_domid, domid,
- "/physmap/%s/%s",
- phys_offset, node);
-}
-
-int libxl__toolstack_save(uint32_t domid, uint8_t **buf,
- uint32_t *len, void *dss_void)
-{
- libxl__domain_suspend_state *dss = dss_void;
- STATE_AO_GC(dss->ao);
- int i = 0;
- char *start_addr = NULL, *size = NULL, *phys_offset = NULL, *name = NULL;
- unsigned int num = 0;
- uint32_t count = 0, version = TOOLSTACK_SAVE_VERSION, namelen = 0;
- uint8_t *ptr = NULL;
- char **entries = NULL;
- struct libxl__physmap_info *pi;
- uint32_t dm_domid;
-
- dm_domid = libxl_get_stubdom_id(CTX, domid);
-
- entries = libxl__xs_directory(gc, 0,
- libxl__device_model_xs_path(gc, dm_domid, domid, "/physmap"),
- &num);
- count = num;
-
- *len = sizeof(version) + sizeof(count);
- *buf = calloc(1, *len);
- ptr = *buf;
- if (*buf == NULL)
- return -1;
-
- memcpy(ptr, &version, sizeof(version));
- ptr += sizeof(version);
- memcpy(ptr, &count, sizeof(count));
- ptr += sizeof(count);
-
- for (i = 0; i < count; i++) {
- unsigned long offset;
- char *xs_path;
- phys_offset = entries[i];
- if (phys_offset == NULL) {
- LOG(ERROR, "phys_offset %d is NULL", i);
- return -1;
- }
-
- xs_path = physmap_path(gc, dm_domid, domid, phys_offset, "start_addr");
- start_addr = libxl__xs_read(gc, 0, xs_path);
- if (start_addr == NULL) {
- LOG(ERROR, "%s is NULL", xs_path);
- return -1;
- }
-
- xs_path = physmap_path(gc, dm_domid, domid, phys_offset, "size");
- size = libxl__xs_read(gc, 0, xs_path);
- if (size == NULL) {
- LOG(ERROR, "%s is NULL", xs_path);
- return -1;
- }
-
- xs_path = physmap_path(gc, dm_domid, domid, phys_offset, "name");
- name = libxl__xs_read(gc, 0, xs_path);
- if (name == NULL)
- namelen = 0;
- else
- namelen = strlen(name) + 1;
- *len += namelen + sizeof(struct libxl__physmap_info);
- offset = ptr - (*buf);
- *buf = realloc(*buf, *len);
- if (*buf == NULL)
- return -1;
- ptr = (*buf) + offset;
- pi = (struct libxl__physmap_info *) ptr;
- pi->phys_offset = strtoll(phys_offset, NULL, 16);
- pi->start_addr = strtoll(start_addr, NULL, 16);
- pi->size = strtoll(size, NULL, 16);
- pi->namelen = namelen;
- memcpy(pi->name, name, namelen);
- ptr += sizeof(struct libxl__physmap_info) + namelen;
- }
-
- LOG(DEBUG,"domain=%"PRIu32" toolstack data size=%"PRIu32, domid, *len);
-
- return 0;
-}
-
/*----- main code for saving, in order of execution -----*/
static void domain_save_done(libxl__egc *egc,
diff --git a/tools/libxl/libxl_toolstack.c b/tools/libxl/libxl_toolstack.c
new file mode 100644
index 0000000..923705c
--- /dev/null
+++ b/tools/libxl/libxl_toolstack.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2009 Citrix Ltd.
+ * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h" /* must come before any other headers */
+
+#include "libxl_internal.h"
+
+struct libxl__physmap_info {
+ uint64_t phys_offset;
+ uint64_t start_addr;
+ uint64_t size;
+ uint32_t namelen;
+ char name[];
+};
+
+#define TOOLSTACK_SAVE_VERSION 1
+
+static inline char *restore_helper(libxl__gc *gc, uint32_t dm_domid,
+ uint32_t domid,
+ uint64_t phys_offset, char *node)
+{
+ return libxl__device_model_xs_path(gc, dm_domid, domid,
+ "/physmap/%"PRIx64"/%s",
+ phys_offset, node);
+}
+
+int libxl__toolstack_restore(uint32_t domid, const uint8_t *buf,
+ uint32_t size, void *user)
+{
+ libxl__save_helper_state *shs = user;
+ libxl__domain_create_state *dcs = CONTAINER_OF(shs, *dcs, shs);
+ STATE_AO_GC(dcs->ao);
+ int i, ret;
+ const uint8_t *ptr = buf;
+ uint32_t count = 0, version = 0;
+ struct libxl__physmap_info* pi;
+ char *xs_path;
+ uint32_t dm_domid;
+
+ LOG(DEBUG,"domain=%"PRIu32" toolstack data size=%"PRIu32, domid, size);
+
+ if (size < sizeof(version) + sizeof(count)) {
+ LOG(ERROR, "wrong size");
+ return -1;
+ }
+
+ memcpy(&version, ptr, sizeof(version));
+ ptr += sizeof(version);
+
+ if (version != TOOLSTACK_SAVE_VERSION) {
+ LOG(ERROR, "wrong version");
+ return -1;
+ }
+
+ memcpy(&count, ptr, sizeof(count));
+ ptr += sizeof(count);
+
+ if (size < sizeof(version) + sizeof(count) +
+ count * (sizeof(struct libxl__physmap_info))) {
+ LOG(ERROR, "wrong size");
+ return -1;
+ }
+
+ dm_domid = libxl_get_stubdom_id(CTX, domid);
+ for (i = 0; i < count; i++) {
+ pi = (struct libxl__physmap_info*) ptr;
+ ptr += sizeof(struct libxl__physmap_info) + pi->namelen;
+
+ xs_path = restore_helper(gc, dm_domid, domid,
+ pi->phys_offset, "start_addr");
+ ret = libxl__xs_write(gc, 0, xs_path, "%"PRIx64, pi->start_addr);
+ if (ret)
+ return -1;
+ xs_path = restore_helper(gc, dm_domid, domid, pi->phys_offset, "size");
+ ret = libxl__xs_write(gc, 0, xs_path, "%"PRIx64, pi->size);
+ if (ret)
+ return -1;
+ if (pi->namelen > 0) {
+ xs_path = restore_helper(gc, dm_domid, domid,
+ pi->phys_offset, "name");
+ ret = libxl__xs_write(gc, 0, xs_path, "%s", pi->name);
+ if (ret)
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static inline char *physmap_path(libxl__gc *gc, uint32_t dm_domid,
+ uint32_t domid,
+ char *phys_offset, char *node)
+{
+ return libxl__device_model_xs_path(gc, dm_domid, domid,
+ "/physmap/%s/%s",
+ phys_offset, node);
+}
+
+int libxl__toolstack_save(uint32_t domid, uint8_t **buf,
+ uint32_t *len, void *dss_void)
+{
+ libxl__domain_suspend_state *dss = dss_void;
+ STATE_AO_GC(dss->ao);
+ int i = 0;
+ char *start_addr = NULL, *size = NULL, *phys_offset = NULL, *name = NULL;
+ unsigned int num = 0;
+ uint32_t count = 0, version = TOOLSTACK_SAVE_VERSION, namelen = 0;
+ uint8_t *ptr = NULL;
+ char **entries = NULL;
+ struct libxl__physmap_info *pi;
+ uint32_t dm_domid;
+
+ dm_domid = libxl_get_stubdom_id(CTX, domid);
+
+ entries = libxl__xs_directory(gc, 0,
+ libxl__device_model_xs_path(gc, dm_domid, domid, "/physmap"),
+ &num);
+ count = num;
+
+ *len = sizeof(version) + sizeof(count);
+ *buf = calloc(1, *len);
+ ptr = *buf;
+ if (*buf == NULL)
+ return -1;
+
+ memcpy(ptr, &version, sizeof(version));
+ ptr += sizeof(version);
+ memcpy(ptr, &count, sizeof(count));
+ ptr += sizeof(count);
+
+ for (i = 0; i < count; i++) {
+ unsigned long offset;
+ char *xs_path;
+ phys_offset = entries[i];
+ if (phys_offset == NULL) {
+ LOG(ERROR, "phys_offset %d is NULL", i);
+ return -1;
+ }
+
+ xs_path = physmap_path(gc, dm_domid, domid, phys_offset, "start_addr");
+ start_addr = libxl__xs_read(gc, 0, xs_path);
+ if (start_addr == NULL) {
+ LOG(ERROR, "%s is NULL", xs_path);
+ return -1;
+ }
+
+ xs_path = physmap_path(gc, dm_domid, domid, phys_offset, "size");
+ size = libxl__xs_read(gc, 0, xs_path);
+ if (size == NULL) {
+ LOG(ERROR, "%s is NULL", xs_path);
+ return -1;
+ }
+
+ xs_path = physmap_path(gc, dm_domid, domid, phys_offset, "name");
+ name = libxl__xs_read(gc, 0, xs_path);
+ if (name == NULL)
+ namelen = 0;
+ else
+ namelen = strlen(name) + 1;
+ *len += namelen + sizeof(struct libxl__physmap_info);
+ offset = ptr - (*buf);
+ *buf = realloc(*buf, *len);
+ if (*buf == NULL)
+ return -1;
+ ptr = (*buf) + offset;
+ pi = (struct libxl__physmap_info *) ptr;
+ pi->phys_offset = strtoll(phys_offset, NULL, 16);
+ pi->start_addr = strtoll(start_addr, NULL, 16);
+ pi->size = strtoll(size, NULL, 16);
+ pi->namelen = namelen;
+ memcpy(pi->name, name, namelen);
+ ptr += sizeof(struct libxl__physmap_info) + namelen;
+ }
+
+ LOG(DEBUG,"domain=%"PRIu32" toolstack data size=%"PRIu32, domid, *len);
+
+ return 0;
+}
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
1.9.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH v1 4/5] tools/libxl: move toolstack code into libxl_toolstack.c
2015-05-20 10:01 ` [PATCH v1 4/5] tools/libxl: move toolstack code into libxl_toolstack.c Yang Hongyang
@ 2015-06-02 14:48 ` Ian Campbell
2015-06-02 16:22 ` Yang Hongyang
0 siblings, 1 reply; 23+ messages in thread
From: Ian Campbell @ 2015-06-02 14:48 UTC (permalink / raw)
To: Yang Hongyang
Cc: wei.liu2, wency, andrew.cooper3, yunhong.jiang, ian.jackson,
xen-devel, rshriram
On Wed, 2015-05-20 at 18:01 +0800, Yang Hongyang wrote:
> move toolstack code into libxl_toolstack.c
It's not clear to me what "toolstack code" is here, the whole of libxl
and xl is "toolstack code".
Is the code being moved stuff to do with adding toolstack state to the
save stream? Perhaps libxl_{suspend,save}_toolstack.c? Or could this not
go in the libxl_dom_suspend.c you just created?
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v1 4/5] tools/libxl: move toolstack code into libxl_toolstack.c
2015-06-02 14:48 ` Ian Campbell
@ 2015-06-02 16:22 ` Yang Hongyang
2015-06-03 2:52 ` Yang Hongyang
0 siblings, 1 reply; 23+ messages in thread
From: Yang Hongyang @ 2015-06-02 16:22 UTC (permalink / raw)
To: Ian Campbell
Cc: wei.liu2, wency, andrew.cooper3, yunhong.jiang, ian.jackson,
xen-devel, rshriram
On 06/02/2015 10:48 PM, Ian Campbell wrote:
> On Wed, 2015-05-20 at 18:01 +0800, Yang Hongyang wrote:
>> move toolstack code into libxl_toolstack.c
>
> It's not clear to me what "toolstack code" is here, the whole of libxl
> and xl is "toolstack code".
>
> Is the code being moved stuff to do with adding toolstack state to the
> save stream? Perhaps libxl_{suspend,save}_toolstack.c? Or could this not
> go in the libxl_dom_suspend.c you just created?
My thought was libxl_dom_suspend.c only contains code that do vm suspend
stuff(not save). So compare to move it to dom_suspend.c, I prefer not
move it or use libxl_{suspend,save}_toolstack.c. Maybe leave the code
not moved?
>
>
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v1 4/5] tools/libxl: move toolstack code into libxl_toolstack.c
2015-06-02 16:22 ` Yang Hongyang
@ 2015-06-03 2:52 ` Yang Hongyang
2015-06-03 9:24 ` Ian Campbell
0 siblings, 1 reply; 23+ messages in thread
From: Yang Hongyang @ 2015-06-03 2:52 UTC (permalink / raw)
To: Ian Campbell
Cc: wei.liu2, wency, andrew.cooper3, yunhong.jiang, ian.jackson,
xen-devel, rshriram
On 06/03/2015 12:22 AM, Yang Hongyang wrote:
>
>
> On 06/02/2015 10:48 PM, Ian Campbell wrote:
>> On Wed, 2015-05-20 at 18:01 +0800, Yang Hongyang wrote:
>>> move toolstack code into libxl_toolstack.c
>>
>> It's not clear to me what "toolstack code" is here, the whole of libxl
>> and xl is "toolstack code".
>>
>> Is the code being moved stuff to do with adding toolstack state to the
>> save stream? Perhaps libxl_{suspend,save}_toolstack.c? Or could this not
>> go in the libxl_dom_suspend.c you just created?
>
> My thought was libxl_dom_suspend.c only contains code that do vm suspend
> stuff(not save). So compare to move it to dom_suspend.c, I prefer not
> move it or use libxl_{suspend,save}_toolstack.c. Maybe leave the code
> not moved?
I think I'm going to move this code into libxl_dom_save.c, by merge this
patch with the next patch.
>
>>
>>
>> .
>>
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v1 4/5] tools/libxl: move toolstack code into libxl_toolstack.c
2015-06-03 2:52 ` Yang Hongyang
@ 2015-06-03 9:24 ` Ian Campbell
0 siblings, 0 replies; 23+ messages in thread
From: Ian Campbell @ 2015-06-03 9:24 UTC (permalink / raw)
To: Yang Hongyang
Cc: wei.liu2, wency, andrew.cooper3, yunhong.jiang, ian.jackson,
xen-devel, rshriram
On Wed, 2015-06-03 at 10:52 +0800, Yang Hongyang wrote:
>
> On 06/03/2015 12:22 AM, Yang Hongyang wrote:
> >
> >
> > On 06/02/2015 10:48 PM, Ian Campbell wrote:
> >> On Wed, 2015-05-20 at 18:01 +0800, Yang Hongyang wrote:
> >>> move toolstack code into libxl_toolstack.c
> >>
> >> It's not clear to me what "toolstack code" is here, the whole of libxl
> >> and xl is "toolstack code".
> >>
> >> Is the code being moved stuff to do with adding toolstack state to the
> >> save stream? Perhaps libxl_{suspend,save}_toolstack.c? Or could this not
> >> go in the libxl_dom_suspend.c you just created?
> >
> > My thought was libxl_dom_suspend.c only contains code that do vm suspend
> > stuff(not save). So compare to move it to dom_suspend.c, I prefer not
> > move it or use libxl_{suspend,save}_toolstack.c. Maybe leave the code
> > not moved?
>
> I think I'm going to move this code into libxl_dom_save.c, by merge this
> patch with the next patch.
OK.
^ permalink raw reply [flat|nested] 23+ messages in thread
* [PATCH v1 5/5] tools/libxl: move domain save codes into libxl_dom_save.c
2015-05-20 10:01 [PATCH v1 0/5] Misc cleanups for libxl Yang Hongyang
` (3 preceding siblings ...)
2015-05-20 10:01 ` [PATCH v1 4/5] tools/libxl: move toolstack code into libxl_toolstack.c Yang Hongyang
@ 2015-05-20 10:01 ` Yang Hongyang
2015-05-27 8:30 ` [PATCH v1 0/5] Misc cleanups for libxl Yang Hongyang
2015-06-02 14:53 ` Ian Campbell
6 siblings, 0 replies; 23+ messages in thread
From: Yang Hongyang @ 2015-05-20 10:01 UTC (permalink / raw)
To: xen-devel
Cc: wei.liu2, ian.campbell, wency, andrew.cooper3, yunhong.jiang,
ian.jackson, rshriram
move domain save codes into libxl_dom_save.c
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
CC: Ian Campbell <Ian.Campbell@citrix.com>
CC: Ian Jackson <Ian.Jackson@eu.citrix.com>
CC: Wei Liu <wei.liu2@citrix.com>
CC: Andrew Cooper <andrew.cooper3@citrix.com>
---
tools/libxl/Makefile | 2 +-
tools/libxl/libxl_dom.c | 468 ----------------------------------------
tools/libxl/libxl_dom_save.c | 493 +++++++++++++++++++++++++++++++++++++++++++
3 files changed, 494 insertions(+), 469 deletions(-)
create mode 100644 tools/libxl/libxl_dom_save.c
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index 48f2cbb..105a989 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -96,7 +96,7 @@ LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \
libxl_json.o libxl_aoutils.o libxl_numa.o libxl_vnuma.o \
libxl_save_callout.o _libxl_save_msgs_callout.o \
libxl_qmp.o libxl_event.o libxl_fork.o libxl_dom_suspend.o \
- libxl_toolstack.o $(LIBXL_OBJS-y)
+ libxl_toolstack.o libxl_dom_save.o $(LIBXL_OBJS-y)
LIBXL_OBJS += libxl_genid.o
LIBXL_OBJS += _libxl_types.o libxl_flask.o _libxl_types_internal.o
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index 1caf21c..d536475 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -1020,474 +1020,6 @@ int libxl__qemu_traditional_cmd(libxl__gc *gc, uint32_t domid,
return libxl__xs_write(gc, XBT_NULL, path, "%s", cmd);
}
-/*----- complicated callback, called by xc_domain_save -----*/
-
-/*
- * We implement the other end of protocol for controlling qemu-dm's
- * logdirty. There is no documentation for this protocol, but our
- * counterparty's implementation is in
- * qemu-xen-traditional.git:xenstore.c in the function
- * xenstore_process_logdirty_event
- */
-
-static void switch_logdirty_timeout(libxl__egc *egc, libxl__ev_time *ev,
- const struct timeval *requested_abs);
-static void switch_logdirty_xswatch(libxl__egc *egc, libxl__ev_xswatch*,
- const char *watch_path, const char *event_path);
-static void switch_logdirty_done(libxl__egc *egc,
- libxl__domain_save_state *dss, int ok);
-
-static void logdirty_init(libxl__logdirty_switch *lds)
-{
- lds->cmd_path = 0;
- libxl__ev_xswatch_init(&lds->watch);
- libxl__ev_time_init(&lds->timeout);
-}
-
-static void domain_suspend_switch_qemu_xen_traditional_logdirty
- (int domid, unsigned enable,
- libxl__save_helper_state *shs)
-{
- libxl__egc *egc = shs->egc;
- libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
- libxl__logdirty_switch *lds = &dss->logdirty;
- STATE_AO_GC(dss->ao);
- int rc;
- xs_transaction_t t = 0;
- const char *got;
-
- if (!lds->cmd_path) {
- uint32_t dm_domid = libxl_get_stubdom_id(CTX, domid);
- lds->cmd_path = libxl__device_model_xs_path(gc, dm_domid, domid,
- "/logdirty/cmd");
- lds->ret_path = libxl__device_model_xs_path(gc, dm_domid, domid,
- "/logdirty/ret");
- }
- lds->cmd = enable ? "enable" : "disable";
-
- rc = libxl__ev_xswatch_register(gc, &lds->watch,
- switch_logdirty_xswatch, lds->ret_path);
- if (rc) goto out;
-
- rc = libxl__ev_time_register_rel(gc, &lds->timeout,
- switch_logdirty_timeout, 10*1000);
- if (rc) goto out;
-
- for (;;) {
- rc = libxl__xs_transaction_start(gc, &t);
- if (rc) goto out;
-
- rc = libxl__xs_read_checked(gc, t, lds->cmd_path, &got);
- if (rc) goto out;
-
- if (got) {
- const char *got_ret;
- rc = libxl__xs_read_checked(gc, t, lds->ret_path, &got_ret);
- if (rc) goto out;
-
- if (!got_ret || strcmp(got, got_ret)) {
- LOG(ERROR,"controlling logdirty: qemu was already sent"
- " command `%s' (xenstore path `%s') but result is `%s'",
- got, lds->cmd_path, got_ret ? got_ret : "<none>");
- rc = ERROR_FAIL;
- goto out;
- }
- rc = libxl__xs_rm_checked(gc, t, lds->cmd_path);
- if (rc) goto out;
- }
-
- rc = libxl__xs_rm_checked(gc, t, lds->ret_path);
- if (rc) goto out;
-
- rc = libxl__xs_write_checked(gc, t, lds->cmd_path, lds->cmd);
- if (rc) goto out;
-
- rc = libxl__xs_transaction_commit(gc, &t);
- if (!rc) break;
- if (rc<0) goto out;
- }
-
- /* OK, wait for some callback */
- return;
-
- out:
- LOG(ERROR,"logdirty switch failed (rc=%d), aborting suspend",rc);
- libxl__xs_transaction_abort(gc, &t);
- switch_logdirty_done(egc,dss,-1);
-}
-
-static void domain_suspend_switch_qemu_xen_logdirty
- (int domid, unsigned enable,
- libxl__save_helper_state *shs)
-{
- libxl__egc *egc = shs->egc;
- libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
- STATE_AO_GC(dss->ao);
- int rc;
-
- rc = libxl__qmp_set_global_dirty_log(gc, domid, enable);
- if (!rc) {
- libxl__xc_domain_saverestore_async_callback_done(egc, shs, 0);
- } else {
- LOG(ERROR,"logdirty switch failed (rc=%d), aborting suspend",rc);
- libxl__xc_domain_saverestore_async_callback_done(egc, shs, -1);
- }
-}
-
-void libxl__domain_suspend_common_switch_qemu_logdirty
- (int domid, unsigned enable, void *user)
-{
- libxl__save_helper_state *shs = user;
- libxl__egc *egc = shs->egc;
- libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
- STATE_AO_GC(dss->ao);
-
- switch (libxl__device_model_version_running(gc, domid)) {
- case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
- domain_suspend_switch_qemu_xen_traditional_logdirty(domid, enable, shs);
- break;
- case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
- domain_suspend_switch_qemu_xen_logdirty(domid, enable, shs);
- break;
- default:
- LOG(ERROR,"logdirty switch failed"
- ", no valid device model version found, aborting suspend");
- libxl__xc_domain_saverestore_async_callback_done(egc, shs, -1);
- }
-}
-static void switch_logdirty_timeout(libxl__egc *egc, libxl__ev_time *ev,
- const struct timeval *requested_abs)
-{
- libxl__domain_save_state *dss = CONTAINER_OF(ev, *dss, logdirty.timeout);
- STATE_AO_GC(dss->ao);
- LOG(ERROR,"logdirty switch: wait for device model timed out");
- switch_logdirty_done(egc,dss,-1);
-}
-
-static void switch_logdirty_xswatch(libxl__egc *egc, libxl__ev_xswatch *watch,
- const char *watch_path, const char *event_path)
-{
- libxl__domain_save_state *dss =
- CONTAINER_OF(watch, *dss, logdirty.watch);
- libxl__logdirty_switch *lds = &dss->logdirty;
- STATE_AO_GC(dss->ao);
- const char *got;
- xs_transaction_t t = 0;
- int rc;
-
- for (;;) {
- rc = libxl__xs_transaction_start(gc, &t);
- if (rc) goto out;
-
- rc = libxl__xs_read_checked(gc, t, lds->ret_path, &got);
- if (rc) goto out;
-
- if (!got) {
- rc = +1;
- goto out;
- }
-
- if (strcmp(got, lds->cmd)) {
- LOG(ERROR,"logdirty switch: sent command `%s' but got reply `%s'"
- " (xenstore paths `%s' / `%s')", lds->cmd, got,
- lds->cmd_path, lds->ret_path);
- rc = ERROR_FAIL;
- goto out;
- }
-
- rc = libxl__xs_rm_checked(gc, t, lds->cmd_path);
- if (rc) goto out;
-
- rc = libxl__xs_rm_checked(gc, t, lds->ret_path);
- if (rc) goto out;
-
- rc = libxl__xs_transaction_commit(gc, &t);
- if (!rc) break;
- if (rc<0) goto out;
- }
-
- out:
- /* rc < 0: error
- * rc == 0: ok, we are done
- * rc == +1: need to keep waiting
- */
- libxl__xs_transaction_abort(gc, &t);
-
- if (!rc) {
- switch_logdirty_done(egc,dss,0);
- } else if (rc < 0) {
- LOG(ERROR,"logdirty switch: failed (rc=%d)",rc);
- switch_logdirty_done(egc,dss,-1);
- }
-}
-
-static void switch_logdirty_done(libxl__egc *egc,
- libxl__domain_save_state *dss,
- int broke)
-{
- STATE_AO_GC(dss->ao);
- libxl__logdirty_switch *lds = &dss->logdirty;
-
- libxl__ev_xswatch_deregister(gc, &lds->watch);
- libxl__ev_time_deregister(gc, &lds->timeout);
-
- libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, broke);
-}
-
-/*----- main code for saving, in order of execution -----*/
-
-static void domain_save_done(libxl__egc *egc,
- libxl__domain_save_state *dss, int rc);
-
-void libxl__domain_save(libxl__egc *egc, libxl__domain_save_state *dss)
-{
- STATE_AO_GC(dss->ao);
- int port;
- int rc = ERROR_FAIL;
-
- /* 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;
- libxl__srm_save_autogen_callbacks *const callbacks =
- &dss->shs.callbacks.save.a;
- libxl__domain_suspend_state *dss2 = &dss->dss;
-
- logdirty_init(&dss->logdirty);
- libxl__xswait_init(&dss2->pvcontrol);
- libxl__ev_evtchn_init(&dss2->guest_evtchn);
- libxl__ev_xswatch_init(&dss2->guest_watch);
- libxl__ev_time_init(&dss2->guest_timeout);
-
- switch (type) {
- case LIBXL_DOMAIN_TYPE_HVM: {
- dss->hvm = 1;
- dss2->hvm = 1;
- break;
- }
- case LIBXL_DOMAIN_TYPE_PV:
- dss->hvm = 0;
- dss2->hvm = 0;
- break;
- default:
- abort();
- }
-
- dss->xcflags = (live ? XCFLAGS_LIVE : 0)
- | (debug ? XCFLAGS_DEBUG : 0)
- | (dss->hvm ? XCFLAGS_HVM : 0);
-
- dss2->guest_evtchn.port = -1;
- dss2->guest_evtchn_lockfd = -1;
- dss2->guest_responded = 0;
- dss2->dm_savefile = libxl__device_model_savefile(gc, domid);
- dss2->domid = domid;
- dss2->ao = ao;
-
- if (r_info != NULL) {
- dss->interval = r_info->interval;
- dss->xcflags |= XCFLAGS_CHECKPOINTED;
- if (libxl_defbool_val(r_info->compression))
- dss->xcflags |= XCFLAGS_CHECKPOINT_COMPRESS;
- }
-
- port = xs_suspend_evtchn_port(dss2->domid);
-
- if (port >= 0) {
- rc = libxl__ctx_evtchn_init(gc);
- if (rc) goto out;
-
- dss2->guest_evtchn.port =
- xc_suspend_evtchn_init_exclusive(CTX->xch, CTX->xce,
- dss2->domid, port, &dss2->guest_evtchn_lockfd);
-
- if (dss2->guest_evtchn.port < 0) {
- LOG(WARN, "Suspend event channel initialization failed");
- rc = ERROR_FAIL;
- goto out;
- }
- }
-
- memset(callbacks, 0, sizeof(*callbacks));
- if (r_info != NULL) {
- callbacks->suspend = libxl__remus_domain_suspend_callback;
- callbacks->postcopy = libxl__remus_domain_resume_callback;
- callbacks->checkpoint = libxl__remus_domain_checkpoint_callback;
- } else
- callbacks->suspend = libxl__domain_suspend_callback;
-
- callbacks->switch_qemu_logdirty = libxl__domain_suspend_common_switch_qemu_logdirty;
- dss->shs.callbacks.save.toolstack_save = libxl__toolstack_save;
-
- libxl__xc_domain_save(egc, dss);
- return;
-
- out:
- domain_save_done(egc, dss, rc);
-}
-
-void libxl__xc_domain_save_done(libxl__egc *egc, void *dss_void,
- int rc, int retval, int errnoval)
-{
- libxl__domain_save_state *dss = dss_void;
- STATE_AO_GC(dss->ao);
-
- /* Convenience aliases */
- const libxl_domain_type type = dss->type;
- libxl__domain_suspend_state *dss2 = &dss->dss;
-
- if (rc)
- goto out;
-
- if (retval) {
- LOGEV(ERROR, errnoval, "saving domain: %s",
- dss2->guest_responded ?
- "domain responded to suspend request" :
- "domain did not respond to suspend request");
- if ( !dss2->guest_responded )
- rc = ERROR_GUEST_TIMEDOUT;
- else
- rc = ERROR_FAIL;
- goto out;
- }
-
- if (type == LIBXL_DOMAIN_TYPE_HVM) {
- rc = libxl__domain_suspend_device_model(gc, dss2);
- if (rc) goto out;
-
- libxl__domain_save_device_model(egc, dss, domain_save_done);
- return;
- }
-
- rc = 0;
-
-out:
- domain_save_done(egc, dss, rc);
-}
-
-static void save_device_model_datacopier_done(libxl__egc *egc,
- libxl__datacopier_state *dc, int onwrite, int errnoval);
-
-void libxl__domain_save_device_model(libxl__egc *egc,
- libxl__domain_save_state *dss,
- libxl__save_device_model_cb *callback)
-{
- STATE_AO_GC(dss->ao);
- struct stat st;
- uint32_t qemu_state_len;
- int rc;
-
- dss->save_dm_callback = callback;
-
- /* Convenience aliases */
- const char *const filename = dss->dss.dm_savefile;
- const int fd = dss->fd;
-
- libxl__datacopier_state *dc = &dss->save_dm_datacopier;
- memset(dc, 0, sizeof(*dc));
- dc->readwhat = GCSPRINTF("qemu save file %s", filename);
- dc->ao = ao;
- dc->readfd = -1;
- dc->writefd = fd;
- dc->maxsz = INT_MAX;
- dc->bytes_to_read = -1;
- dc->copywhat = GCSPRINTF("qemu save file for domain %"PRIu32, dss->domid);
- dc->writewhat = "save/migration stream";
- dc->callback = save_device_model_datacopier_done;
-
- dc->readfd = open(filename, O_RDONLY);
- if (dc->readfd < 0) {
- LOGE(ERROR, "unable to open %s", dc->readwhat);
- goto out;
- }
-
- if (fstat(dc->readfd, &st))
- {
- LOGE(ERROR, "unable to fstat %s", dc->readwhat);
- goto out;
- }
-
- if (!S_ISREG(st.st_mode)) {
- LOG(ERROR, "%s is not a plain file!", dc->readwhat);
- goto out;
- }
-
- qemu_state_len = st.st_size;
- LOG(DEBUG, "%s is %d bytes", dc->readwhat, qemu_state_len);
-
- rc = libxl__datacopier_start(dc);
- if (rc) goto out;
-
- libxl__datacopier_prefixdata(egc, dc,
- QEMU_SIGNATURE, strlen(QEMU_SIGNATURE));
-
- libxl__datacopier_prefixdata(egc, dc,
- &qemu_state_len, sizeof(qemu_state_len));
- return;
-
- out:
- save_device_model_datacopier_done(egc, dc, -1, 0);
-}
-
-static void save_device_model_datacopier_done(libxl__egc *egc,
- libxl__datacopier_state *dc, int onwrite, int errnoval)
-{
- libxl__domain_save_state *dss =
- CONTAINER_OF(dc, *dss, save_dm_datacopier);
- STATE_AO_GC(dss->ao);
-
- /* Convenience aliases */
- const char *const filename = dss->dss.dm_savefile;
- int our_rc = 0;
- int rc;
-
- libxl__datacopier_kill(dc);
-
- if (onwrite || errnoval)
- our_rc = ERROR_FAIL;
-
- if (dc->readfd >= 0) {
- close(dc->readfd);
- dc->readfd = -1;
- }
-
- rc = libxl__remove_file(gc, filename);
- if (!our_rc) our_rc = rc;
-
- dss->save_dm_callback(egc, dss, our_rc);
-}
-
-static void domain_save_done(libxl__egc *egc,
- libxl__domain_save_state *dss, int rc)
-{
- STATE_AO_GC(dss->ao);
-
- /* Convenience aliases */
- const uint32_t domid = dss->domid;
- libxl__domain_suspend_state *dss2 = &dss->dss;
-
- libxl__ev_evtchn_cancel(gc, &dss2->guest_evtchn);
-
- if (dss2->guest_evtchn.port > 0)
- xc_suspend_evtchn_release(CTX->xch, CTX->xce, domid,
- dss2->guest_evtchn.port, &dss2->guest_evtchn_lockfd);
-
- if (dss->remus) {
- /*
- * With Remus, if we reach this point, it means either
- * backup died or some network error occurred preventing us
- * from sending checkpoints. Teardown the network buffers and
- * release netlink resources. This is an async op.
- */
- libxl__remus_teardown(egc, dss, rc);
- return;
- }
-
- dss->callback(egc, dss, rc);
-}
-
/*==================== Miscellaneous ====================*/
char *libxl__uuid2string(libxl__gc *gc, const libxl_uuid uuid)
diff --git a/tools/libxl/libxl_dom_save.c b/tools/libxl/libxl_dom_save.c
new file mode 100644
index 0000000..c98f1dd
--- /dev/null
+++ b/tools/libxl/libxl_dom_save.c
@@ -0,0 +1,493 @@
+/*
+ * Copyright (C) 2009 Citrix Ltd.
+ * Author Vincent Hanquez <vincent.hanquez@eu.citrix.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h" /* must come before any other headers */
+
+#include "libxl_internal.h"
+
+/*----- complicated callback, called by xc_domain_save -----*/
+
+/*
+ * We implement the other end of protocol for controlling qemu-dm's
+ * logdirty. There is no documentation for this protocol, but our
+ * counterparty's implementation is in
+ * qemu-xen-traditional.git:xenstore.c in the function
+ * xenstore_process_logdirty_event
+ */
+
+static void switch_logdirty_timeout(libxl__egc *egc, libxl__ev_time *ev,
+ const struct timeval *requested_abs);
+static void switch_logdirty_xswatch(libxl__egc *egc, libxl__ev_xswatch*,
+ const char *watch_path, const char *event_path);
+static void switch_logdirty_done(libxl__egc *egc,
+ libxl__domain_save_state *dss, int ok);
+
+static void logdirty_init(libxl__logdirty_switch *lds)
+{
+ lds->cmd_path = 0;
+ libxl__ev_xswatch_init(&lds->watch);
+ libxl__ev_time_init(&lds->timeout);
+}
+
+static void domain_suspend_switch_qemu_xen_traditional_logdirty
+ (int domid, unsigned enable,
+ libxl__save_helper_state *shs)
+{
+ libxl__egc *egc = shs->egc;
+ libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
+ libxl__logdirty_switch *lds = &dss->logdirty;
+ STATE_AO_GC(dss->ao);
+ int rc;
+ xs_transaction_t t = 0;
+ const char *got;
+
+ if (!lds->cmd_path) {
+ uint32_t dm_domid = libxl_get_stubdom_id(CTX, domid);
+ lds->cmd_path = libxl__device_model_xs_path(gc, dm_domid, domid,
+ "/logdirty/cmd");
+ lds->ret_path = libxl__device_model_xs_path(gc, dm_domid, domid,
+ "/logdirty/ret");
+ }
+ lds->cmd = enable ? "enable" : "disable";
+
+ rc = libxl__ev_xswatch_register(gc, &lds->watch,
+ switch_logdirty_xswatch, lds->ret_path);
+ if (rc) goto out;
+
+ rc = libxl__ev_time_register_rel(gc, &lds->timeout,
+ switch_logdirty_timeout, 10*1000);
+ if (rc) goto out;
+
+ for (;;) {
+ rc = libxl__xs_transaction_start(gc, &t);
+ if (rc) goto out;
+
+ rc = libxl__xs_read_checked(gc, t, lds->cmd_path, &got);
+ if (rc) goto out;
+
+ if (got) {
+ const char *got_ret;
+ rc = libxl__xs_read_checked(gc, t, lds->ret_path, &got_ret);
+ if (rc) goto out;
+
+ if (!got_ret || strcmp(got, got_ret)) {
+ LOG(ERROR,"controlling logdirty: qemu was already sent"
+ " command `%s' (xenstore path `%s') but result is `%s'",
+ got, lds->cmd_path, got_ret ? got_ret : "<none>");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ rc = libxl__xs_rm_checked(gc, t, lds->cmd_path);
+ if (rc) goto out;
+ }
+
+ rc = libxl__xs_rm_checked(gc, t, lds->ret_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_write_checked(gc, t, lds->cmd_path, lds->cmd);
+ if (rc) goto out;
+
+ rc = libxl__xs_transaction_commit(gc, &t);
+ if (!rc) break;
+ if (rc<0) goto out;
+ }
+
+ /* OK, wait for some callback */
+ return;
+
+ out:
+ LOG(ERROR,"logdirty switch failed (rc=%d), aborting suspend",rc);
+ libxl__xs_transaction_abort(gc, &t);
+ switch_logdirty_done(egc,dss,-1);
+}
+
+static void domain_suspend_switch_qemu_xen_logdirty
+ (int domid, unsigned enable,
+ libxl__save_helper_state *shs)
+{
+ libxl__egc *egc = shs->egc;
+ libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
+ STATE_AO_GC(dss->ao);
+ int rc;
+
+ rc = libxl__qmp_set_global_dirty_log(gc, domid, enable);
+ if (!rc) {
+ libxl__xc_domain_saverestore_async_callback_done(egc, shs, 0);
+ } else {
+ LOG(ERROR,"logdirty switch failed (rc=%d), aborting suspend",rc);
+ libxl__xc_domain_saverestore_async_callback_done(egc, shs, -1);
+ }
+}
+
+void libxl__domain_suspend_common_switch_qemu_logdirty
+ (int domid, unsigned enable, void *user)
+{
+ libxl__save_helper_state *shs = user;
+ libxl__egc *egc = shs->egc;
+ libxl__domain_save_state *dss = CONTAINER_OF(shs, *dss, shs);
+ STATE_AO_GC(dss->ao);
+
+ switch (libxl__device_model_version_running(gc, domid)) {
+ case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL:
+ domain_suspend_switch_qemu_xen_traditional_logdirty(domid, enable, shs);
+ break;
+ case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
+ domain_suspend_switch_qemu_xen_logdirty(domid, enable, shs);
+ break;
+ default:
+ LOG(ERROR,"logdirty switch failed"
+ ", no valid device model version found, aborting suspend");
+ libxl__xc_domain_saverestore_async_callback_done(egc, shs, -1);
+ }
+}
+static void switch_logdirty_timeout(libxl__egc *egc, libxl__ev_time *ev,
+ const struct timeval *requested_abs)
+{
+ libxl__domain_save_state *dss = CONTAINER_OF(ev, *dss, logdirty.timeout);
+ STATE_AO_GC(dss->ao);
+ LOG(ERROR,"logdirty switch: wait for device model timed out");
+ switch_logdirty_done(egc,dss,-1);
+}
+
+static void switch_logdirty_xswatch(libxl__egc *egc, libxl__ev_xswatch *watch,
+ const char *watch_path, const char *event_path)
+{
+ libxl__domain_save_state *dss =
+ CONTAINER_OF(watch, *dss, logdirty.watch);
+ libxl__logdirty_switch *lds = &dss->logdirty;
+ STATE_AO_GC(dss->ao);
+ const char *got;
+ xs_transaction_t t = 0;
+ int rc;
+
+ for (;;) {
+ rc = libxl__xs_transaction_start(gc, &t);
+ if (rc) goto out;
+
+ rc = libxl__xs_read_checked(gc, t, lds->ret_path, &got);
+ if (rc) goto out;
+
+ if (!got) {
+ rc = +1;
+ goto out;
+ }
+
+ if (strcmp(got, lds->cmd)) {
+ LOG(ERROR,"logdirty switch: sent command `%s' but got reply `%s'"
+ " (xenstore paths `%s' / `%s')", lds->cmd, got,
+ lds->cmd_path, lds->ret_path);
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ rc = libxl__xs_rm_checked(gc, t, lds->cmd_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_rm_checked(gc, t, lds->ret_path);
+ if (rc) goto out;
+
+ rc = libxl__xs_transaction_commit(gc, &t);
+ if (!rc) break;
+ if (rc<0) goto out;
+ }
+
+ out:
+ /* rc < 0: error
+ * rc == 0: ok, we are done
+ * rc == +1: need to keep waiting
+ */
+ libxl__xs_transaction_abort(gc, &t);
+
+ if (!rc) {
+ switch_logdirty_done(egc,dss,0);
+ } else if (rc < 0) {
+ LOG(ERROR,"logdirty switch: failed (rc=%d)",rc);
+ switch_logdirty_done(egc,dss,-1);
+ }
+}
+
+static void switch_logdirty_done(libxl__egc *egc,
+ libxl__domain_save_state *dss,
+ int broke)
+{
+ STATE_AO_GC(dss->ao);
+ libxl__logdirty_switch *lds = &dss->logdirty;
+
+ libxl__ev_xswatch_deregister(gc, &lds->watch);
+ libxl__ev_time_deregister(gc, &lds->timeout);
+
+ libxl__xc_domain_saverestore_async_callback_done(egc, &dss->shs, broke);
+}
+
+/*----- main code for saving, in order of execution -----*/
+
+static void domain_save_done(libxl__egc *egc,
+ libxl__domain_save_state *dss, int rc);
+
+void libxl__domain_save(libxl__egc *egc, libxl__domain_save_state *dss)
+{
+ STATE_AO_GC(dss->ao);
+ int port;
+ int rc = ERROR_FAIL;
+
+ /* 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;
+ libxl__srm_save_autogen_callbacks *const callbacks =
+ &dss->shs.callbacks.save.a;
+ libxl__domain_suspend_state *dss2 = &dss->dss;
+
+ logdirty_init(&dss->logdirty);
+ libxl__xswait_init(&dss2->pvcontrol);
+ libxl__ev_evtchn_init(&dss2->guest_evtchn);
+ libxl__ev_xswatch_init(&dss2->guest_watch);
+ libxl__ev_time_init(&dss2->guest_timeout);
+
+ switch (type) {
+ case LIBXL_DOMAIN_TYPE_HVM: {
+ dss->hvm = 1;
+ dss2->hvm = 1;
+ break;
+ }
+ case LIBXL_DOMAIN_TYPE_PV:
+ dss->hvm = 0;
+ dss2->hvm = 0;
+ break;
+ default:
+ abort();
+ }
+
+ dss->xcflags = (live ? XCFLAGS_LIVE : 0)
+ | (debug ? XCFLAGS_DEBUG : 0)
+ | (dss->hvm ? XCFLAGS_HVM : 0);
+
+ dss2->guest_evtchn.port = -1;
+ dss2->guest_evtchn_lockfd = -1;
+ dss2->guest_responded = 0;
+ dss2->dm_savefile = libxl__device_model_savefile(gc, domid);
+ dss2->domid = domid;
+ dss2->ao = ao;
+
+ if (r_info != NULL) {
+ dss->interval = r_info->interval;
+ dss->xcflags |= XCFLAGS_CHECKPOINTED;
+ if (libxl_defbool_val(r_info->compression))
+ dss->xcflags |= XCFLAGS_CHECKPOINT_COMPRESS;
+ }
+
+ port = xs_suspend_evtchn_port(dss2->domid);
+
+ if (port >= 0) {
+ rc = libxl__ctx_evtchn_init(gc);
+ if (rc) goto out;
+
+ dss2->guest_evtchn.port =
+ xc_suspend_evtchn_init_exclusive(CTX->xch, CTX->xce,
+ dss2->domid, port, &dss2->guest_evtchn_lockfd);
+
+ if (dss2->guest_evtchn.port < 0) {
+ LOG(WARN, "Suspend event channel initialization failed");
+ rc = ERROR_FAIL;
+ goto out;
+ }
+ }
+
+ memset(callbacks, 0, sizeof(*callbacks));
+ if (r_info != NULL) {
+ callbacks->suspend = libxl__remus_domain_suspend_callback;
+ callbacks->postcopy = libxl__remus_domain_resume_callback;
+ callbacks->checkpoint = libxl__remus_domain_checkpoint_callback;
+ } else
+ callbacks->suspend = libxl__domain_suspend_callback;
+
+ callbacks->switch_qemu_logdirty = libxl__domain_suspend_common_switch_qemu_logdirty;
+ dss->shs.callbacks.save.toolstack_save = libxl__toolstack_save;
+
+ libxl__xc_domain_save(egc, dss);
+ return;
+
+ out:
+ domain_save_done(egc, dss, rc);
+}
+
+void libxl__xc_domain_save_done(libxl__egc *egc, void *dss_void,
+ int rc, int retval, int errnoval)
+{
+ libxl__domain_save_state *dss = dss_void;
+ STATE_AO_GC(dss->ao);
+
+ /* Convenience aliases */
+ const libxl_domain_type type = dss->type;
+ libxl__domain_suspend_state *dss2 = &dss->dss;
+
+ if (rc)
+ goto out;
+
+ if (retval) {
+ LOGEV(ERROR, errnoval, "saving domain: %s",
+ dss2->guest_responded ?
+ "domain responded to suspend request" :
+ "domain did not respond to suspend request");
+ if ( !dss2->guest_responded )
+ rc = ERROR_GUEST_TIMEDOUT;
+ else
+ rc = ERROR_FAIL;
+ goto out;
+ }
+
+ if (type == LIBXL_DOMAIN_TYPE_HVM) {
+ rc = libxl__domain_suspend_device_model(gc, dss2);
+ if (rc) goto out;
+
+ libxl__domain_save_device_model(egc, dss, domain_save_done);
+ return;
+ }
+
+ rc = 0;
+
+out:
+ domain_save_done(egc, dss, rc);
+}
+
+static void save_device_model_datacopier_done(libxl__egc *egc,
+ libxl__datacopier_state *dc, int onwrite, int errnoval);
+
+void libxl__domain_save_device_model(libxl__egc *egc,
+ libxl__domain_save_state *dss,
+ libxl__save_device_model_cb *callback)
+{
+ STATE_AO_GC(dss->ao);
+ struct stat st;
+ uint32_t qemu_state_len;
+ int rc;
+
+ dss->save_dm_callback = callback;
+
+ /* Convenience aliases */
+ const char *const filename = dss->dss.dm_savefile;
+ const int fd = dss->fd;
+
+ libxl__datacopier_state *dc = &dss->save_dm_datacopier;
+ memset(dc, 0, sizeof(*dc));
+ dc->readwhat = GCSPRINTF("qemu save file %s", filename);
+ dc->ao = ao;
+ dc->readfd = -1;
+ dc->writefd = fd;
+ dc->maxsz = INT_MAX;
+ dc->bytes_to_read = -1;
+ dc->copywhat = GCSPRINTF("qemu save file for domain %"PRIu32, dss->domid);
+ dc->writewhat = "save/migration stream";
+ dc->callback = save_device_model_datacopier_done;
+
+ dc->readfd = open(filename, O_RDONLY);
+ if (dc->readfd < 0) {
+ LOGE(ERROR, "unable to open %s", dc->readwhat);
+ goto out;
+ }
+
+ if (fstat(dc->readfd, &st))
+ {
+ LOGE(ERROR, "unable to fstat %s", dc->readwhat);
+ goto out;
+ }
+
+ if (!S_ISREG(st.st_mode)) {
+ LOG(ERROR, "%s is not a plain file!", dc->readwhat);
+ goto out;
+ }
+
+ qemu_state_len = st.st_size;
+ LOG(DEBUG, "%s is %d bytes", dc->readwhat, qemu_state_len);
+
+ rc = libxl__datacopier_start(dc);
+ if (rc) goto out;
+
+ libxl__datacopier_prefixdata(egc, dc,
+ QEMU_SIGNATURE, strlen(QEMU_SIGNATURE));
+
+ libxl__datacopier_prefixdata(egc, dc,
+ &qemu_state_len, sizeof(qemu_state_len));
+ return;
+
+ out:
+ save_device_model_datacopier_done(egc, dc, -1, 0);
+}
+
+static void save_device_model_datacopier_done(libxl__egc *egc,
+ libxl__datacopier_state *dc, int onwrite, int errnoval)
+{
+ libxl__domain_save_state *dss =
+ CONTAINER_OF(dc, *dss, save_dm_datacopier);
+ STATE_AO_GC(dss->ao);
+
+ /* Convenience aliases */
+ const char *const filename = dss->dss.dm_savefile;
+ int our_rc = 0;
+ int rc;
+
+ libxl__datacopier_kill(dc);
+
+ if (onwrite || errnoval)
+ our_rc = ERROR_FAIL;
+
+ if (dc->readfd >= 0) {
+ close(dc->readfd);
+ dc->readfd = -1;
+ }
+
+ rc = libxl__remove_file(gc, filename);
+ if (!our_rc) our_rc = rc;
+
+ dss->save_dm_callback(egc, dss, our_rc);
+}
+
+static void domain_save_done(libxl__egc *egc,
+ libxl__domain_save_state *dss, int rc)
+{
+ STATE_AO_GC(dss->ao);
+
+ /* Convenience aliases */
+ const uint32_t domid = dss->domid;
+ libxl__domain_suspend_state *dss2 = &dss->dss;
+
+ libxl__ev_evtchn_cancel(gc, &dss2->guest_evtchn);
+
+ if (dss2->guest_evtchn.port > 0)
+ xc_suspend_evtchn_release(CTX->xch, CTX->xce, domid,
+ dss2->guest_evtchn.port, &dss2->guest_evtchn_lockfd);
+
+ if (dss->remus) {
+ /*
+ * With Remus, if we reach this point, it means either
+ * backup died or some network error occurred preventing us
+ * from sending checkpoints. Teardown the network buffers and
+ * release netlink resources. This is an async op.
+ */
+ libxl__remus_teardown(egc, dss, rc);
+ return;
+ }
+
+ dss->callback(egc, dss, rc);
+}
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
1.9.1
^ permalink raw reply related [flat|nested] 23+ messages in thread
* Re: [PATCH v1 0/5] Misc cleanups for libxl
2015-05-20 10:01 [PATCH v1 0/5] Misc cleanups for libxl Yang Hongyang
` (4 preceding siblings ...)
2015-05-20 10:01 ` [PATCH v1 5/5] tools/libxl: move domain save codes into libxl_dom_save.c Yang Hongyang
@ 2015-05-27 8:30 ` Yang Hongyang
2015-06-02 14:53 ` Ian Campbell
6 siblings, 0 replies; 23+ messages in thread
From: Yang Hongyang @ 2015-05-27 8:30 UTC (permalink / raw)
To: xen-devel
Cc: wei.liu2, ian.campbell, wency, andrew.cooper3, yunhong.jiang,
ian.jackson, rshriram
ping...
On 05/20/2015 06:01 PM, Yang Hongyang wrote:
> This patchset mainly focus on libxl save, most of the patches are
> simply move codes out of libxl_dom.c, no functional changes, may conflict
> with Andrew Cooper's libxl work for migration v2, so CCed Andrew for
> comments.
>
> For convenience, my previous sent patch
> [PATCH v1] libxl/save: Refactor libxl__domain_suspend_state
> is included in this series because all the other patches in this
> series are based on that.
>
> Please see individual patch for detail.
>
> Can get the whole patchset from:
> https://github.com/macrosheep/xen/tree/misc-libxl-v1
>
> Yang Hongyang (5):
> libxl/save: Refactor libxl__domain_suspend_state
> tools/libxl: move domain suspend codes into a separate file
> tools/libxl: move remus codes into libxl_remus.c
> tools/libxl: move toolstack code into libxl_toolstack.c
> tools/libxl: move domain save codes into libxl_dom_save.c
>
> tools/libxl/Makefile | 5 +-
> tools/libxl/libxl.c | 67 +--
> tools/libxl/libxl_dom.c | 1202 --------------------------------------
> tools/libxl/libxl_dom_save.c | 493 ++++++++++++++++
> tools/libxl/libxl_dom_suspend.c | 400 +++++++++++++
> tools/libxl/libxl_internal.h | 62 +-
> tools/libxl/libxl_netbuffer.c | 2 +-
> tools/libxl/libxl_remus.c | 306 ++++++++++
> tools/libxl/libxl_save_callout.c | 2 +-
> tools/libxl/libxl_toolstack.c | 196 +++++++
> 10 files changed, 1452 insertions(+), 1283 deletions(-)
> create mode 100644 tools/libxl/libxl_dom_save.c
> create mode 100644 tools/libxl/libxl_dom_suspend.c
> create mode 100644 tools/libxl/libxl_remus.c
> create mode 100644 tools/libxl/libxl_toolstack.c
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v1 0/5] Misc cleanups for libxl
2015-05-20 10:01 [PATCH v1 0/5] Misc cleanups for libxl Yang Hongyang
` (5 preceding siblings ...)
2015-05-27 8:30 ` [PATCH v1 0/5] Misc cleanups for libxl Yang Hongyang
@ 2015-06-02 14:53 ` Ian Campbell
2015-06-02 16:25 ` Yang Hongyang
6 siblings, 1 reply; 23+ messages in thread
From: Ian Campbell @ 2015-06-02 14:53 UTC (permalink / raw)
To: Yang Hongyang
Cc: wei.liu2, wency, andrew.cooper3, yunhong.jiang, ian.jackson,
xen-devel, rshriram
On Wed, 2015-05-20 at 18:01 +0800, Yang Hongyang wrote:
I've just been through this, sorry for the delay.
I also have written on my TODO list "Remus on Migration-v2 (v7)", but I
have no such patches in my folders and I think I already applied
everything to do with that, so I think that's just a stale entry. If
there's something remus related I've dropped please point me at it.
"[PATCH v1 COLO Pre 00/12]" from earlier is on my TODO list separately
already.
> This patchset mainly focus on libxl save, most of the patches are
> simply move codes out of libxl_dom.c, no functional changes, may conflict
> with Andrew Cooper's libxl work for migration v2, so CCed Andrew for
> comments.
>
> For convenience, my previous sent patch
> [PATCH v1] libxl/save: Refactor libxl__domain_suspend_state
> is included in this series because all the other patches in this
> series are based on that.
>
> Please see individual patch for detail.
>
> Can get the whole patchset from:
> https://github.com/macrosheep/xen/tree/misc-libxl-v1
>
> Yang Hongyang (5):
> libxl/save: Refactor libxl__domain_suspend_state
> tools/libxl: move domain suspend codes into a separate file
> tools/libxl: move remus codes into libxl_remus.c
> tools/libxl: move toolstack code into libxl_toolstack.c
> tools/libxl: move domain save codes into libxl_dom_save.c
>
> tools/libxl/Makefile | 5 +-
> tools/libxl/libxl.c | 67 +--
> tools/libxl/libxl_dom.c | 1202 --------------------------------------
> tools/libxl/libxl_dom_save.c | 493 ++++++++++++++++
> tools/libxl/libxl_dom_suspend.c | 400 +++++++++++++
> tools/libxl/libxl_internal.h | 62 +-
> tools/libxl/libxl_netbuffer.c | 2 +-
> tools/libxl/libxl_remus.c | 306 ++++++++++
> tools/libxl/libxl_save_callout.c | 2 +-
> tools/libxl/libxl_toolstack.c | 196 +++++++
> 10 files changed, 1452 insertions(+), 1283 deletions(-)
> create mode 100644 tools/libxl/libxl_dom_save.c
> create mode 100644 tools/libxl/libxl_dom_suspend.c
> create mode 100644 tools/libxl/libxl_remus.c
> create mode 100644 tools/libxl/libxl_toolstack.c
>
^ permalink raw reply [flat|nested] 23+ messages in thread
* Re: [PATCH v1 0/5] Misc cleanups for libxl
2015-06-02 14:53 ` Ian Campbell
@ 2015-06-02 16:25 ` Yang Hongyang
0 siblings, 0 replies; 23+ messages in thread
From: Yang Hongyang @ 2015-06-02 16:25 UTC (permalink / raw)
To: Ian Campbell
Cc: wei.liu2, wency, andrew.cooper3, yunhong.jiang, ian.jackson,
xen-devel, rshriram
Hi Ian,
Thank you very much for taking time to review this!
On 06/02/2015 10:53 PM, Ian Campbell wrote:
> On Wed, 2015-05-20 at 18:01 +0800, Yang Hongyang wrote:
>
> I've just been through this, sorry for the delay.
>
> I also have written on my TODO list "Remus on Migration-v2 (v7)", but I
> have no such patches in my folders and I think I already applied
> everything to do with that, so I think that's just a stale entry. If
> there's something remus related I've dropped please point me at it.
Yeah, you have already applied all Remus on Migration-v2 stuff. Thanks again..
>
> "[PATCH v1 COLO Pre 00/12]" from earlier is on my TODO list separately
> already.
Thank you!
>
>> This patchset mainly focus on libxl save, most of the patches are
>> simply move codes out of libxl_dom.c, no functional changes, may conflict
>> with Andrew Cooper's libxl work for migration v2, so CCed Andrew for
>> comments.
>>
>> For convenience, my previous sent patch
>> [PATCH v1] libxl/save: Refactor libxl__domain_suspend_state
>> is included in this series because all the other patches in this
>> series are based on that.
>>
>> Please see individual patch for detail.
>>
>> Can get the whole patchset from:
>> https://github.com/macrosheep/xen/tree/misc-libxl-v1
>>
>> Yang Hongyang (5):
>> libxl/save: Refactor libxl__domain_suspend_state
>> tools/libxl: move domain suspend codes into a separate file
>> tools/libxl: move remus codes into libxl_remus.c
>> tools/libxl: move toolstack code into libxl_toolstack.c
>> tools/libxl: move domain save codes into libxl_dom_save.c
>>
>> tools/libxl/Makefile | 5 +-
>> tools/libxl/libxl.c | 67 +--
>> tools/libxl/libxl_dom.c | 1202 --------------------------------------
>> tools/libxl/libxl_dom_save.c | 493 ++++++++++++++++
>> tools/libxl/libxl_dom_suspend.c | 400 +++++++++++++
>> tools/libxl/libxl_internal.h | 62 +-
>> tools/libxl/libxl_netbuffer.c | 2 +-
>> tools/libxl/libxl_remus.c | 306 ++++++++++
>> tools/libxl/libxl_save_callout.c | 2 +-
>> tools/libxl/libxl_toolstack.c | 196 +++++++
>> 10 files changed, 1452 insertions(+), 1283 deletions(-)
>> create mode 100644 tools/libxl/libxl_dom_save.c
>> create mode 100644 tools/libxl/libxl_dom_suspend.c
>> create mode 100644 tools/libxl/libxl_remus.c
>> create mode 100644 tools/libxl/libxl_toolstack.c
>>
>
>
> .
>
--
Thanks,
Yang.
^ permalink raw reply [flat|nested] 23+ messages in thread