|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 15/19] libxl: suspend: Async xenstore pvcontrol wait
On Tue, 2014-03-04 at 14:56 +0000, Ian Jackson wrote:
> 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>
> ---
> tools/libxl/libxl_dom.c | 93
> ++++++++++++++++++++++++++----------------
> tools/libxl/libxl_internal.h | 1 +
> 2 files changed, 59 insertions(+), 35 deletions(-)
>
> diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
> index 8aceba9..dde7e33 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,81 @@ 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))
> + 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.
This behaviour has gone completely now?
> - */
> - 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);
Is this right/proper in the success case?
If rc != TIMEOUT t may not have been started, although it is initialised
so I suppose this is intended to be ok.
> 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 +1235,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 +1422,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 97dbd8e..5ac02cb 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -2422,6 +2422,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;
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |