From: Yang Hongyang <yanghy@cn.fujitsu.com>
To: xen-devel@lists.xen.org
Cc: ian.campbell@citrix.com, wency@cn.fujitsu.com,
stefano.stabellini@eu.citrix.com, andrew.cooper3@citrix.com,
yunhong.jiang@intel.com, ian.jackson@eu.citrix.com,
eddie.dong@intel.com, rshriram@cs.ubc.ca, roger.pau@citrix.com,
laijs@cn.fujitsu.com
Subject: [PATCH v10 1/5] libxl: introduce asynchronous execution API
Date: Thu, 5 Jun 2014 09:34:25 +0800 [thread overview]
Message-ID: <1401932069-16460-2-git-send-email-yanghy@cn.fujitsu.com> (raw)
In-Reply-To: <1401932069-16460-1-git-send-email-yanghy@cn.fujitsu.com>
1.introduce asynchronous execution API:
libxl__async_exec_init
libxl__async_exec_start
libxl__async_exec_inuse
2.use the async exec API to execute device hotplug scripts
Signed-off-by: Lai Jiangshan <laijs@cn.fujitsu.com>
Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Yang Hongyang <yanghy@cn.fujitsu.com>
Acked-by: Roger Pau Monné <roger.pau@citrix.com
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
---
tools/libxl/libxl_aoutils.c | 89 ++++++++++++++++++++++++++++++++++++++++++++
tools/libxl/libxl_device.c | 78 +++++++++++---------------------------
tools/libxl/libxl_internal.h | 34 +++++++++++++++--
3 files changed, 141 insertions(+), 60 deletions(-)
diff --git a/tools/libxl/libxl_aoutils.c b/tools/libxl/libxl_aoutils.c
index 1c9eb9e..b10d2e1 100644
--- a/tools/libxl/libxl_aoutils.c
+++ b/tools/libxl/libxl_aoutils.c
@@ -451,3 +451,92 @@ int libxl__openptys(libxl__openpty_state *op,
return rc;
}
+static void async_exec_timeout(libxl__egc *egc,
+ libxl__ev_time *ev,
+ const struct timeval *requested_abs)
+{
+ libxl__async_exec_state *aes = CONTAINER_OF(ev, *aes, time);
+ STATE_AO_GC(aes->ao);
+
+ libxl__ev_time_deregister(gc, &aes->time);
+
+ assert(libxl__ev_child_inuse(&aes->child));
+ LOG(ERROR, "killing execution of %s because of timeout", aes->what);
+
+ if (kill(aes->child.pid, SIGKILL)) {
+ LOGEV(ERROR, errno, "unable to kill %s [%ld]",
+ aes->what, (unsigned long)aes->child.pid);
+ }
+
+ return;
+}
+
+static void async_exec_done(libxl__egc *egc,
+ libxl__ev_child *child,
+ pid_t pid, int status)
+{
+ libxl__async_exec_state *aes = CONTAINER_OF(child, *aes, child);
+ STATE_AO_GC(aes->ao);
+
+ libxl__ev_time_deregister(gc, &aes->time);
+
+ if (status) {
+ libxl_report_child_exitstatus(CTX, LIBXL__LOG_ERROR,
+ aes->what, pid, status);
+ }
+
+ aes->callback(egc, aes, status);
+}
+
+void libxl__async_exec_init(libxl__async_exec_state *aes)
+{
+ libxl__ev_time_init(&aes->time);
+ libxl__ev_child_init(&aes->child);
+}
+
+int libxl__async_exec_start(libxl__gc *gc, libxl__async_exec_state *aes)
+{
+ pid_t pid;
+
+ /* Convenience aliases */
+ libxl__ev_child *const child = &aes->child;
+ char ** const args = aes->args;
+
+ /* Set execution timeout */
+ if (libxl__ev_time_register_rel(gc, &aes->time,
+ async_exec_timeout,
+ aes->timeout_ms)) {
+ LOG(ERROR, "unable to register timeout for executing: %s", aes->what);
+ goto out;
+ }
+
+ LOG(DEBUG, "forking to execute: %s ", aes->what);
+
+ /* Fork and exec */
+ pid = libxl__ev_child_fork(gc, child, async_exec_done);
+ if (pid == -1) {
+ LOG(ERROR, "unable to fork");
+ goto out;
+ }
+
+ if (!pid) {
+ /* child */
+ libxl__exec(gc, aes->stdfds[0], aes->stdfds[1],
+ aes->stdfds[2], args[0], args, aes->env);
+ /* notreached */
+ abort();
+ }
+
+ return 0;
+
+out:
+ return ERROR_FAIL;
+}
+
+bool libxl__async_exec_inuse(const libxl__async_exec_state *aes)
+{
+ bool time_inuse = libxl__ev_time_isregistered(&aes->time);
+ bool child_inuse = libxl__ev_child_inuse(&aes->child);
+ assert(time_inuse == child_inuse);
+ return child_inuse;
+}
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index fa99f77..90ae564 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -430,7 +430,7 @@ void libxl__prepare_ao_device(libxl__ao *ao, libxl__ao_device *aodev)
aodev->rc = 0;
aodev->dev = NULL;
aodev->num_exec = 0;
- /* Initialize timer for QEMU Bodge and hotplug execution */
+ /* Initialize timer for QEMU Bodge */
libxl__ev_time_init(&aodev->timeout);
/*
* Initialize xs_watch, because it's not used on all possible
@@ -440,7 +440,7 @@ void libxl__prepare_ao_device(libxl__ao *ao, libxl__ao_device *aodev)
aodev->active = 1;
/* We init this here because we might call device_hotplug_done
* without actually calling any hotplug script */
- libxl__ev_child_init(&aodev->child);
+ libxl__async_exec_init(&aodev->aes);
}
/* multidev */
@@ -707,12 +707,9 @@ static void device_backend_cleanup(libxl__gc *gc,
static void device_hotplug(libxl__egc *egc, libxl__ao_device *aodev);
-static void device_hotplug_timeout_cb(libxl__egc *egc, libxl__ev_time *ev,
- const struct timeval *requested_abs);
-
static void device_hotplug_child_death_cb(libxl__egc *egc,
- libxl__ev_child *child,
- pid_t pid, int status);
+ libxl__async_exec_state *aes,
+ int status);
static void device_destroy_be_timeout_cb(libxl__egc *egc, libxl__ev_time *ev,
const struct timeval *requested_abs);
@@ -953,11 +950,11 @@ static void device_backend_cleanup(libxl__gc *gc, libxl__ao_device *aodev)
static void device_hotplug(libxl__egc *egc, libxl__ao_device *aodev)
{
STATE_AO_GC(aodev->ao);
+ libxl__async_exec_state *aes = &aodev->aes;
char *be_path = libxl__device_backend_path(gc, aodev->dev);
char **args = NULL, **env = NULL;
int rc = 0;
int hotplug, nullfd = -1;
- pid_t pid;
uint32_t domid;
/*
@@ -1009,16 +1006,6 @@ static void device_hotplug(libxl__egc *egc, libxl__ao_device *aodev)
goto out;
}
- /* Set hotplug timeout */
- rc = libxl__ev_time_register_rel(gc, &aodev->timeout,
- device_hotplug_timeout_cb,
- LIBXL_HOTPLUG_TIMEOUT * 1000);
- if (rc) {
- LOG(ERROR, "unable to register timeout for hotplug device %s", be_path);
- goto out;
- }
-
- aodev->what = GCSPRINTF("%s %s", args[0], args[1]);
LOG(DEBUG, "calling hotplug script: %s %s", args[0], args[1]);
nullfd = open("/dev/null", O_RDONLY);
@@ -1028,23 +1015,22 @@ static void device_hotplug(libxl__egc *egc, libxl__ao_device *aodev)
goto out;
}
- /* fork and execute hotplug script */
- pid = libxl__ev_child_fork(gc, &aodev->child, device_hotplug_child_death_cb);
- if (pid == -1) {
- LOG(ERROR, "unable to fork");
- rc = ERROR_FAIL;
+ aes->ao = ao;
+ aes->what = GCSPRINTF("%s %s", args[0], args[1]);
+ aes->env = env;
+ aes->args = args;
+ aes->callback = device_hotplug_child_death_cb;
+ aes->timeout_ms = LIBXL_HOTPLUG_TIMEOUT * 1000;
+ aes->stdfds[0] = nullfd;
+ aes->stdfds[1] = 2;
+ aes->stdfds[2] = -1;
+
+ rc = libxl__async_exec_start(gc, aes);
+ if (rc)
goto out;
- }
-
- if (!pid) {
- /* child */
- libxl__exec(gc, nullfd, 2, -1, args[0], args, env);
- /* notreached */
- abort();
- }
close(nullfd);
- assert(libxl__ev_child_inuse(&aodev->child));
+ assert(libxl__async_exec_inuse(&aodev->aes));
return;
@@ -1055,29 +1041,11 @@ out:
return;
}
-static void device_hotplug_timeout_cb(libxl__egc *egc, libxl__ev_time *ev,
- const struct timeval *requested_abs)
-{
- libxl__ao_device *aodev = CONTAINER_OF(ev, *aodev, timeout);
- STATE_AO_GC(aodev->ao);
-
- libxl__ev_time_deregister(gc, &aodev->timeout);
-
- assert(libxl__ev_child_inuse(&aodev->child));
- LOG(DEBUG, "killing hotplug script %s because of timeout", aodev->what);
- if (kill(aodev->child.pid, SIGKILL)) {
- LOGEV(ERROR, errno, "unable to kill hotplug script %s [%ld]",
- aodev->what, (unsigned long)aodev->child.pid);
- }
-
- return;
-}
-
static void device_hotplug_child_death_cb(libxl__egc *egc,
- libxl__ev_child *child,
- pid_t pid, int status)
+ libxl__async_exec_state *aes,
+ int status)
{
- libxl__ao_device *aodev = CONTAINER_OF(child, *aodev, child);
+ libxl__ao_device *aodev = CONTAINER_OF(aes, *aodev, aes);
STATE_AO_GC(aodev->ao);
char *be_path = libxl__device_backend_path(gc, aodev->dev);
char *hotplug_error;
@@ -1085,8 +1053,6 @@ static void device_hotplug_child_death_cb(libxl__egc *egc,
device_hotplug_clean(gc, aodev);
if (status) {
- libxl_report_child_exitstatus(CTX, LIBXL__LOG_ERROR,
- aodev->what, pid, status);
hotplug_error = libxl__xs_read(gc, XBT_NULL,
GCSPRINTF("%s/hotplug-error", be_path));
if (hotplug_error)
@@ -1178,7 +1144,7 @@ static void device_hotplug_clean(libxl__gc *gc, libxl__ao_device *aodev)
/* Clean events and check reentrancy */
libxl__ev_time_deregister(gc, &aodev->timeout);
libxl__ev_xswatch_deregister(gc, &aodev->xs_watch);
- assert(!libxl__ev_child_inuse(&aodev->child));
+ assert(!libxl__async_exec_inuse(&aodev->aes));
}
static void devices_remove_callback(libxl__egc *egc,
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 082749e..5968485 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -2050,6 +2050,33 @@ _hidden const char *libxl__xen_script_dir_path(void);
_hidden const char *libxl__lock_dir_path(void);
_hidden const char *libxl__run_dir_path(void);
+/*----- subprocess execution with timeout -----*/
+
+typedef struct libxl__async_exec_state libxl__async_exec_state;
+
+typedef void libxl__async_exec_callback(libxl__egc *egc,
+ libxl__async_exec_state *aes, int status);
+
+struct libxl__async_exec_state {
+ /* caller must fill these in */
+ libxl__ao *ao;
+ const char *what; /* for error msgs, what we're executing */
+ int timeout_ms;
+ libxl__async_exec_callback *callback;
+ /* caller must fill in; as for libxl__exec */
+ int stdfds[3];
+ char **args; /* execution arguments */
+ char **env; /* execution environment */
+
+ /* private */
+ libxl__ev_time time;
+ libxl__ev_child child;
+};
+
+void libxl__async_exec_init(libxl__async_exec_state *aes);
+int libxl__async_exec_start(libxl__gc *gc, libxl__async_exec_state *aes);
+bool libxl__async_exec_inuse(const libxl__async_exec_state *aes);
+
/*----- device addition/removal -----*/
typedef struct libxl__ao_device libxl__ao_device;
@@ -2086,14 +2113,13 @@ struct libxl__ao_device {
libxl__multidev *multidev; /* reference to the containing multidev */
/* private for add/remove implementation */
libxl__ev_devstate backend_ds;
- /* Bodge for Qemu devices, also used for timeout of hotplug execution */
+ /* Bodge for Qemu devices */
libxl__ev_time timeout;
/* xenstore watch for backend path of driver domains */
libxl__ev_xswatch xs_watch;
- /* device hotplug execution */
- const char *what;
int num_exec;
- libxl__ev_child child;
+ /* for calling hotplug scripts */
+ libxl__async_exec_state aes;
};
/*
--
1.9.1
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel
next prev parent reply other threads:[~2014-06-05 1:34 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-06-05 1:34 [PATCH v10 0/5] Remus netbuffer: Network buffering support Yang Hongyang
2014-06-05 1:34 ` Yang Hongyang [this message]
2014-06-05 16:01 ` [PATCH v10 1/5] libxl: introduce asynchronous execution API Ian Jackson
2014-06-05 1:34 ` [PATCH v10 2/5] remus: add libnl3 dependency for network buffering support Yang Hongyang
2014-06-05 16:18 ` Ian Jackson
2014-06-06 1:48 ` Hongyang Yang
2014-06-06 6:45 ` Shriram Rajagopalan
2014-06-06 10:07 ` Ian Campbell
2014-06-06 11:04 ` Ian Jackson
2014-06-05 1:34 ` [PATCH v10 3/5] remus: introduce remus device Yang Hongyang
2014-06-05 17:06 ` Ian Jackson
2014-06-06 1:54 ` Hongyang Yang
2014-06-09 2:08 ` Hongyang Yang
2014-06-05 1:34 ` [PATCH v10 4/5] remus: implement remus network buffering for nic devices Yang Hongyang
2014-06-05 16:50 ` Shriram Rajagopalan
2014-06-05 17:37 ` Ian Jackson
2014-06-05 17:44 ` Ian Jackson
2014-06-05 17:56 ` Shriram Rajagopalan
2014-06-06 2:08 ` Hongyang Yang
2014-06-06 1:59 ` Hongyang Yang
2014-06-05 17:24 ` Ian Jackson
2014-06-10 7:33 ` Hongyang Yang
2014-07-09 23:15 ` Ian Jackson
2014-07-10 1:38 ` Hongyang Yang
2014-06-05 1:34 ` [PATCH v10 5/5] libxl: network buffering cmdline switch Yang Hongyang
2014-06-05 1:39 ` [PATCH v10] remus drbd: Implement remus drbd replicated disk Yang Hongyang
2014-06-05 16:25 ` Shriram Rajagopalan
2014-06-05 17:41 ` Ian Jackson
2014-06-05 18:14 ` Shriram Rajagopalan
2014-06-05 18:26 ` Ian Jackson
2014-06-06 11:23 ` Ian Jackson
2014-06-06 5:38 ` Hongyang Yang
2014-06-06 7:12 ` Shriram Rajagopalan
2014-06-06 11:18 ` Ian Jackson
2014-06-06 2:21 ` Hongyang Yang
2014-06-05 17:30 ` [PATCH v10 5/5] libxl: network buffering cmdline switch Ian Jackson
2014-06-06 6:34 ` Hongyang Yang
2014-06-06 7:26 ` Shriram Rajagopalan
2014-06-06 11:13 ` Ian Jackson
2014-06-05 10:47 ` [PATCH v10 0/5] Remus netbuffer: Network buffering support George Dunlap
2014-06-06 2:17 ` Hongyang Yang
2014-06-05 16:01 ` Ian Jackson
2014-06-05 16:12 ` Ian Jackson
2014-06-06 2:26 ` Hongyang Yang
-- strict thread matches above, loose matches on Subject: below --
2014-05-21 10:14 [PATCH v10 0/5] Remus/Libxl: " Yang Hongyang
2014-05-21 10:14 ` [PATCH v10 1/5] libxl: introduce asynchronous execution API Yang Hongyang
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=1401932069-16460-2-git-send-email-yanghy@cn.fujitsu.com \
--to=yanghy@cn.fujitsu.com \
--cc=andrew.cooper3@citrix.com \
--cc=eddie.dong@intel.com \
--cc=ian.campbell@citrix.com \
--cc=ian.jackson@eu.citrix.com \
--cc=laijs@cn.fujitsu.com \
--cc=roger.pau@citrix.com \
--cc=rshriram@cs.ubc.ca \
--cc=stefano.stabellini@eu.citrix.com \
--cc=wency@cn.fujitsu.com \
--cc=xen-devel@lists.xen.org \
--cc=yunhong.jiang@intel.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).