From: Ian Campbell <ian.campbell@citrix.com>
To: xen-devel@lists.xensource.com
Cc: Bastian Blank <waldi@debian.org>
Subject: [PATCH 4 of 4] libxl: add statup checks to libxl__wait_for_device_model
Date: Wed, 4 May 2011 15:51:12 +0100 [thread overview]
Message-ID: <36871b37a9bd286d6ef2.1304520672@localhost.localdomain> (raw)
In-Reply-To: <patchbomb.1304520668@localhost.localdomain>
# HG changeset patch
# User Ian Campbell <ian.campbell@citrix.com>
# Date 1304516515 -3600
# Node ID 36871b37a9bd286d6ef291b41513c33325db9719
# Parent ec008dc43727191f472cd4bd5e59d9d35d9d36c2
libxl: add statup checks to libxl__wait_for_device_model
When the device model is starting up push checks for spawn failure down into
libxl__wait_for_device_model, allowing us to fail more quickly when the device
model fails to start (e.g. due to a missing library or an early setup error
etc).
In order to allow the select loop in libxl__wait_for_device_model to wake when
the child dies add pipe between the parent and the intermediate process which
the intermediate process can use to signal the parent.
Signed-off-by: Ian Campbell <ian.campbell@citrix.com>
diff -r ec008dc43727 -r 36871b37a9bd tools/libxl/libxl.c
--- a/tools/libxl/libxl.c Wed May 04 14:37:21 2011 +0100
+++ b/tools/libxl/libxl.c Wed May 04 14:41:55 2011 +0100
@@ -522,7 +522,7 @@ int libxl_domain_unpause(libxl_ctx *ctx,
state = libxl__xs_read(&gc, XBT_NULL, path);
if (state != NULL && !strcmp(state, "paused")) {
libxl__xs_write(&gc, XBT_NULL, libxl__sprintf(&gc, "/local/domain/0/device-model/%d/command", domid), "continue");
- libxl__wait_for_device_model(&gc, domid, "running", NULL, NULL);
+ libxl__wait_for_device_model(&gc, domid, "running", NULL, NULL, NULL);
}
}
ret = xc_domain_unpause(ctx->xch, domid);
diff -r ec008dc43727 -r 36871b37a9bd tools/libxl/libxl_device.c
--- a/tools/libxl/libxl_device.c Wed May 04 14:37:21 2011 +0100
+++ b/tools/libxl/libxl_device.c Wed May 04 14:41:55 2011 +0100
@@ -410,6 +410,7 @@ out:
int libxl__wait_for_device_model(libxl__gc *gc,
uint32_t domid, char *state,
+ libxl__device_model_starting *starting,
int (*check_callback)(libxl__gc *gc,
uint32_t domid,
const char *state,
@@ -439,7 +440,17 @@ int libxl__wait_for_device_model(libxl__
tv.tv_sec = LIBXL_DEVICE_MODEL_START_TIMEOUT;
tv.tv_usec = 0;
nfds = xs_fileno(xsh) + 1;
+ if (starting && starting->for_spawn->fd > xs_fileno(xsh))
+ nfds = starting->for_spawn->fd + 1;
+
while (rc > 0 || (!rc && tv.tv_sec > 0)) {
+ if ( starting ) {
+ rc = libxl__spawn_check(gc, starting->for_spawn);
+ if ( rc ) {
+ rc = -1;
+ goto err_died;
+ }
+ }
p = xs_read(xsh, XBT_NULL, path, &len);
if ( NULL == p )
goto again;
@@ -461,15 +472,24 @@ again:
free(p);
FD_ZERO(&rfds);
FD_SET(xs_fileno(xsh), &rfds);
+ if (starting)
+ FD_SET(starting->for_spawn->fd, &rfds);
rc = select(nfds, &rfds, NULL, NULL, &tv);
if (rc > 0) {
- l = xs_read_watch(xsh, &num);
- if (l != NULL)
- free(l);
- else
- goto again;
+ if (FD_ISSET(xs_fileno(xsh), &rfds)) {
+ l = xs_read_watch(xsh, &num);
+ if (l != NULL)
+ free(l);
+ else
+ goto again;
+ }
+ if (starting && FD_ISSET(starting->for_spawn->fd, &rfds)) {
+ unsigned char dummy;
+ read(starting->for_spawn->fd, &dummy, sizeof(dummy));
+ }
}
}
+err_died:
xs_unwatch(xsh, path, path);
xs_daemon_close(xsh);
LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Device Model not ready");
diff -r ec008dc43727 -r 36871b37a9bd tools/libxl/libxl_dm.c
--- a/tools/libxl/libxl_dm.c Wed May 04 14:37:21 2011 +0100
+++ b/tools/libxl/libxl_dm.c Wed May 04 14:41:55 2011 +0100
@@ -855,14 +855,12 @@ static int detach_device_model(libxl__gc
return rc;
}
-
int libxl__confirm_device_model_startup(libxl__gc *gc,
libxl__device_model_starting *starting)
{
- int problem = libxl__wait_for_device_model(gc, starting->domid, "running", NULL, NULL);
int detach;
- if ( !problem )
- problem = libxl__spawn_check(gc, starting->for_spawn);
+ int problem = libxl__wait_for_device_model(gc, starting->domid, "running",
+ starting, NULL, NULL);
detach = detach_device_model(gc, starting);
return problem ? problem : detach;
}
diff -r ec008dc43727 -r 36871b37a9bd tools/libxl/libxl_dom.c
--- a/tools/libxl/libxl_dom.c Wed May 04 14:37:21 2011 +0100
+++ b/tools/libxl/libxl_dom.c Wed May 04 14:41:55 2011 +0100
@@ -543,7 +543,7 @@ int libxl__domain_save_device_model(libx
LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Saving device model state to %s", filename);
libxl__xs_write(gc, XBT_NULL, libxl__sprintf(gc, "/local/domain/0/device-model/%d/command", domid), "save");
- libxl__wait_for_device_model(gc, domid, "paused", NULL, NULL);
+ libxl__wait_for_device_model(gc, domid, "paused", NULL, NULL, NULL);
if (stat(filename, &st) < 0)
{
diff -r ec008dc43727 -r 36871b37a9bd tools/libxl/libxl_exec.c
--- a/tools/libxl/libxl_exec.c Wed May 04 14:37:21 2011 +0100
+++ b/tools/libxl/libxl_exec.c Wed May 04 14:41:55 2011 +0100
@@ -26,6 +26,7 @@
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h> /* for SIGKILL */
+#include <fcntl.h>
#include "libxl.h"
#include "libxl_internal.h"
@@ -91,6 +92,22 @@ void libxl_report_child_exitstatus(libxl
}
}
+static int libxl__set_fd_flag(libxl__gc *gc, int fd, int flag)
+{
+ int flags;
+
+ flags = fcntl(fd, F_GETFL);
+ if (flags == -1)
+ return ERROR_FAIL;
+
+ flags |= flag;
+
+ if (fcntl(fd, F_SETFL, flags) == -1)
+ return ERROR_FAIL;
+
+ return 0;
+}
+
int libxl__spawn_spawn(libxl__gc *gc,
libxl__spawn_starting *for_spawn,
const char *what,
@@ -100,22 +117,33 @@ int libxl__spawn_spawn(libxl__gc *gc,
{
libxl_ctx *ctx = libxl__gc_owner(gc);
pid_t child, got;
- int status;
+ int status, rc;
pid_t intermediate;
+ int pipes[2];
+ unsigned char dummy = 0;
if (for_spawn) {
for_spawn->what = strdup(what);
if (!for_spawn->what) return ERROR_NOMEM;
+
+ if (libxl_pipe(ctx, pipes) < 0)
+ goto err_parent;
+ if (libxl__set_fd_flag(gc, pipes[0], O_NONBLOCK) < 0 ||
+ libxl__set_fd_flag(gc, pipes[1], O_NONBLOCK) < 0)
+ goto err_parent_pipes;
}
intermediate = libxl_fork(ctx);
- if (intermediate ==-1) {
- if (for_spawn) free(for_spawn->what);
- return ERROR_FAIL;
- }
+ if (intermediate ==-1)
+ goto err_parent_pipes;
+
if (intermediate) {
/* parent */
- if (for_spawn) for_spawn->intermediate = intermediate;
+ if (for_spawn) {
+ for_spawn->intermediate = intermediate;
+ for_spawn->fd = pipes[0];
+ close(pipes[1]);
+ }
return 1;
}
@@ -124,8 +152,10 @@ int libxl__spawn_spawn(libxl__gc *gc,
child = fork();
if (child == -1)
exit(255);
- if (!child)
+ if (!child) {
+ if (for_spawn) close(pipes[1]);
return 0; /* caller runs child code */
+ }
intermediate_hook(hook_data, child);
@@ -134,9 +164,23 @@ int libxl__spawn_spawn(libxl__gc *gc,
got = call_waitpid(ctx->waitpid_instead, child, &status, 0);
assert(got == child);
- _exit(WIFEXITED(status) ? WEXITSTATUS(status) :
+ rc = (WIFEXITED(status) ? WEXITSTATUS(status) :
WIFSIGNALED(status) && WTERMSIG(status) < 127
? WTERMSIG(status)+128 : -1);
+ if (for_spawn)
+ write(pipes[1], &dummy, sizeof(dummy));
+ _exit(rc);
+
+ err_parent_pipes:
+ if (for_spawn) {
+ close(pipes[0]);
+ close(pipes[1]);
+ }
+
+ err_parent:
+ if (for_spawn) free(for_spawn->what);
+
+ return ERROR_FAIL;
}
static void report_spawn_intermediate_status(libxl__gc *gc,
diff -r ec008dc43727 -r 36871b37a9bd tools/libxl/libxl_internal.h
--- a/tools/libxl/libxl_internal.h Wed May 04 14:37:21 2011 +0100
+++ b/tools/libxl/libxl_internal.h Wed May 04 14:41:55 2011 +0100
@@ -233,6 +233,7 @@ typedef struct {
/* put this in your own status structure as returned to application */
/* all fields are private to libxl_spawn_... */
pid_t intermediate;
+ int fd;
char *what; /* malloc'd in spawn_spawn */
} libxl__spawn_starting;
@@ -270,6 +271,7 @@ _hidden int libxl__confirm_device_model_
_hidden int libxl__detach_device_model(libxl__gc *gc, libxl__device_model_starting *starting);
_hidden int libxl__wait_for_device_model(libxl__gc *gc,
uint32_t domid, char *state,
+ libxl__device_model_starting *starting,
int (*check_callback)(libxl__gc *gc,
uint32_t domid,
const char *state,
diff -r ec008dc43727 -r 36871b37a9bd tools/libxl/libxl_pci.c
--- a/tools/libxl/libxl_pci.c Wed May 04 14:37:21 2011 +0100
+++ b/tools/libxl/libxl_pci.c Wed May 04 14:41:55 2011 +0100
@@ -612,7 +612,8 @@ static int do_pci_add(libxl__gc *gc, uin
hvm = libxl__domain_is_hvm(gc, domid);
if (hvm) {
- if (libxl__wait_for_device_model(gc, domid, "running", NULL, NULL) < 0) {
+ if (libxl__wait_for_device_model(gc, domid, "running",
+ NULL, NULL, NULL) < 0) {
return ERROR_FAIL;
}
path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/state", domid);
@@ -626,7 +627,8 @@ static int do_pci_add(libxl__gc *gc, uin
pcidev->bus, pcidev->dev, pcidev->func);
path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/command", domid);
xs_write(ctx->xsh, XBT_NULL, path, "pci-ins", strlen("pci-ins"));
- rc = libxl__wait_for_device_model(gc, domid, NULL, pci_ins_check, state);
+ rc = libxl__wait_for_device_model(gc, domid, NULL, NULL,
+ pci_ins_check, state);
path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/parameter", domid);
vdevfn = libxl__xs_read(gc, XBT_NULL, path);
path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/state", domid);
@@ -843,7 +845,8 @@ static int do_pci_remove(libxl__gc *gc,
hvm = libxl__domain_is_hvm(gc, domid);
if (hvm) {
- if (libxl__wait_for_device_model(gc, domid, "running", NULL, NULL) < 0) {
+ if (libxl__wait_for_device_model(gc, domid, "running",
+ NULL, NULL, NULL) < 0) {
return ERROR_FAIL;
}
path = libxl__sprintf(gc, "/local/domain/0/device-model/%d/state", domid);
@@ -857,7 +860,8 @@ static int do_pci_remove(libxl__gc *gc,
* device-model for function 0 */
if ( !force && (pcidev->vdevfn & 0x7) == 0 ) {
xs_write(ctx->xsh, XBT_NULL, path, "pci-rem", strlen("pci-rem"));
- if (libxl__wait_for_device_model(gc, domid, "pci-removed", NULL, NULL) < 0) {
+ if (libxl__wait_for_device_model(gc, domid, "pci-removed",
+ NULL, NULL, NULL) < 0) {
LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Device Model didn't respond in time");
/* This depends on guest operating system acknowledging the
* SCI, if it doesn't respond in time then we may wish to
next prev parent reply other threads:[~2011-05-04 14:51 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <4DB82B38.6090207@gmail.com>
[not found] ` <BAY148-w56B2B88110870F89DE84D4EF980@phx.gbl>
[not found] ` <4DB89A39.6070203@gmail.com>
[not found] ` <BAY148-w282F83283CEBAD8F438117EF9B0@phx.gbl>
[not found] ` <4DB91947.2070203@gmail.com>
[not found] ` <1303977639.25988.1447.camel@localhost.localdomain>
[not found] ` <20110428110658.GA26816@wavehammer.waldi.eu.org>
[not found] ` <1303990128.25988.1570.camel@localhost.localdomain>
[not found] ` <4DB9534F.1070701@gmail.com>
2011-04-28 14:11 ` [Pkg-xen-devel] xen 4.1 blktap2 support Ian Campbell
[not found] ` <20110428122719.GA27897@wavehammer.waldi.eu.org>
2011-04-28 14:20 ` Ian Campbell
2011-04-29 11:08 ` Bastian Blank
2011-05-03 16:39 ` Ian Campbell
2011-05-04 14:51 ` [PATCH 0 of 4] libxl: improve error handling when device model fails to start early on Ian Campbell
2011-05-04 14:51 ` [PATCH 1 of 4] libxl: check that device model binary is executable Ian Campbell
2011-05-24 14:59 ` Ian Jackson
2011-05-04 14:51 ` [PATCH 2 of 4] libxl: remove redundant call to libxl_domain_device_model Ian Campbell
2011-05-04 14:51 ` [PATCH 3 of 4] libxl: pass libxl__spawn_starting to libxl__spawn_spawn Ian Campbell
2011-05-04 14:51 ` Ian Campbell [this message]
2011-05-04 16:23 ` [PATCH 4 of 4] libxl: add statup checks to libxl__wait_for_device_model Ian Campbell
2011-05-24 15:57 ` Ian Jackson
2011-05-24 16:08 ` Ian Campbell
2011-05-19 16:04 ` [PATCH 0 of 4] libxl: improve error handling when device model fails to start early on Ian Jackson
2011-05-20 7:08 ` Ian Campbell
2011-05-05 12:17 ` [PATCH] Re: Re: [Pkg-xen-devel] xen 4.1 blktap2 support Ian Campbell
2011-05-20 17:08 ` Ian Jackson
2011-05-23 9:47 ` Ian Campbell
2011-05-24 15:19 ` Ian Jackson
2011-04-30 13:09 ` Bastian Blank
2011-04-30 14:42 ` Bastian Blank
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=36871b37a9bd286d6ef2.1304520672@localhost.localdomain \
--to=ian.campbell@citrix.com \
--cc=waldi@debian.org \
--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).