[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 18/22] libxl: suspend: Async xenstore pvcontrol wait
When negotiating guest suspend via the xenstore pvcontrol protocol (ie when the guest does NOT support the evtchn fast suspend protocol): Replace the use of loops and usleep with a call to libxl__xswait. Also, replace the xenstore transaction loop with one using libxl__xs_transaction_start et al. There is not intended to be any semantic change, other than to make the algorithm properly asynchronous. Signed-off-by: Ian Jackson <Ian.Jackson@xxxxxxxxxxxxx> CC: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx> CC: Ian Campbell <ian.campbell@xxxxxxxxxx> --- v3: Add a comment to clarify last minute ack. v3X: Do NOT rename "pvcontrol" xswait state struct to "guest_wait" (because we're NOT going to use it for the event channel based wait too). --- tools/libxl/libxl_dom.c | 94 ++++++++++++++++++++++++++---------------- tools/libxl/libxl_internal.h | 1 + 2 files changed, 60 insertions(+), 35 deletions(-) diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c index 9fec4e7..0c48159 100644 --- a/tools/libxl/libxl_dom.c +++ b/tools/libxl/libxl_dom.c @@ -1028,6 +1028,8 @@ 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_failed(libxl__egc *egc, libxl__domain_suspend_state *dss); static void domain_suspend_common_done(libxl__egc *egc, @@ -1047,10 +1049,6 @@ static void domain_suspend_callback_common(libxl__egc *egc, STATE_AO_GC(dss->ao); unsigned long hvm_s_state = 0, hvm_pvdrv = 0; int ret; - char *state = "suspend"; - int watchdog; - xs_transaction_t t; - int rc; /* Convenience aliases */ const uint32_t domid = dss->domid; @@ -1096,59 +1094,82 @@ static void domain_suspend_callback_common(libxl__egc *egc, libxl__domain_pvcontrol_write(gc, XBT_NULL, domid, "suspend"); - LOG(DEBUG, "wait for the guest to acknowledge suspend request"); - watchdog = 60; - while (!domain_suspend_pvcontrol_acked(state) && watchdog > 0) { - usleep(100000); + dss->pvcontrol.path = libxl__domain_pvcontrol_xspath(gc, domid); + if (!dss->pvcontrol.path) goto err; - state = libxl__domain_pvcontrol_read(gc, XBT_NULL, domid); + 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; - watchdog--; - } + err: + domain_suspend_common_failed(egc, dss); +} - /* - * 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. - */ - if (!domain_suspend_pvcontrol_acked(state)) { - LOG(ERROR, "guest didn't acknowledge suspend, cancelling request"); +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; - state = libxl__domain_pvcontrol_read(gc, t, domid); + rc = libxl__xs_read_checked(gc, t, xswa->path, &state); + if (rc) goto err; + + if (domain_suspend_pvcontrol_acked(state)) + /* last minute ack */ + break; - if (!domain_suspend_pvcontrol_acked(state)) - libxl__domain_pvcontrol_write(gc, t, domid, ""); + rc = libxl__xs_write_checked(gc, t, xswa->path, ""); + if (rc) goto err; rc = libxl__xs_transaction_commit(gc, &t); - if (!rc) break; + if (!rc) { + LOG(ERROR, + "guest didn't acknowledge suspend, cancelling request"); + goto err; + } if (rc<0) goto err; } - } - - /* - * Final check for guest acknowledgement. The guest may have - * acknowledged while we were cancelling the request in which - * case we lost the race while cancelling and should continue. - */ - if (!domain_suspend_pvcontrol_acked(state)) { - LOG(ERROR, "guest didn't acknowledge suspend, request cancelled"); + } 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, @@ -1215,6 +1236,8 @@ static void domain_suspend_common_done(libxl__egc *egc, libxl__domain_suspend_state *dss, bool ok) { + EGC_GC; + assert(!libxl__xswait_inuse(&dss->pvcontrol)); dss->callback_common_done(egc, dss, ok); } @@ -1400,6 +1423,7 @@ void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss) &dss->shs.callbacks.save.a; logdirty_init(&dss->logdirty); + libxl__xswait_init(&dss->pvcontrol); switch (type) { case LIBXL_DOMAIN_TYPE_HVM: { diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 9ec0d0b..479edb7 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -2444,6 +2444,7 @@ struct libxl__domain_suspend_state { int hvm; int xcflags; int guest_responded; + libxl__xswait_state pvcontrol; const char *dm_savefile; int interval; /* checkpoint interval (for Remus) */ libxl__save_helper_state shs; -- 1.7.10.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |