[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 25 of 29 RFC] libxl: add libxl_hotplug_dispatch



# HG changeset patch
# User Roger Pau Monne <roger.pau@xxxxxxxxxxxxx>
# Date 1328179686 -3600
# Node ID 94532199f647fc03816fc5ae50ab53c8c5b80cd8
# Parent  1506b1f2ab0fe5f4cd5bcd86a566d5a7be5f838b
libxl: add libxl_hotplug_dispatch

Added a new function to libxl API to handle device hotplug. Actions to
execute upon hotplug device state changes are handled using the
libxl_device_disk_hotplug_actions and libxl_device_nic_hotplug_actions
depending on the type of device. Currently only VIF and VBD devices
are handled by the hotplug mechanism.

Signed-off-by: Roger Pau Monne <roger.pau@xxxxxxxxxxxxx>

diff -r 1506b1f2ab0f -r 94532199f647 tools/libxl/libxl.c
--- a/tools/libxl/libxl.c       Thu Feb 02 11:45:03 2012 +0100
+++ b/tools/libxl/libxl.c       Thu Feb 02 11:48:06 2012 +0100
@@ -982,6 +982,188 @@ out:
     return rc;
 }
 
+static int libxl__hotplug_generic_dispatcher(libxl__gc *gc, char *path,
+                                uint32_t domid,
+                                libxl__hotplug_status state,
+                                libxl__device_generic_hotplug_actions *action,
+                                void *device)
+{
+    libxl_ctx *ctx = libxl__gc_owner(gc);
+    char *spath = libxl__sprintf(gc, "%s/state", path);
+    int rc = 0;
+
+    LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "processing device %s with state %d",
+                                      path, state);
+    switch(state) {
+    case HOTPLUG_DEVICE_INIT:
+        if (action->init) {
+            rc = action->init(ctx, domid, device);
+            if (rc < 0) {
+                LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unable to init"
+                                                  " device %s", path);
+                libxl__xs_write(gc, XBT_NULL, spath, "%d",
+                                HOTPLUG_DEVICE_ERROR);
+                break;
+            }
+        }
+        libxl__xs_write(gc, XBT_NULL, spath, "%d", HOTPLUG_DEVICE_CONNECT);
+        break;
+    case HOTPLUG_DEVICE_CONNECT:
+        if (action->connect) {
+            rc = action->connect(ctx, domid, device);
+            if (rc < 0) {
+                LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unable to connect"
+                                                  " device %s", path);
+                libxl__xs_write(gc, XBT_NULL, spath, "%d",
+                                HOTPLUG_DEVICE_ERROR);
+                break;
+            }
+        }
+        libxl__xs_write(gc, XBT_NULL, spath, "%d", HOTPLUG_DEVICE_CONNECTED);
+        break;
+    case HOTPLUG_DEVICE_CONNECTED:
+        if (action->connected) {
+            rc = action->connected(ctx, domid, device);
+            if (rc < 0) {
+                LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unable to execute "
+                                                  "connected action on"
+                                                  " device %s", path);
+                libxl__xs_write(gc, XBT_NULL, spath, "%d",
+                                HOTPLUG_DEVICE_ERROR);
+                break;
+            }
+        }
+        break;
+    case HOTPLUG_DEVICE_DISCONNECT:
+        if (action->disconnect) {
+            rc = action->disconnect(ctx, domid, device);
+            if (rc < 0) {
+                LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unable to unplug"
+                                                  " device %s", path);
+                libxl__xs_write(gc, XBT_NULL, spath, "%d",
+                                HOTPLUG_DEVICE_ERROR);
+                break;
+            }
+        }
+        libxl__xs_write(gc, XBT_NULL, spath, "%d",
+                        HOTPLUG_DEVICE_DISCONNECTED);
+        break;
+    case HOTPLUG_DEVICE_DISCONNECTED:
+        if (action->disconnected) {
+            rc = action->disconnected(ctx, domid, device);
+            if (rc < 0) {
+                LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unable to execute "
+                                                  "unpluged action on"
+                                                  " device %s", path);
+                libxl__xs_write(gc, XBT_NULL, spath, "%d",
+                                HOTPLUG_DEVICE_ERROR);
+                break;
+            }
+        }
+        break;
+    case HOTPLUG_DEVICE_FORCE_DISCONNECT:
+        if (action->force_disconnect) {
+            rc = action->force_disconnect(ctx, domid, device);
+            if (rc < 0) {
+                LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unable to force "
+                                                  "disconnect device "
+                                                  "%s", path);
+                libxl__xs_write(gc, XBT_NULL, spath, "%d",
+                                HOTPLUG_DEVICE_ERROR);
+                break;
+            }
+        }
+        libxl__xs_write(gc, XBT_NULL, spath, "%d",
+                        HOTPLUG_DEVICE_DISCONNECTED);
+        break;
+    case HOTPLUG_DEVICE_ERROR:
+        if (action->error)
+            rc = action->error(ctx, domid, device);
+        break;
+    }
+    return rc;
+}
+
+int libxl_hotplug_dispatch(libxl_ctx *ctx,
+                           libxl_device_disk_hotplug_actions *disk_handler,
+                           libxl_device_nic_hotplug_actions *nic_handler)
+{
+    unsigned int n;
+    char **l1, *sstate, *entry, *spath;
+    libxl__device dev;
+    libxl_device_disk disk;
+    libxl_device_nic nic;
+    libxl__hotplug_status state;
+
+    for (;;) {
+        GC_INIT(ctx);
+        l1 = xs_read_watch(ctx->xsh, &n);
+        if (!l1) {
+            continue;
+        }
+
+        /* Only react to "state" changes */
+        entry = strrchr(l1[0], '/');
+        if (!entry || strcmp(entry, "/state"))
+            goto next;
+
+        spath = libxl__strdup(gc, l1[0]);
+        /* Fetch state info */
+        sstate = libxl__xs_read(gc, XBT_NULL, l1[0]);
+        if (!sstate) {
+            LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unable to parse state"
+                                              "from %s", l1[0]);
+            goto next;
+        }
+        state = atoi(sstate);
+
+        /* remove "state" part from path */
+        *entry = '\0';
+        if (libxl__parse_hotplug_path(gc, l1[0], &dev) < 0)
+            goto next;
+
+        switch(dev.backend_kind) {
+        case LIBXL__DEVICE_KIND_VBD:
+            libxl_device_disk_init(ctx, &disk);
+            if (libxl__parse_disk_hotplug_path(gc, l1[0], &disk)) {
+                LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unable to parse disk data"
+                                                  "from %s", l1[0]);
+                goto next;
+            }
+            /* Choose suitable backend */
+            disk.backend = LIBXL_DISK_BACKEND_UNKNOWN;
+            if (libxl__device_disk_set_backend(gc, &disk) < 0) {
+                LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "no suitable backend for"
+                                                  "disk %s", disk.pdev_path);
+                goto next;
+            }
+            libxl__hotplug_generic_dispatcher(gc, l1[0], dev.domid, state,
+                    (libxl__device_generic_hotplug_actions *) disk_handler,
+                    (void *) &disk);
+            break;
+        case LIBXL__DEVICE_KIND_VIF:
+            libxl_device_nic_init(ctx, &nic);
+            if (libxl__parse_nic_hotplug_path(gc, l1[0], &nic)) {
+                LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unable to parse nic data"
+                                                  "from %s", l1[0]);
+                goto next;
+            }
+            libxl__hotplug_generic_dispatcher(gc, l1[0], dev.domid, state,
+                    (libxl__device_generic_hotplug_actions *) nic_handler,
+                    (void *) &nic);
+            break;
+        default:
+            LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
+                       "unable to handle device type %s from %s",
+                       libxl__device_kind_to_string(dev.backend_kind), l1[0]);
+            break;
+        }
+next:
+        free(l1);
+        GC_FREE;
+    }
+}
+
 
/******************************************************************************/
 
 int libxl_device_disk_init(libxl_ctx *ctx, libxl_device_disk *disk)
diff -r 1506b1f2ab0f -r 94532199f647 tools/libxl/libxl.h
--- a/tools/libxl/libxl.h       Thu Feb 02 11:45:03 2012 +0100
+++ b/tools/libxl/libxl.h       Thu Feb 02 11:48:06 2012 +0100
@@ -464,6 +464,12 @@ libxl_vminfo * libxl_list_vm(libxl_ctx *
  *   Set the necessary watches to start monitoring /hotplug/ entries for
  *   the caller domain.
  *
+ * libxl_hotplug_dispatch(ctx, disk_handler, nic_handler):
+ *
+ *   React to /hotplug/<domid> changes and execute the necessary handlers
+ *   based on the passed disk_handler and nic_handler structs that contain
+ *   the pointers to the functions to be executed.
+ *
  */
 
 /* Disks */
@@ -532,7 +538,37 @@ int libxl_device_pci_destroy(libxl_ctx *
 libxl_device_pci *libxl_device_pci_list(libxl_ctx *ctx, uint32_t domid, int 
*num);
 
 /* Hotplug */
+typedef int libxl_device_disk_hotplug_handler(libxl_ctx *ctx,
+                                              uint32_t domid,
+                                              libxl_device_disk *disk);
+typedef int libxl_device_nic_hotplug_handler(libxl_ctx *ctx,
+                                             uint32_t domid,
+                                             libxl_device_nic *nic);
+
+typedef struct libxl_device_disk_hotplug_actions {
+    libxl_device_disk_hotplug_handler *init;
+    libxl_device_disk_hotplug_handler *connect;
+    libxl_device_disk_hotplug_handler *connected;
+    libxl_device_disk_hotplug_handler *disconnect;
+    libxl_device_disk_hotplug_handler *disconnected;
+    libxl_device_disk_hotplug_handler *force_disconnect;
+    libxl_device_disk_hotplug_handler *error;
+} libxl_device_disk_hotplug_actions;
+
+typedef struct libxl_device_nic_hotplug_actions {
+    libxl_device_nic_hotplug_handler *init;
+    libxl_device_nic_hotplug_handler *connect;
+    libxl_device_nic_hotplug_handler *connected;
+    libxl_device_nic_hotplug_handler *disconnect;
+    libxl_device_nic_hotplug_handler *disconnected;
+    libxl_device_nic_hotplug_handler *force_disconnect;
+    libxl_device_nic_hotplug_handler *error;
+} libxl_device_nic_hotplug_actions;
+
 int libxl_setup_hotplug_listener(libxl_ctx *ctx);
+int libxl_hotplug_dispatch(libxl_ctx *ctx,
+                           libxl_device_disk_hotplug_actions *disk_handler,
+                           libxl_device_nic_hotplug_actions *nic_handler);
 
 /*
  * Parse a PCI BDF into a PCI device structure.
diff -r 1506b1f2ab0f -r 94532199f647 tools/libxl/libxl_internal.h
--- a/tools/libxl/libxl_internal.h      Thu Feb 02 11:45:03 2012 +0100
+++ b/tools/libxl/libxl_internal.h      Thu Feb 02 11:48:06 2012 +0100
@@ -384,6 +384,22 @@ typedef enum {
 _hidden int libxl__device_hotplug_disconnect(libxl__gc *gc, libxl__device *dev,
                                        libxl__hotplug_status disconnect_param);
 
+/* Generic handlers for hotplug devices */
+/* Hotplug */
+typedef int libxl__device_generic_hotplug_handler(libxl_ctx *ctx,
+                                                 uint32_t domid,
+                                                 void *device);
+
+typedef struct libxl__device_generic_hotplug_actions {
+    libxl__device_generic_hotplug_handler *init;
+    libxl__device_generic_hotplug_handler *connect;
+    libxl__device_generic_hotplug_handler *connected;
+    libxl__device_generic_hotplug_handler *disconnect;
+    libxl__device_generic_hotplug_handler *disconnected;
+    libxl__device_generic_hotplug_handler *force_disconnect;
+    libxl__device_generic_hotplug_handler *error;
+} libxl__device_generic_hotplug_actions;
+
 /*
  * libxl__device_hotplug - generic function to execute hotplug scripts
  * gc: allocation pool

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.