From: Ian Jackson <ian.jackson@eu.citrix.com>
To: xen-devel@lists.xensource.com
Cc: Shriram Rajagopalan <rshriram@cs.ubc.ca>,
George Dunlap <George.Dunlap@eu.citrix.com>,
Ian Jackson <Ian.Jackson@eu.citrix.com>,
Ian Campbell <ian.campbell@citrix.com>,
Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Subject: [PATCH 22/23] libxl: suspend: Async evtchn wait
Date: Tue, 17 Dec 2013 18:35:36 +0000 [thread overview]
Message-ID: <1387305337-15355-23-git-send-email-ian.jackson@eu.citrix.com> (raw)
In-Reply-To: <1387305337-15355-1-git-send-email-ian.jackson@eu.citrix.com>
When negotiating guest suspend via the evtchn ("fast") protocol,
abolish synchronous wait for domain suspend.
If the guest supports the event channel suspend protocol, we used to
sit in a loop waiting for it to suspend.
Instead, use the new libxl event channel event facility. When we see
that the event is signaled, we look at the domain to see if it has
suspended.
So the suspend operation no longer blocks with the libxl ctx lock
held, and instead returns to the event loop. Additionally, domains
which signal the event channel themselves, or undergo other state
changes, will be handled more correctly.
We end up making a few more hypercalls.
Also, if we encounter errors setting up the suspend event channel
(which should not happen), abort the operation rather than falling
back to the xenstore protocol.
Signed-off-by: Ian Jackson <Ian.Jackson@eu.citrix.com>
CC: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
CC: Ian Campbell <ian.campbell@citrix.com>
---
tools/libxl/libxl_dom.c | 78 ++++++++++++++++++++++++++----------------
tools/libxl/libxl_internal.h | 3 +-
2 files changed, 50 insertions(+), 31 deletions(-)
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index 88700ee..c431a2d 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -1031,8 +1031,12 @@ static void domain_suspend_common_guest_suspended(libxl__egc *egc,
static void domain_suspend_common_pvcontrol_suspending(libxl__egc *egc,
libxl__xswait_state *xswa, int rc, const char *state);
+static void domain_suspend_common_wait_guest_evtchn(libxl__egc *egc,
+ libxl__ev_evtchn *evev);
static void suspend_common_wait_guest_watch(libxl__egc *egc,
libxl__ev_xswatch *xsw, const char *watch_path, const char *event_path);
+static void suspend_common_wait_guest_check(libxl__egc *egc,
+ libxl__domain_suspend_state *dss);
static void suspend_common_wait_guest_timeout(libxl__egc *egc,
libxl__ev_time *ev, const struct timeval *requested_abs);
@@ -1054,7 +1058,7 @@ 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;
+ int ret, rc;
/* Convenience aliases */
const uint32_t domid = dss->domid;
@@ -1064,21 +1068,19 @@ static void domain_suspend_callback_common(libxl__egc *egc,
xc_get_hvm_param(CTX->xch, domid, HVM_PARAM_ACPI_S_STATE, &hvm_s_state);
}
- if ((hvm_s_state == 0) && (dss->suspend_eventchn >= 0)) {
+ if ((hvm_s_state == 0) && (dss->guest_evtchn.port >= 0)) {
LOG(DEBUG, "issuing %s suspend request via event channel",
dss->hvm ? "PVHVM" : "PV");
- ret = xc_evtchn_notify(dss->xce, dss->suspend_eventchn);
+ ret = xc_evtchn_notify(CTX->xce, dss->guest_evtchn.port);
if (ret < 0) {
LOG(ERROR, "xc_evtchn_notify failed ret=%d", ret);
goto err;
}
- ret = xc_await_suspend(CTX->xch, dss->xce, dss->suspend_eventchn);
- if (ret < 0) {
- LOG(ERROR, "xc_await_suspend failed ret=%d", ret);
- goto err;
- }
- dss->guest_responded = 1;
- domain_suspend_common_guest_suspended(egc, dss);
+
+ dss->guest_evtchn.callback = domain_suspend_common_wait_guest_evtchn;
+ rc = libxl__ev_evtchn_wait(gc, &dss->guest_evtchn);
+ if (rc) goto err;
+
return;
}
@@ -1114,6 +1116,19 @@ static void domain_suspend_callback_common(libxl__egc *egc,
domain_suspend_common_failed(egc, dss);
}
+static void domain_suspend_common_wait_guest_evtchn(libxl__egc *egc,
+ libxl__ev_evtchn *evev)
+{
+ libxl__domain_suspend_state *dss = CONTAINER_OF(evev, *dss, guest_evtchn);
+ STATE_AO_GC(dss->ao);
+ /* If we should be done waiting, suspend_common_wait_guest_check
+ * will end up calling domain_suspend_common_guest_suspended or
+ * domain_suspend_common_failed, both of which cancel the evtchn
+ * wait. So re-enable it now. */
+ libxl__ev_evtchn_wait(gc, &dss->guest_evtchn);
+ suspend_common_wait_guest_check(egc, dss);
+}
+
static void domain_suspend_common_pvcontrol_suspending(libxl__egc *egc,
libxl__xswait_state *xswa, int rc, const char *state)
{
@@ -1203,8 +1218,13 @@ static void domain_suspend_common_wait_guest(libxl__egc *egc,
static void suspend_common_wait_guest_watch(libxl__egc *egc,
libxl__ev_xswatch *xsw, const char *watch_path, const char *event_path)
{
- libxl__domain_suspend_state *dss =
- CONTAINER_OF(xsw, *dss, guest_watch);
+ libxl__domain_suspend_state *dss = CONTAINER_OF(xsw, *dss, guest_watch);
+ suspend_common_wait_guest_check(egc, dss);
+}
+
+static void suspend_common_wait_guest_check(libxl__egc *egc,
+ libxl__domain_suspend_state *dss)
+{
STATE_AO_GC(dss->ao);
xc_domaininfo_t info;
int ret;
@@ -1261,6 +1281,7 @@ static void domain_suspend_common_guest_suspended(libxl__egc *egc,
STATE_AO_GC(dss->ao);
int ret;
+ libxl__ev_evtchn_cancel(gc, &dss->guest_evtchn);
libxl__ev_xswatch_deregister(gc, &dss->guest_watch);
libxl__ev_time_deregister(gc, &dss->guest_timeout);
@@ -1287,6 +1308,7 @@ static void domain_suspend_common_done(libxl__egc *egc,
{
EGC_GC;
assert(!libxl__xswait_inuse(&dss->pvcontrol));
+ libxl__ev_evtchn_cancel(gc, &dss->guest_evtchn);
libxl__ev_xswatch_deregister(gc, &dss->guest_watch);
libxl__ev_time_deregister(gc, &dss->guest_timeout);
dss->callback_common_done(egc, dss, ok);
@@ -1475,6 +1497,7 @@ void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss)
logdirty_init(&dss->logdirty);
libxl__xswait_init(&dss->pvcontrol);
+ libxl__ev_evtchn_init(&dss->guest_evtchn);
libxl__ev_xswatch_init(&dss->guest_watch);
libxl__ev_time_init(&dss->guest_timeout);
@@ -1503,7 +1526,7 @@ void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss)
| (debug ? XCFLAGS_DEBUG : 0)
| (dss->hvm ? XCFLAGS_HVM : 0);
- dss->suspend_eventchn = -1;
+ dss->guest_evtchn.port = -1;
dss->guest_evtchn_lockfd = -1;
dss->guest_responded = 0;
dss->dm_savefile = libxl__device_model_savefile(gc, domid);
@@ -1514,20 +1537,17 @@ void libxl__domain_suspend(libxl__egc *egc, libxl__domain_suspend_state *dss)
dss->xcflags |= XCFLAGS_CHECKPOINT_COMPRESS;
}
- dss->xce = xc_evtchn_open(NULL, 0);
- if (dss->xce == NULL)
- goto out;
- else
- {
- port = xs_suspend_evtchn_port(dss->domid);
+ port = xs_suspend_evtchn_port(dss->domid);
- if (port >= 0) {
- dss->suspend_eventchn =
- xc_suspend_evtchn_init_exclusive(CTX->xch, dss->xce,
+ if (port >= 0) {
+ dss->guest_evtchn.port =
+ xc_suspend_evtchn_init_exclusive(CTX->xch, CTX->xce,
dss->domid, port, &dss->guest_evtchn_lockfd);
- if (dss->suspend_eventchn < 0)
- LOG(WARN, "Suspend event channel initialization failed");
+ if (dss->guest_evtchn.port < 0) {
+ LOG(WARN, "Suspend event channel initialization failed");
+ rc = ERROR_FAIL;
+ goto out;
}
}
@@ -1686,11 +1706,11 @@ static void domain_suspend_done(libxl__egc *egc,
/* Convenience aliases */
const uint32_t domid = dss->domid;
- if (dss->suspend_eventchn > 0)
- xc_suspend_evtchn_release(CTX->xch, dss->xce, domid,
- dss->suspend_eventchn, &dss->guest_evtchn_lockfd);
- if (dss->xce != NULL)
- xc_evtchn_close(dss->xce);
+ libxl__ev_evtchn_cancel(gc, &dss->guest_evtchn);
+
+ if (dss->guest_evtchn.port > 0)
+ xc_suspend_evtchn_release(CTX->xch, CTX->xce, domid,
+ dss->guest_evtchn.port, &dss->guest_evtchn_lockfd);
dss->callback(egc, dss, rc);
}
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index d428e77..126e5bf 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -2404,8 +2404,7 @@ struct libxl__domain_suspend_state {
int debug;
const libxl_domain_remus_info *remus;
/* private */
- xc_evtchn *xce; /* event channel handle */
- int suspend_eventchn;
+ libxl__ev_evtchn guest_evtchn;
int guest_evtchn_lockfd;
int hvm;
int xcflags;
--
1.7.10.4
next prev parent reply other threads:[~2013-12-17 18:35 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-12-17 18:35 (no subject) Ian Jackson
2013-12-17 18:35 ` [PATCH 01/23] xen: Document XEN_DOMCTL_subscribe Ian Jackson
2013-12-17 18:35 ` [PATCH 02/23] xen: Document that EVTCHNOP_bind_interdomain signals Ian Jackson
2013-12-17 18:35 ` [PATCH 03/23] docs: Document event-channel-based suspend protocol Ian Jackson
2013-12-17 18:35 ` [PATCH 04/23] libxc: Document xenctrl.h event channel calls Ian Jackson
2013-12-17 18:35 ` [PATCH 05/23] libxl: init: Provide a gc later in libxl_ctx_alloc Ian Jackson
2013-12-19 12:51 ` Ian Campbell
2013-12-19 17:26 ` Ian Jackson
2013-12-17 18:35 ` [PATCH 06/23] libxl: init: libxl__poller_init and _get take gc Ian Jackson
2013-12-19 13:00 ` Ian Campbell
2013-12-19 17:27 ` Ian Jackson
2013-12-17 18:35 ` [PATCH 07/23] libxl: events: const-correct *_inuse, *_isregistered Ian Jackson
2013-12-19 13:01 ` Ian Campbell
2013-12-17 18:35 ` [PATCH 08/23] libxl: events: Provide libxl__xswait_* Ian Jackson
2013-12-19 13:05 ` Ian Campbell
2013-12-19 17:30 ` Ian Jackson
2013-12-17 18:35 ` [PATCH 09/23] libxl: events: Use libxl__xswait_* in spawn code Ian Jackson
2013-12-19 13:33 ` Ian Campbell
2013-12-17 18:35 ` [PATCH 10/23] libxl: events: Provide libxl__ev_evtchn* Ian Jackson
2013-12-19 13:43 ` Ian Campbell
2013-12-19 17:47 ` Ian Jackson
2013-12-19 17:51 ` Ian Campbell
2013-12-20 11:52 ` Ian Jackson
2013-12-17 18:35 ` [PATCH 11/23] libxc: suspend: Rename, improve xc_suspend_evtchn_init Ian Jackson
2014-03-13 16:05 ` Ian Campbell
2013-12-17 18:35 ` [PATCH 12/23] libxc: suspend: Fix suspend event channel locking Ian Jackson
2013-12-17 18:35 ` [PATCH 13/23] libxl: suspend: Async libxl__domain_suspend_callback Ian Jackson
2013-12-17 18:35 ` [PATCH 14/23] libxl: suspend: Async domain_suspend_callback_common Ian Jackson
2013-12-17 18:35 ` [PATCH 15/23] libxl: suspend: Reorg domain_suspend_callback_common Ian Jackson
2013-12-17 18:35 ` [PATCH 16/23] libxl: suspend: New libxl__domain_pvcontrol_xspath Ian Jackson
2013-12-17 18:35 ` [PATCH 17/23] libxl: suspend: New domain_suspend_pvcontrol_acked Ian Jackson
2013-12-17 18:35 ` [PATCH 18/23] libxl: suspend: domain_suspend_callback_common xs errs Ian Jackson
2013-12-17 18:35 ` [PATCH 19/23] libxl: suspend: Async xenstore pvcontrol wait Ian Jackson
2013-12-17 18:35 ` [PATCH 20/23] libxl: suspend: Abolish usleeps in domain suspend wait Ian Jackson
2013-12-17 18:35 ` [PATCH 21/23] libxl: suspend: Fix suspend wait corner cases Ian Jackson
2013-12-17 18:35 ` Ian Jackson [this message]
2013-12-17 18:35 ` [PATCH 23/23] libxl: suspend: Apply guest timeout in evtchn case Ian Jackson
2013-12-18 11:19 ` (no subject) George Dunlap
2013-12-18 13:35 ` Ian Campbell
2014-01-07 13:55 ` Ian Campbell
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1387305337-15355-23-git-send-email-ian.jackson@eu.citrix.com \
--to=ian.jackson@eu.citrix.com \
--cc=George.Dunlap@eu.citrix.com \
--cc=ian.campbell@citrix.com \
--cc=rshriram@cs.ubc.ca \
--cc=stefano.stabellini@eu.citrix.com \
--cc=xen-devel@lists.xensource.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).