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:
Anthony PERARD authored and Ian Jackson committed 2019-09-20 10:42:42 +01:00
1 parent b215f2ab6a
commit 6298f0eb8f
2 files changed
+219

No files matched your search

+192
View File
@@ -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
+27
View File
@@ -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);
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.