]> xenbits.xensource.com Git - people/larsk/xen.git/commitdiff
libxl: wait for the ack when issuing power control requests
authorRoger Pau Monne <roger.pau@citrix.com>
Tue, 1 Oct 2019 15:22:33 +0000 (17:22 +0200)
committerWei Liu <wl@xen.org>
Wed, 2 Oct 2019 13:43:19 +0000 (14:43 +0100)
Currently only suspend power control requests wait for an ack from the
domain, while power off or reboot requests simply write the command to
xenstore and exit.

Introduce a 1 minute wait for the domain to acknowledge the request, or
else return an error. The suspend code is slightly modified to use the
new infrastructure added, but shouldn't have any functional change.

Fix the ocaml bindings and also provide a backwards compatible
interface for the reboot and poweroff libxl API functions.

Reported-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Signed-off-by: Roger Pau Monné <roger.pau@citrix.com>
Reviewed-by: Anthony PERARD <anthony.perard@citrix.com>
Release-acked-by: Juergen Gross <jgross@suse.com>
Acked-by: Christian Lindig <christian.lindig@citrix.com>
[ wei: change ret to rc to fix build ]
Signed-off-by: Wei Liu <wl@xen.org>
tools/libxl/libxl.h
tools/libxl/libxl_dom_suspend.c
tools/libxl/libxl_domain.c
tools/libxl/libxl_internal.h
tools/ocaml/libs/xl/xenlight.ml.in
tools/ocaml/libs/xl/xenlight.mli.in
tools/ocaml/libs/xl/xenlight_stubs.c
tools/xl/xl_vmcontrol.c

index f711cfc750fa7c0dd8463fe88827a46b543f01a2..2555e9cd3b01e036ff6c58d618334ec49fd63527 100644 (file)
@@ -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;
index 9bb2d00bec9ae1dce6c5a24266d563aff5a7b126..248dbc33e384ae008e4ab9ce8fb573be06dddd72 100644 (file)
@@ -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:
index 0dd5b7ffa963d44f2980903062485de8020bfa01..9d0eb5aed11d75df5827320c6776fc5f578cb250 100644 (file)
@@ -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;
+    return false;
+}
 
-    if (!ret)
-        return ERROR_NOPARAVIRT;
+/* 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);
 
-    return libxl__domain_pvcontrol_write(gc, XBT_NULL, domid, cmd);
+int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid,
+                          const libxl_asyncop_how *ao_how)
+{
+    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_shutdown(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, "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, "reboot");
+
+    return rc ? AO_CREATE_FAIL(rc) : AO_INPROGRESS;
 }
 
-int libxl_domain_reboot(libxl_ctx *ctx, uint32_t domid)
+static void pvcontrol_cb(libxl__egc *egc, libxl__xswait_state *xswa, int rc,
+                         const char *state)
 {
-    GC_INIT(ctx);
-    int ret;
-    ret = libxl__domain_pvcontrol(gc, domid, "reboot");
-    GC_FREE;
-    return ret;
+    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,
index bfeb38e0eda3a47d8b05270c3eb8d1f5195c1891..d2d5af746b5052f1ee3952f1338c246f3d3f0293 100644 (file)
@@ -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
 
 /*
index 954e56fc740b1018e9881a9241b17edfedd8b02c..6989bb6638cd2c6576efc70ae6c54766a6ef3306 100644 (file)
@@ -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"
index c08304ae8b01def6420778c20de692b3808dbad9..b98a3db7e777111505e647400dc3b5e5497e0b78 100644 (file)
@@ -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"
index 37b046df6351309fe285266c32d2ff849eb09ad8..ff16b8710ba6d1538328a12b5e8636df58180035 100644 (file)
@@ -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");
 
index eb6779a561976427c4ebba913ab77e2ca0b87994..b20582e15b9db13d773c34a7549b61d751a40163 100644 (file)
@@ -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:"