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

[Xen-devel] [PATCH 19 of 29 RFC] libxl: add libxl__device_hotplug_disconnect



# HG changeset patch
# User Roger Pau Monne <roger.pau@xxxxxxxxxxxxx>
# Date 1328178627 -3600
# Node ID 937bbe68a1942e22c40aa18c8bb66490aec56945
# Parent  94733bc9cc2fbeaa08a660ec90dcd9c5ad924e1b
libxl: add libxl__device_hotplug_disconnect

Sets the necessary xenstore entries to trigger the unplug of a device,
and waits for the device to react (either by setting the device state
to disconnected or to error).

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

diff -r 94733bc9cc2f -r 937bbe68a194 tools/libxl/libxl_device.c
--- a/tools/libxl/libxl_device.c        Thu Feb 02 11:27:27 2012 +0100
+++ b/tools/libxl/libxl_device.c        Thu Feb 02 11:30:27 2012 +0100
@@ -405,7 +405,7 @@ int libxl__device_disk_dev_number(const 
  * or timeout occurred.
  */
 int libxl__wait_for_device_state(libxl__gc *gc, struct timeval *tv,
-                                 XenbusState state,
+                                 int state,
                                  libxl__device_state_handler handler)
 {
     libxl_ctx *ctx = libxl__gc_owner(gc);
@@ -413,6 +413,7 @@ int libxl__wait_for_device_state(libxl__
     unsigned int n;
     fd_set rfds;
     char **l1 = NULL;
+    char *entry;
 
 start:
     rc = 1;
@@ -431,6 +432,10 @@ start:
         default:
             l1 = xs_read_watch(ctx->xsh, &n);
             if (l1 != NULL) {
+                entry = strrchr(l1[0], '/');
+                if (!entry || strcmp(entry, "/state"))
+                    goto start;
+
                 char *sstate = libxl__xs_read(gc, XBT_NULL,
                                              l1[XS_WATCH_PATH]);
                 if (!sstate || atoi(sstate) == state) {
@@ -575,6 +580,71 @@ out:
     return rc;
 }
 
+int libxl__device_hotplug_disconnect(libxl__gc *gc, libxl__device *dev,
+                                     libxl__hotplug_status disconnect_param)
+{
+    libxl_ctx *ctx = libxl__gc_owner(gc);
+    xs_transaction_t t;
+    char *hotplug_path = libxl__device_hotplug_path(gc, dev);
+    char *state_path = libxl__sprintf(gc, "%s/state", hotplug_path);
+    char *state;
+    struct timeval tv;
+    int rc = 0;
+
+retry_transaction:
+    t = xs_transaction_start(ctx->xsh);
+    state = libxl__xs_read(gc, t, state_path);
+    LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Disconnecting device with path %s and "
+                                      "state %s", hotplug_path, state);
+    if (!state) {
+        xs_transaction_end(ctx->xsh, t, 0);
+        goto out;
+    }
+    if (atoi(state) != HOTPLUG_DEVICE_CONNECTED) {
+        xs_transaction_end(ctx->xsh, t, 0);
+        goto out;
+    }
+    libxl__xs_write(gc, t, state_path, "%d", disconnect_param);
+    if (!xs_transaction_end(ctx->xsh, t, 0)) {
+        if (errno == EAGAIN)
+            goto retry_transaction;
+        else {
+            rc = ERROR_FAIL;
+            goto out;
+        }
+    }
+
+    xs_watch(ctx->xsh, state_path, hotplug_path);
+
+    tv.tv_sec = LIBXL_DESTROY_TIMEOUT;
+    tv.tv_usec = 0;
+    rc = libxl__wait_for_device_state(gc, &tv, HOTPLUG_DEVICE_DISCONNECTED,
+                                      NULL);
+    xs_unwatch(ctx->xsh, state_path, hotplug_path);
+    state = libxl__xs_read(gc, XBT_NULL, state_path);
+    if (!state) {
+        goto out;
+    }
+    if (atoi(state) == HOTPLUG_DEVICE_ERROR) {
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
+                   "Error while unplug of "
+                   "device with hotplug path %s", hotplug_path);
+        rc = ERROR_FAIL;
+    } else if (rc == ERROR_TIMEDOUT) {
+        LIBXL__LOG(ctx, LIBXL__LOG_DEBUG,
+                   "Timeout while waiting for unplug of "
+                   "device with hotplug path %s", hotplug_path);
+    } else if (rc == ERROR_FAIL) {
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
+                   "failed to destroy device with "
+                   "hotplug path %s", hotplug_path);
+    }
+
+out:
+    libxl__xs_path_cleanup(gc, hotplug_path);
+    return rc;
+}
+
 int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
 {
     char *be_path = libxl__device_backend_path(gc, dev);
diff -r 94733bc9cc2f -r 937bbe68a194 tools/libxl/libxl_internal.h
--- a/tools/libxl/libxl_internal.h      Thu Feb 02 11:27:27 2012 +0100
+++ b/tools/libxl/libxl_internal.h      Thu Feb 02 11:30:27 2012 +0100
@@ -334,7 +334,7 @@ typedef int libxl__device_state_handler(
  * Returns 0 on success, and < 0 on error.
  */
 _hidden int libxl__wait_for_device_state(libxl__gc *gc, struct timeval *tv,
-                                         XenbusState state,
+                                         int state,
                                          libxl__device_state_handler handler);
 
 /*
@@ -366,6 +366,16 @@ typedef enum {
 } libxl__hotplug_status;
 
 /*
+ * libxl__device_hotplug_disconnect - disconnect remove device
+ * disconnect_param: action to use when disconnecting the device, either
+ * HOTPLUG_DEVICE_DISCONNECT or HOTPLUG_DEVICE_FORCE_DISCONNECT
+ *
+ * Returns 0 on success, and < 0 on error.
+ */
+_hidden int libxl__device_hotplug_disconnect(libxl__gc *gc, libxl__device *dev,
+                                       libxl__hotplug_status disconnect_param);
+
+/*
  * libxl__device_hotplug - generic function to execute hotplug scripts
  * gc: allocation pool
  * dev: reference to the device that executes the hotplug scripts

_______________________________________________
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®.