[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |