diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index f711cfc750..2555e9cd3b 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -1239,6 +1239,8 @@ void libxl_mac_copy(libxl_ctx *ctx, libxl_mac *dst, const libxl_mac *src); * libxl_set_vcpuonline() * libxl_retrieve_domain_configuration() * libxl_qemu_monitor_command() + * libxl_domain_shutdown() + * libxl_domain_reboot() */ #define LIBXL_HAVE_FN_USING_QMP_ASYNC 1 @@ -1628,8 +1630,27 @@ int libxl_domain_remus_start(libxl_ctx *ctx, libxl_domain_remus_info *info, const libxl_asyncop_how *ao_how) LIBXL_EXTERNAL_CALLERS_ONLY; -int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid); -int libxl_domain_reboot(libxl_ctx *ctx, uint32_t domid); +int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid, + const libxl_asyncop_how *ao_how) + LIBXL_EXTERNAL_CALLERS_ONLY; +int libxl_domain_reboot(libxl_ctx *ctx, uint32_t domid, + const libxl_asyncop_how *ao_how) + LIBXL_EXTERNAL_CALLERS_ONLY; +#if defined(LIBXL_API_VERSION) && LIBXL_API_VERSION < 0x041300 +static inline int libxl_domain_shutdown_0x041200(libxl_ctx *ctx, + uint32_t domid) +{ + return libxl_domain_shutdown(ctx, domid, NULL); +} +#define libxl_domain_shutdown libxl_domain_shutdown_0x041200 +static inline int libxl_domain_reboot_0x041200(libxl_ctx *ctx, + uint32_t domid) +{ + return libxl_domain_reboot(ctx, domid, NULL); +} +#define libxl_domain_reboot libxl_domain_reboot_0x041200 +#endif + int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid, const libxl_asyncop_how *ao_how) LIBXL_EXTERNAL_CALLERS_ONLY; diff --git a/tools/libxl/libxl_dom_suspend.c b/tools/libxl/libxl_dom_suspend.c index 9bb2d00bec..248dbc33e3 100644 --- a/tools/libxl/libxl_dom_suspend.c +++ b/tools/libxl/libxl_dom_suspend.c @@ -193,16 +193,11 @@ static void domain_suspend_callback_common(libxl__egc *egc, LOGD(DEBUG, domid, "issuing %s suspend request via XenBus control node", dsps->type != LIBXL_DOMAIN_TYPE_PV ? "PVH/HVM" : "PV"); - libxl__domain_pvcontrol_write(gc, XBT_NULL, domid, "suspend"); - - dsps->pvcontrol.path = libxl__domain_pvcontrol_xspath(gc, domid); - if (!dsps->pvcontrol.path) { rc = ERROR_FAIL; goto err; } - dsps->pvcontrol.ao = ao; - dsps->pvcontrol.what = "guest acknowledgement of suspend request"; - dsps->pvcontrol.timeout_ms = 60 * 1000; dsps->pvcontrol.callback = domain_suspend_common_pvcontrol_suspending; - libxl__xswait_start(gc, &dsps->pvcontrol); + rc = libxl__domain_pvcontrol(egc, &dsps->pvcontrol, domid, "suspend"); + if (rc) goto err; + return; err: diff --git a/tools/libxl/libxl_domain.c b/tools/libxl/libxl_domain.c index 0dd5b7ffa9..9d0eb5aed1 100644 --- a/tools/libxl/libxl_domain.c +++ b/tools/libxl/libxl_domain.c @@ -763,49 +763,91 @@ char * libxl__domain_pvcontrol_read(libxl__gc *gc, xs_transaction_t t, return libxl__xs_read(gc, t, shutdown_path); } -int libxl__domain_pvcontrol_write(libxl__gc *gc, xs_transaction_t t, - uint32_t domid, const char *cmd) +int libxl__domain_pvcontrol(libxl__egc *egc, libxl__xswait_state *pvcontrol, + domid_t domid, const char *cmd) { + STATE_AO_GC(pvcontrol->ao); const char *shutdown_path; + int rc; + + rc = libxl__domain_pvcontrol_available(gc, domid); + if (rc < 0) + return rc; shutdown_path = libxl__domain_pvcontrol_xspath(gc, domid); if (!shutdown_path) return ERROR_FAIL; - return libxl__xs_printf(gc, t, shutdown_path, "%s", cmd); + rc = libxl__xs_printf(gc, XBT_NULL, shutdown_path, "%s", cmd); + if (rc) + return rc; + + pvcontrol->path = shutdown_path; + pvcontrol->what = GCSPRINTF("guest acknowledgement of %s request", cmd); + pvcontrol->timeout_ms = 60 * 1000; + rc = libxl__xswait_start(gc, pvcontrol); + if (rc) + return rc; + + return 0; } -static int libxl__domain_pvcontrol(libxl__gc *gc, uint32_t domid, - const char *cmd) +static bool pvcontrol_acked(const char *state) { - int ret; + if (!state || !strcmp(state,"")) + return true; - ret = libxl__domain_pvcontrol_available(gc, domid); - if (ret < 0) - return ret; - - if (!ret) - return ERROR_NOPARAVIRT; - - return libxl__domain_pvcontrol_write(gc, XBT_NULL, domid, cmd); + return false; } -int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid) +/* Xenstore watch callback prototype for the reboot/poweroff operations. */ +static void pvcontrol_cb(libxl__egc *egc, libxl__xswait_state *xswa, int rc, + const char *state); + +int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid, + const libxl_asyncop_how *ao_how) { - GC_INIT(ctx); - int ret; - ret = libxl__domain_pvcontrol(gc, domid, "poweroff"); - GC_FREE; - return ret; + AO_CREATE(ctx, domid, ao_how); + libxl__xswait_state *pvcontrol; + int rc; + + GCNEW(pvcontrol); + pvcontrol->ao = ao; + pvcontrol->callback = pvcontrol_cb; + rc = libxl__domain_pvcontrol(egc, pvcontrol, domid, "poweroff"); + + return rc ? AO_CREATE_FAIL(rc) : AO_INPROGRESS; } -int libxl_domain_reboot(libxl_ctx *ctx, uint32_t domid) +int libxl_domain_reboot(libxl_ctx *ctx, uint32_t domid, + const libxl_asyncop_how *ao_how) { - GC_INIT(ctx); - int ret; - ret = libxl__domain_pvcontrol(gc, domid, "reboot"); - GC_FREE; - return ret; + AO_CREATE(ctx, domid, ao_how); + libxl__xswait_state *pvcontrol; + int rc; + + GCNEW(pvcontrol); + pvcontrol->ao = ao; + pvcontrol->callback = pvcontrol_cb; + rc = libxl__domain_pvcontrol(egc, pvcontrol, domid, "reboot"); + + return rc ? AO_CREATE_FAIL(rc) : AO_INPROGRESS; +} + +static void pvcontrol_cb(libxl__egc *egc, libxl__xswait_state *xswa, int rc, + const char *state) +{ + STATE_AO_GC(xswa->ao); + + if (!rc && !pvcontrol_acked(state)) + return; + + libxl__xswait_stop(gc, xswa); + + if (rc) + LOG(ERROR, "guest didn't acknowledge control request: %d", rc); + + libxl__ao_complete(egc, ao, rc); } static void domain_death_occurred(libxl__egc *egc, diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index bfeb38e0ed..d2d5af746b 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -1378,8 +1378,6 @@ _hidden int libxl__domain_pvcontrol_available(libxl__gc *gc, uint32_t domid); _hidden const char *libxl__domain_pvcontrol_xspath(libxl__gc*, uint32_t domid); _hidden char * libxl__domain_pvcontrol_read(libxl__gc *gc, xs_transaction_t t, uint32_t domid); -_hidden int libxl__domain_pvcontrol_write(libxl__gc *gc, xs_transaction_t t, - uint32_t domid, const char *cmd); /* from xl_device */ _hidden char *libxl__device_disk_string_of_backend(libxl_disk_backend backend); @@ -4719,6 +4717,11 @@ _hidden void libxl__ev_devlock_init(libxl__ev_devlock *); _hidden void libxl__ev_devlock_lock(libxl__egc *, libxl__ev_devlock *); _hidden void libxl__ev_devlock_unlock(libxl__gc *, libxl__ev_devlock *); +/* Send control commands over xenstore and wait for an Ack. */ +_hidden int libxl__domain_pvcontrol(libxl__egc *egc, + libxl__xswait_state *pvcontrol, + domid_t domid, const char *cmd); + #endif /* diff --git a/tools/ocaml/libs/xl/xenlight.ml.in b/tools/ocaml/libs/xl/xenlight.ml.in index 954e56fc74..6989bb6638 100644 --- a/tools/ocaml/libs/xl/xenlight.ml.in +++ b/tools/ocaml/libs/xl/xenlight.ml.in @@ -37,8 +37,8 @@ module Domain = struct external create_new : ctx -> Domain_config.t -> ?async:'a -> unit -> domid = "stub_libxl_domain_create_new" external create_restore : ctx -> Domain_config.t -> (Unix.file_descr * Domain_restore_params.t) -> ?async:'a -> unit -> domid = "stub_libxl_domain_create_restore" - external shutdown : ctx -> domid -> unit = "stub_libxl_domain_shutdown" - external reboot : ctx -> domid -> unit = "stub_libxl_domain_reboot" + external shutdown : ctx -> domid -> ?async:'a -> unit -> unit = "stub_libxl_domain_shutdown" + external reboot : ctx -> domid -> ?async:'a -> unit -> unit = "stub_libxl_domain_reboot" external destroy : ctx -> domid -> ?async:'a -> unit -> unit = "stub_libxl_domain_destroy" external suspend : ctx -> domid -> Unix.file_descr -> ?async:'a -> unit -> unit = "stub_libxl_domain_suspend" external pause : ctx -> domid -> ?async:'a -> unit = "stub_libxl_domain_pause" diff --git a/tools/ocaml/libs/xl/xenlight.mli.in b/tools/ocaml/libs/xl/xenlight.mli.in index c08304ae8b..b98a3db7e7 100644 --- a/tools/ocaml/libs/xl/xenlight.mli.in +++ b/tools/ocaml/libs/xl/xenlight.mli.in @@ -39,8 +39,8 @@ module Domain : sig external create_new : ctx -> Domain_config.t -> ?async:'a -> unit -> domid = "stub_libxl_domain_create_new" external create_restore : ctx -> Domain_config.t -> (Unix.file_descr * Domain_restore_params.t) -> ?async:'a -> unit -> domid = "stub_libxl_domain_create_restore" - external shutdown : ctx -> domid -> unit = "stub_libxl_domain_shutdown" - external reboot : ctx -> domid -> unit = "stub_libxl_domain_reboot" + external shutdown : ctx -> domid -> ?async:'a -> unit -> unit = "stub_libxl_domain_shutdown" + external reboot : ctx -> domid -> ?async:'a -> unit -> unit = "stub_libxl_domain_reboot" external destroy : ctx -> domid -> ?async:'a -> unit -> unit = "stub_libxl_domain_destroy" external suspend : ctx -> domid -> Unix.file_descr -> ?async:'a -> unit -> unit = "stub_libxl_domain_suspend" external pause : ctx -> domid -> ?async:'a -> unit = "stub_libxl_domain_pause" diff --git a/tools/ocaml/libs/xl/xenlight_stubs.c b/tools/ocaml/libs/xl/xenlight_stubs.c index 37b046df63..ff16b8710b 100644 --- a/tools/ocaml/libs/xl/xenlight_stubs.c +++ b/tools/ocaml/libs/xl/xenlight_stubs.c @@ -551,32 +551,38 @@ value stub_libxl_domain_create_restore(value ctx, value domain_config, value par CAMLreturn(Val_int(c_domid)); } -value stub_libxl_domain_shutdown(value ctx, value domid) +value stub_libxl_domain_shutdown(value ctx, value domid, value async, value unit) { - CAMLparam2(ctx, domid); + CAMLparam4(ctx, domid, async, unit); int ret; uint32_t c_domid = Int_val(domid); + libxl_asyncop_how *ao_how = aohow_val(async); caml_enter_blocking_section(); - ret = libxl_domain_shutdown(CTX, c_domid); + ret = libxl_domain_shutdown(CTX, c_domid, ao_how); caml_leave_blocking_section(); + free(ao_how); + if (ret != 0) failwith_xl(ret, "domain_shutdown"); CAMLreturn(Val_unit); } -value stub_libxl_domain_reboot(value ctx, value domid) +value stub_libxl_domain_reboot(value ctx, value domid, value async, value unit) { - CAMLparam2(ctx, domid); + CAMLparam4(ctx, domid, async, unit); int ret; uint32_t c_domid = Int_val(domid); + libxl_asyncop_how *ao_how = aohow_val(async); caml_enter_blocking_section(); - ret = libxl_domain_reboot(CTX, c_domid); + ret = libxl_domain_reboot(CTX, c_domid, ao_how); caml_leave_blocking_section(); + free(ao_how); + if (ret != 0) failwith_xl(ret, "domain_reboot"); diff --git a/tools/xl/xl_vmcontrol.c b/tools/xl/xl_vmcontrol.c index eb6779a561..b20582e15b 100644 --- a/tools/xl/xl_vmcontrol.c +++ b/tools/xl/xl_vmcontrol.c @@ -103,7 +103,7 @@ static void reboot_domain(uint32_t domid, libxl_evgen_domain_death **deathw, int rc; fprintf(stderr, "Rebooting domain %u\n", domid); - rc=libxl_domain_reboot(ctx, domid); + rc = libxl_domain_reboot(ctx, domid, NULL); if (rc == ERROR_NOPARAVIRT) { if (fallback_trigger) { fprintf(stderr, "PV control interface not available:" @@ -136,7 +136,7 @@ static void shutdown_domain(uint32_t domid, int rc; fprintf(stderr, "Shutting down domain %u\n", domid); - rc=libxl_domain_shutdown(ctx, domid); + rc = libxl_domain_shutdown(ctx, domid, NULL); if (rc == ERROR_NOPARAVIRT) { if (fallback_trigger) { fprintf(stderr, "PV control interface not available:"