mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 10:11:27 +01:00
libxl: Re-introduce libxl__domain_resume
libxl__domain_resume is a rework libxl__domain_resume_deprecated. It makes uses of ev_xswatch and ev_qmp, to replace synchronous QMP calls and libxl__wait_for_device_model_deprecated call. This patch also introduce libxl__dm_resume which is a sub-operation of both libxl__domain_resume and libxl__domain_unpause and can be used instead of libxl__domain_resume_device_model_deprecated. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
This commit is contained in:
1 parent
b215f2ab6a
commit
6298f0eb8f
2 files changed
+219
No files matched your search
@@ -481,6 +481,198 @@ out:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void dm_resume_init(libxl__dm_resume_state *dmrs)
|
||||
{
|
||||
libxl__ev_qmp_init(&dmrs->qmp);
|
||||
libxl__ev_time_init(&dmrs->time);
|
||||
libxl__ev_xswatch_init(&dmrs->watch);
|
||||
}
|
||||
|
||||
static void dm_resume_dispose(libxl__gc *gc,
|
||||
libxl__dm_resume_state *dmrs)
|
||||
{
|
||||
libxl__ev_qmp_dispose(gc, &dmrs->qmp);
|
||||
libxl__ev_time_deregister(gc, &dmrs->time);
|
||||
libxl__ev_xswatch_deregister(gc, &dmrs->watch);
|
||||
}
|
||||
|
||||
static void dm_resume_xswatch_cb(libxl__egc *egc,
|
||||
libxl__ev_xswatch *, const char *watch_path, const char *);
|
||||
static void dm_resume_qmp_done(libxl__egc *egc,
|
||||
libxl__ev_qmp *qmp, const libxl__json_object *, int rc);
|
||||
static void dm_resume_timeout(libxl__egc *egc,
|
||||
libxl__ev_time *, const struct timeval *, int rc);
|
||||
static void dm_resume_done(libxl__egc *egc,
|
||||
libxl__dm_resume_state *dmrs, int rc);
|
||||
|
||||
void libxl__dm_resume(libxl__egc *egc,
|
||||
libxl__dm_resume_state *dmrs)
|
||||
{
|
||||
STATE_AO_GC(dmrs->ao);
|
||||
int rc = 0;
|
||||
|
||||
/* Convenience aliases */
|
||||
libxl_domid domid = dmrs->domid;
|
||||
libxl__ev_qmp *qmp = &dmrs->qmp;
|
||||
|
||||
dm_resume_init(dmrs);
|
||||
|
||||
rc = libxl__ev_time_register_rel(dmrs->ao,
|
||||
&dmrs->time,
|
||||
dm_resume_timeout,
|
||||
LIBXL_DEVICE_MODEL_START_TIMEOUT);
|
||||
if (rc) goto out;
|
||||
|
||||
switch (libxl__device_model_version_running(gc, domid)) {
|
||||
case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN_TRADITIONAL: {
|
||||
uint32_t dm_domid = libxl_get_stubdom_id(CTX, domid);
|
||||
const char *path, *state;
|
||||
|
||||
path = DEVICE_MODEL_XS_PATH(gc, dm_domid, domid, "/state");
|
||||
rc = libxl__xs_read_checked(gc, XBT_NULL, path, &state);
|
||||
if (rc) goto out;
|
||||
if (!state || strcmp(state, "paused")) {
|
||||
/* already running */
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rc = libxl__qemu_traditional_cmd(gc, domid, "continue");
|
||||
if (rc) goto out;
|
||||
rc = libxl__ev_xswatch_register(gc, &dmrs->watch,
|
||||
dm_resume_xswatch_cb,
|
||||
path);
|
||||
if (rc) goto out;
|
||||
break;
|
||||
}
|
||||
case LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN:
|
||||
qmp->ao = dmrs->ao;
|
||||
qmp->domid = domid;
|
||||
qmp->callback = dm_resume_qmp_done;
|
||||
qmp->payload_fd = -1;
|
||||
rc = libxl__ev_qmp_send(gc, qmp, "cont", NULL);
|
||||
if (rc) goto out;
|
||||
break;
|
||||
default:
|
||||
rc = ERROR_INVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
out:
|
||||
dm_resume_done(egc, dmrs, rc);
|
||||
}
|
||||
|
||||
static void dm_resume_xswatch_cb(libxl__egc *egc,
|
||||
libxl__ev_xswatch *xsw,
|
||||
const char *watch_path,
|
||||
const char *event_path)
|
||||
{
|
||||
EGC_GC;
|
||||
libxl__dm_resume_state *dmrs = CONTAINER_OF(xsw, *dmrs, watch);
|
||||
int rc;
|
||||
const char *value;
|
||||
|
||||
rc = libxl__xs_read_checked(gc, XBT_NULL, watch_path, &value);
|
||||
if (rc) goto out;
|
||||
|
||||
if (!value || strcmp(value, "running"))
|
||||
return;
|
||||
|
||||
rc = 0;
|
||||
out:
|
||||
dm_resume_done(egc, dmrs, rc);
|
||||
}
|
||||
|
||||
static void dm_resume_qmp_done(libxl__egc *egc,
|
||||
libxl__ev_qmp *qmp,
|
||||
const libxl__json_object *response,
|
||||
int rc)
|
||||
{
|
||||
libxl__dm_resume_state *dmrs = CONTAINER_OF(qmp, *dmrs, qmp);
|
||||
dm_resume_done(egc, dmrs, rc);
|
||||
}
|
||||
|
||||
static void dm_resume_timeout(libxl__egc *egc,
|
||||
libxl__ev_time *ev,
|
||||
const struct timeval *requested_abs,
|
||||
int rc)
|
||||
{
|
||||
libxl__dm_resume_state *dmrs = CONTAINER_OF(ev, *dmrs, time);
|
||||
dm_resume_done(egc, dmrs, rc);
|
||||
}
|
||||
|
||||
static void dm_resume_done(libxl__egc *egc,
|
||||
libxl__dm_resume_state *dmrs,
|
||||
int rc)
|
||||
{
|
||||
EGC_GC;
|
||||
|
||||
if (rc) {
|
||||
LOGD(ERROR, dmrs->domid,
|
||||
"Failed to resume device model: rc=%d", rc);
|
||||
}
|
||||
|
||||
dm_resume_dispose(gc, dmrs);
|
||||
dmrs->dm_resumed_callback(egc, dmrs, rc);
|
||||
}
|
||||
|
||||
|
||||
static void domain_resume_done(libxl__egc *egc,
|
||||
libxl__dm_resume_state *dmrs, int rc);
|
||||
|
||||
void libxl__domain_resume(libxl__egc *egc,
|
||||
libxl__dm_resume_state *dmrs,
|
||||
bool suspend_cancel)
|
||||
{
|
||||
STATE_AO_GC(dmrs->ao);
|
||||
int rc = 0;
|
||||
libxl_domain_type type = libxl__domain_type(gc, dmrs->domid);
|
||||
|
||||
if (type == LIBXL_DOMAIN_TYPE_INVALID) {
|
||||
rc = ERROR_FAIL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (type != LIBXL_DOMAIN_TYPE_HVM) {
|
||||
rc = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
dmrs->suspend_cancel = suspend_cancel;
|
||||
dmrs->dm_resumed_callback = domain_resume_done;
|
||||
libxl__dm_resume(egc, dmrs); /* must be last */
|
||||
return;
|
||||
|
||||
out:
|
||||
domain_resume_done(egc, dmrs, rc);
|
||||
}
|
||||
|
||||
static void domain_resume_done(libxl__egc *egc,
|
||||
libxl__dm_resume_state *dmrs, int rc)
|
||||
{
|
||||
EGC_GC;
|
||||
|
||||
/* Convenience aliases */
|
||||
libxl_domid domid = dmrs->domid;
|
||||
|
||||
if (rc) goto out;
|
||||
|
||||
if (xc_domain_resume(CTX->xch, domid, dmrs->suspend_cancel)) {
|
||||
LOGED(ERROR, domid, "xc_domain_resume failed");
|
||||
rc = ERROR_FAIL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!xs_resume_domain(CTX->xsh, domid)) {
|
||||
LOGED(ERROR, domid, "xs_resume_domain failed");
|
||||
rc = ERROR_FAIL;
|
||||
}
|
||||
out:
|
||||
dmrs->callback(egc, dmrs, rc);
|
||||
}
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* mode: C
|
||||
|
||||
@@ -197,6 +197,7 @@ typedef struct libxl__device_type libxl__device_type;
|
||||
typedef struct libxl__json_object libxl__json_object;
|
||||
typedef struct libxl__carefd libxl__carefd;
|
||||
typedef struct libxl__ev_devlock libxl__ev_devlock;
|
||||
typedef struct libxl__dm_resume_state libxl__dm_resume_state;
|
||||
|
||||
typedef struct libxl__domain_create_state libxl__domain_create_state;
|
||||
typedef void libxl__domain_create_cb(struct libxl__egc *egc,
|
||||
@@ -1340,6 +1341,32 @@ _hidden int libxl__domain_resume_deprecated(libxl__gc *gc, uint32_t domid,
|
||||
_hidden int libxl__domain_unpause_deprecated(libxl__gc *,
|
||||
libxl_domid domid);
|
||||
|
||||
/* Call libxl__dm_resume_init() and fill the first few fields,
|
||||
* then call one of libxl__domain_resume / libxl__domain_unpause
|
||||
* or directly libxl__dm_resume if only the device model needs to be
|
||||
* "resumed". */
|
||||
struct libxl__dm_resume_state {
|
||||
/* caller must fill these in, and they must all remain valid */
|
||||
libxl__ao *ao;
|
||||
libxl_domid domid;
|
||||
void (*callback)(libxl__egc *, libxl__dm_resume_state *, int rc);
|
||||
|
||||
/* private to libxl__domain_resume */
|
||||
void (*dm_resumed_callback)(libxl__egc *,
|
||||
libxl__dm_resume_state *, int rc);
|
||||
bool suspend_cancel;
|
||||
|
||||
/* private to libxl__dm_resume */
|
||||
libxl__ev_qmp qmp;
|
||||
libxl__ev_time time;
|
||||
libxl__ev_xswatch watch;
|
||||
};
|
||||
_hidden void libxl__dm_resume(libxl__egc *egc,
|
||||
libxl__dm_resume_state *dmrs);
|
||||
_hidden void libxl__domain_resume(libxl__egc *egc,
|
||||
libxl__dm_resume_state *dmrs,
|
||||
bool suspend_cancel);
|
||||
|
||||
/* returns 0 or 1, or a libxl error code */
|
||||
_hidden int libxl__domain_pvcontrol_available(libxl__gc *gc, uint32_t domid);
|
||||
|
||||
|
||||