# HG changeset patch
# User Roger Pau Monne <roger.pau@xxxxxxxxxxxxx>
# Date 1317028951 -7200
# Node ID 18c7ed71d2bfe50b65427860bb192ef273568b04
# Parent 0ab9f548890e5e58122f73aa1c4164fd6e319b1c
libxl: add custom disconnect functions for different device types.
This patch creates a new struct, called libxl__disconnect that can be used to
assign different functions that will be called to check if the device is
disconnected and to add it to the shutdown watch. Added a helper function to
get the libxl__device_kind from a be_path. The only device that has a different
shutdown mechanism right now is vbd.
diff -r 0ab9f548890e -r 18c7ed71d2bf tools/libxl/libxl_device.c
--- a/tools/libxl/libxl_device.c Fri Sep 23 13:31:51 2011 +0200
+++ b/tools/libxl/libxl_device.c Mon Sep 26 11:22:31 2011 +0200
@@ -28,6 +28,11 @@
#include "libxl.h"
#include "libxl_internal.h"
+static int libxl__watch_for_disconnect_vbd(libxl__gc *gc, char *be_path);
+static int libxl__has_disconnected_vbd(libxl__gc *gc, char *be_path);
+static int libxl__watch_for_disconnect_generic(libxl__gc *gc, char *be_path);
+static int libxl__has_disconnected_generic(libxl__gc *gc, char *be_path);
+
static const char *string_of_kinds[] = {
[DEVICE_VIF] = "vif",
[DEVICE_VBD] = "vbd",
@@ -38,6 +43,27 @@ static const char *string_of_kinds[] = {
[DEVICE_CONSOLE] = "console",
};
+static const libxl__disconnect disconnect_vbd = {
+ .watch_for_disconnect = libxl__watch_for_disconnect_vbd,
+ .has_disconnected = libxl__has_disconnected_vbd,
+};
+
+static const libxl__disconnect disconnect_generic = {
+ .watch_for_disconnect = libxl__watch_for_disconnect_generic,
+ .has_disconnected = libxl__has_disconnected_generic,
+};
+
+static const libxl__disconnect *disconnect_ops[] = {
+ [DEVICE_UNKNOWN] = &disconnect_generic,
+ [DEVICE_VIF] = &disconnect_generic,
+ [DEVICE_VBD] = &disconnect_vbd,
+ [DEVICE_QDISK] = &disconnect_generic,
+ [DEVICE_PCI] = &disconnect_generic,
+ [DEVICE_VFB] = &disconnect_generic,
+ [DEVICE_VKBD] = &disconnect_generic,
+ [DEVICE_CONSOLE] = &disconnect_generic,
+};
+
char *libxl__device_frontend_path(libxl__gc *gc, libxl__device *device)
{
char *dom_path = libxl__xs_get_dompath(gc, device->domid);
@@ -59,6 +85,23 @@ char *libxl__device_backend_path(libxl__
device->domid, device->devid);
}
+static libxl__device_kinds libxl__device_identify(char *be_path)
+{
+ char strkind[16]; /* Longest is actually "console" */
+ int len = sizeof(string_of_kinds)/sizeof(char *);
+
+ /* /local/domain/<domid>/backend/<kind>/<domid>/<devid> */
+ if (sscanf(be_path, "/local/domain/%*d/backend/%16[^/]s", strkind) != 1)
+ return DEVICE_UNKNOWN;
+
+ for (int j = 1; j < len; j++) {
+ if (strncmp(strkind, string_of_kinds[j], 16) == 0)
+ return j;
+ }
+
+ return DEVICE_UNKNOWN;
+}
+
int libxl__device_generic_add(libxl__gc *gc, libxl__device *device,
char **bents, char **fents)
{
@@ -371,15 +414,11 @@ int libxl__device_destroy(libxl__gc *gc,
libxl_ctx *ctx = libxl__gc_owner(gc);
xs_transaction_t t;
char *state_path = libxl__sprintf(gc, "%s/state", be_path);
- char *state = libxl__xs_read(gc, XBT_NULL, state_path);
+ libxl__device_kinds device_type = libxl__device_identify(be_path);
int rc = 0;
- if (!state)
+ if (disconnect_ops[device_type]->has_disconnected(gc, be_path))
goto out;
- if (atoi(state) != 4) {
- xs_rm(ctx->xsh, XBT_NULL, be_path);
- goto out;
- }
retry_transaction:
t = xs_transaction_start(ctx->xsh);
@@ -394,7 +433,7 @@ retry_transaction:
}
}
if (!force) {
- xs_watch(ctx->xsh, state_path, be_path);
+ disconnect_ops[device_type]->watch_for_disconnect(gc, be_path);
rc = 1;
} else {
xs_rm(ctx->xsh, XBT_NULL, be_path);
@@ -410,6 +449,7 @@ static int wait_for_dev_destroy(libxl__g
unsigned int n;
fd_set rfds;
char **l1 = NULL;
+ libxl__device_kinds device_type;
rc = 1;
nfds = xs_fileno(ctx->xsh) + 1;
@@ -418,11 +458,9 @@ static int wait_for_dev_destroy(libxl__g
if (select(nfds, &rfds, NULL, NULL, tv) > 0) {
l1 = xs_read_watch(ctx->xsh, &n);
if (l1 != NULL) {
- char *state = libxl__xs_read(gc, XBT_NULL, l1[XS_WATCH_PATH]);
- if (!state || atoi(state) == 6) {
+ device_type = libxl__device_identify(l1[XS_WATCH_TOKEN]);
+ if (disconnect_ops[device_type]->has_disconnected(gc,
l1[XS_WATCH_TOKEN])) {
xs_unwatch(ctx->xsh, l1[0], l1[1]);
- xs_rm(ctx->xsh, XBT_NULL, l1[XS_WATCH_TOKEN]);
- LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Destroyed device backend at
%s", l1[XS_WATCH_TOKEN]);
rc = 0;
}
free(l1);
@@ -528,6 +566,62 @@ out:
return rc;
}
+static int libxl__watch_for_disconnect_vbd(libxl__gc *gc, char *be_path)
+{
+ libxl_ctx *ctx = libxl__gc_owner(gc);
+ char *hotplug_path = libxl__sprintf(gc, "%s/hotplug-status", be_path);
+
+ xs_watch(ctx->xsh, hotplug_path, be_path);
+
+ return 1;
+}
+
+static int libxl__has_disconnected_vbd(libxl__gc *gc, char *be_path)
+{
+ libxl_ctx *ctx = libxl__gc_owner(gc);
+ char *hotplug_path = libxl__sprintf(gc, "%s/hotplug-status", be_path);
+ char *hotplug = libxl__xs_read(gc, XBT_NULL, hotplug_path);
+ int rc = 0;
+
+ if (!hotplug || !strcmp(hotplug, "disconnected")) {
+ xs_rm(ctx->xsh, XBT_NULL, be_path);
+ LIBXL__LOG(ctx, LIBXL__LOG_DEBUG,
+ "Destroyed device backend at %s",
+ be_path);
+ rc = 1;
+ }
+
+ return rc;
+}
+
+static int libxl__watch_for_disconnect_generic(libxl__gc *gc, char *be_path)
+{
+ libxl_ctx *ctx = libxl__gc_owner(gc);
+ char *state_path = libxl__sprintf(gc, "%s/state", be_path);
+
+ xs_watch(ctx->xsh, state_path, be_path);
+
+ return 1;
+}
+
+static int libxl__has_disconnected_generic(libxl__gc *gc, char *be_path)
+{
+ libxl_ctx *ctx = libxl__gc_owner(gc);
+ char *state_path = libxl__sprintf(gc, "%s/state", be_path);
+ char *state = libxl__xs_read(gc, XBT_NULL, state_path);
+ int rc = 0;
+
+ if (!state || atoi(state) != 4) {
+ xs_rm(ctx->xsh, XBT_NULL, be_path);
+ LIBXL__LOG(ctx, LIBXL__LOG_DEBUG,
+ "Destroyed device backend at %s",
+ be_path);
+ rc = 1;
+ }
+
+ return rc;
+}
+
int libxl__wait_for_device_model(libxl__gc *gc,
uint32_t domid, char *state,
libxl__device_model_starting *starting,
diff -r 0ab9f548890e -r 18c7ed71d2bf tools/libxl/libxl_internal.h
--- a/tools/libxl/libxl_internal.h Fri Sep 23 13:31:51 2011 +0200
+++ b/tools/libxl/libxl_internal.h Mon Sep 26 11:22:31 2011 +0200
@@ -95,7 +95,8 @@ struct libxl__ctx {
};
typedef enum {
- DEVICE_VIF = 1,
+ DEVICE_UNKNOWN = 0,
+ DEVICE_VIF,
DEVICE_VBD,
DEVICE_QDISK,
DEVICE_PCI,
@@ -206,6 +207,12 @@ _hidden int libxl__domain_save_device_mo
_hidden void libxl__userdata_destroyall(libxl__gc *gc, uint32_t domid);
/* from xl_device */
+
+typedef struct {
+ int (*watch_for_disconnect)(libxl__gc *gc, char *be_path);
+ int (*has_disconnected)(libxl__gc *gc, char *be_path);
+} libxl__disconnect;
+
_hidden char *libxl__device_disk_string_of_backend(libxl_disk_backend backend);
_hidden char *libxl__device_disk_string_of_format(libxl_disk_format format);
_hidden int libxl__device_disk_set_backend(libxl__gc*, libxl_device_disk*);
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|