xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Roger Pau Monne <roger.pau@citrix.com>
To: xen-devel@lists.xen.org
Cc: Ian Jackson <ian.jackson@eu.citrix.com>,
	Roger Pau Monne <roger.pau@citrix.com>
Subject: [PATCH v10 15/19] libxl: call hotplug scripts for disk devices from libxl
Date: Fri, 20 Jul 2012 15:12:24 +0100	[thread overview]
Message-ID: <1342793548-10239-16-git-send-email-roger.pau@citrix.com> (raw)
In-Reply-To: <1342793548-10239-1-git-send-email-roger.pau@citrix.com>

Since most of the needed work is already done in previous patches,
this patch only contains the necessary code to call hotplug scripts
for disk devices, that should be called when the device is added or
removed from a guest.

We will chain the launch of the disk hotplug scripts after the
device_backend_callback callback, or directly from
libxl__initiate_device_{add,remove} if the device is already in the
desired state.

Changes since v8:

 * Print "hotplug_error" xenstore entry if hotplug execution fails and
   hotplug_error contains information.

Changes since v5:

 * Added common exit point using the device_hotplug_done function.

 * Changed the "what" field in ao_device to "const char *".

Changes since v4:

 * Init args and env to NULL.

 * Correctly propagate errors from libxl__get_hotplug_script_info.

 * Replaced if in libxl__ev_child_inuse with asserts.

 * Renamed fork_cb to child_death_cb.

 * Move deregistration of device_hotplug_timeout_cb to the top of the
   function.

 * Removed "pid" field from libxl__ao_device struct.

 * Moved arraysize declaration.

 * Fixed diff complain about no newline at the end of libxl_netbsd.c.

Changes since v2:

 * Added array size check with assert.

 * Added NetBSD code (so compilation is not broken).

 * Removed a check for null in device_hotplug_timeout_cb.

Changes since v1:

 * Moved all the event related code that was inside libxl_linux.c into
   libxl_device.c, so the flow of the device addition/removal event is
   all in the same file.

Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Roger Pau Monne <roger.pau@citrix.com>
---
 tools/hotplug/Linux/xen-backend.rules     |    6 +-
 tools/hotplug/Linux/xen-hotplug-common.sh |    6 ++
 tools/libxl/libxl.c                       |   10 ++
 tools/libxl/libxl_device.c                |  133 ++++++++++++++++++++++++++++-
 tools/libxl/libxl_internal.h              |   20 ++++-
 tools/libxl/libxl_linux.c                 |   97 +++++++++++++++++++++
 tools/libxl/libxl_netbsd.c                |    8 ++
 7 files changed, 274 insertions(+), 6 deletions(-)

diff --git a/tools/hotplug/Linux/xen-backend.rules b/tools/hotplug/Linux/xen-backend.rules
index 405387f..d55ff11 100644
--- a/tools/hotplug/Linux/xen-backend.rules
+++ b/tools/hotplug/Linux/xen-backend.rules
@@ -1,11 +1,11 @@
-SUBSYSTEM=="xen-backend", KERNEL=="tap*", RUN+="/etc/xen/scripts/blktap $env{ACTION}"
-SUBSYSTEM=="xen-backend", KERNEL=="vbd*", RUN+="/etc/xen/scripts/block $env{ACTION}"
+SUBSYSTEM=="xen-backend", KERNEL=="tap*", ENV{UDEV_CALL}="1", RUN+="/etc/xen/scripts/blktap $env{ACTION}"
+SUBSYSTEM=="xen-backend", KERNEL=="vbd*", ENV{UDEV_CALL}="1", RUN+="/etc/xen/scripts/block $env{ACTION}"
 SUBSYSTEM=="xen-backend", KERNEL=="vtpm*", RUN+="/etc/xen/scripts/vtpm $env{ACTION}"
 SUBSYSTEM=="xen-backend", KERNEL=="vif2-*", RUN+="/etc/xen/scripts/vif2 $env{ACTION}"
 SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ACTION=="online", RUN+="/etc/xen/scripts/vif-setup online type_if=vif"
 SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ACTION=="offline", RUN+="/etc/xen/scripts/vif-setup offline type_if=vif"
 SUBSYSTEM=="xen-backend", KERNEL=="vscsi*", RUN+="/etc/xen/scripts/vscsi $env{ACTION}"
-SUBSYSTEM=="xen-backend", ACTION=="remove", RUN+="/etc/xen/scripts/xen-hotplug-cleanup"
+SUBSYSTEM=="xen-backend", ACTION=="remove", ENV{UDEV_CALL}="1", RUN+="/etc/xen/scripts/xen-hotplug-cleanup"
 KERNEL=="evtchn", NAME="xen/%k"
 SUBSYSTEM=="xen", KERNEL=="blktap[0-9]*", NAME="xen/%k", MODE="0600"
 SUBSYSTEM=="blktap2", KERNEL=="blktap[0-9]*", NAME="xen/blktap-2/%k", MODE="0600"
diff --git a/tools/hotplug/Linux/xen-hotplug-common.sh b/tools/hotplug/Linux/xen-hotplug-common.sh
index 8f6557d..4a7bc73 100644
--- a/tools/hotplug/Linux/xen-hotplug-common.sh
+++ b/tools/hotplug/Linux/xen-hotplug-common.sh
@@ -15,6 +15,12 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #
 
+# Hack to prevent the execution of hotplug scripts from udev if the domain
+# has been launched from libxl
+if [ -n "${UDEV_CALL}" ] && \
+   xenstore-read "libxl/disable_udev" >/dev/null 2>&1; then
+    exit 0
+fi
 
 dir=$(dirname "$0")
 . "$dir/hotplugpath.sh"
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 5c5c876..25d9786 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1822,6 +1822,11 @@ static void device_disk_add(libxl__egc *egc, uint32_t domid,
                 flexarray_append(back, "params");
                 flexarray_append(back, dev);
 
+                flexarray_append(back, "script");
+                flexarray_append(back, GCSPRINTF("%s/%s",
+                                                 libxl__xen_script_dir_path(),
+                                                 "block"));
+
                 assert(device->backend_kind == LIBXL__DEVICE_KIND_VBD);
                 break;
             case LIBXL_DISK_BACKEND_TAP:
@@ -1837,6 +1842,11 @@ static void device_disk_add(libxl__egc *egc, uint32_t domid,
                     libxl__device_disk_string_of_format(disk->format),
                     disk->pdev_path));
 
+                flexarray_append(back, "script");
+                flexarray_append(back, GCSPRINTF("%s/%s",
+                                                 libxl__xen_script_dir_path(),
+                                                 "blktap"));
+
                 /* now create a phy device to export the device to the guest */
                 goto do_backend_phy;
             case LIBXL_DISK_BACKEND_QDISK:
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index d730b39..0632952 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -410,9 +410,12 @@ void libxl__prepare_ao_device(libxl__ao *ao, libxl__ao_device *aodev)
     aodev->ao = ao;
     aodev->rc = 0;
     aodev->dev = NULL;
-    /* Initialize timer for QEMU Bodge */
+    /* Initialize timer for QEMU Bodge and hotplug execution */
     libxl__ev_time_init(&aodev->timeout);
     aodev->active = 1;
+    /* We init this here because we might call device_hotplug_done
+     * without actually calling any hotplug script */
+    libxl__ev_child_init(&aodev->child);
 }
 
 void libxl__prepare_ao_devices(libxl__ao *ao, libxl__ao_devices *aodevs)
@@ -614,6 +617,15 @@ static void device_backend_callback(libxl__egc *egc, libxl__ev_devstate *ds,
 static void device_backend_cleanup(libxl__gc *gc,
                                    libxl__ao_device *aodev);
 
+static void device_hotplug(libxl__egc *egc, libxl__ao_device *aodev);
+
+static void device_hotplug_timeout_cb(libxl__egc *egc, libxl__ev_time *ev,
+                                      const struct timeval *requested_abs);
+
+static void device_hotplug_child_death_cb(libxl__egc *egc,
+                                          libxl__ev_child *child,
+                                          pid_t pid, int status);
+
 static void device_hotplug_done(libxl__egc *egc, libxl__ao_device *aodev);
 
 void libxl__wait_device_connection(libxl__egc *egc, libxl__ao_device *aodev)
@@ -639,7 +651,7 @@ void libxl__wait_device_connection(libxl__egc *egc, libxl__ao_device *aodev)
          * If Qemu is running, it will set the state of the device to
          * 4 directly, without waiting in state 2 for any hotplug execution.
          */
-        device_hotplug_done(egc, aodev);
+        device_hotplug(egc, aodev);
         return;
     }
 
@@ -773,6 +785,9 @@ static void device_qemu_timeout(libxl__egc *egc, libxl__ev_time *ev,
     rc = libxl__xs_write_checked(gc, XBT_NULL, state_path, "6");
     if (rc) goto out;
 
+    device_hotplug(egc, aodev);
+    return;
+
 out:
     aodev->rc = rc;
     device_hotplug_done(egc, aodev);
@@ -798,6 +813,9 @@ static void device_backend_callback(libxl__egc *egc, libxl__ev_devstate *ds,
         goto out;
     }
 
+    device_hotplug(egc, aodev);
+    return;
+
 out:
     aodev->rc = rc;
     device_hotplug_done(egc, aodev);
@@ -810,6 +828,112 @@ static void device_backend_cleanup(libxl__gc *gc, libxl__ao_device *aodev)
     libxl__ev_devstate_cancel(gc, &aodev->backend_ds);
 }
 
+static void device_hotplug(libxl__egc *egc, libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+    char *be_path = libxl__device_backend_path(gc, aodev->dev);
+    char **args = NULL, **env = NULL;
+    int rc = 0;
+    int hotplug;
+    pid_t pid;
+
+    /* Check if we have to execute hotplug scripts for this device
+     * and return the necessary args/env vars for execution */
+    hotplug = libxl__get_hotplug_script_info(gc, aodev->dev, &args, &env,
+                                             aodev->action);
+    switch (hotplug) {
+    case 0:
+        /* no hotplug script to execute */
+        goto out;
+    case 1:
+        /* execute hotplug script */
+        break;
+    default:
+        /* everything else is an error */
+        LOG(ERROR, "unable to get args/env to execute hotplug script for "
+                   "device %s", libxl__device_backend_path(gc, aodev->dev));
+        rc = hotplug;
+        goto out;
+    }
+
+    /* Set hotplug timeout */
+    rc = libxl__ev_time_register_rel(gc, &aodev->timeout,
+                                     device_hotplug_timeout_cb,
+                                     LIBXL_HOTPLUG_TIMEOUT * 1000);
+    if (rc) {
+        LOG(ERROR, "unable to register timeout for hotplug device %s", be_path);
+        goto out;
+    }
+
+    aodev->what = GCSPRINTF("%s %s", args[0], args[1]);
+    LOG(DEBUG, "calling hotplug script: %s %s", args[0], args[1]);
+
+    /* fork and execute hotplug script */
+    pid = libxl__ev_child_fork(gc, &aodev->child, device_hotplug_child_death_cb);
+    if (pid == -1) {
+        LOG(ERROR, "unable to fork");
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    if (!pid) {
+        /* child */
+        libxl__exec(gc, -1, -1, -1, args[0], args, env);
+        /* notreached */
+        abort();
+    }
+
+    assert(libxl__ev_child_inuse(&aodev->child));
+
+    return;
+
+out:
+    aodev->rc = rc;
+    device_hotplug_done(egc, aodev);
+    return;
+}
+
+static void device_hotplug_timeout_cb(libxl__egc *egc, libxl__ev_time *ev,
+                                      const struct timeval *requested_abs)
+{
+    libxl__ao_device *aodev = CONTAINER_OF(ev, *aodev, timeout);
+    STATE_AO_GC(aodev->ao);
+
+    libxl__ev_time_deregister(gc, &aodev->timeout);
+
+    assert(libxl__ev_child_inuse(&aodev->child));
+    LOG(DEBUG, "killing hotplug script %s because of timeout", aodev->what);
+    if (kill(aodev->child.pid, SIGKILL)) {
+        LOGEV(ERROR, errno, "unable to kill hotplug script %s [%ld]",
+                            aodev->what, (unsigned long)aodev->child.pid);
+    }
+
+    return;
+}
+
+static void device_hotplug_child_death_cb(libxl__egc *egc,
+                                          libxl__ev_child *child,
+                                          pid_t pid, int status)
+{
+    libxl__ao_device *aodev = CONTAINER_OF(child, *aodev, child);
+    STATE_AO_GC(aodev->ao);
+    char *be_path = libxl__device_backend_path(gc, aodev->dev);
+    char *hotplug_error;
+
+    if (status) {
+        libxl_report_child_exitstatus(CTX, LIBXL__LOG_ERROR,
+                                      aodev->what, pid, status);
+        hotplug_error = libxl__xs_read(gc, XBT_NULL,
+                                       GCSPRINTF("%s/hotplug-error", be_path));
+        if (hotplug_error)
+            LOG(ERROR, "reason of failure reported by hotplug script: %s",
+                       hotplug_error);
+        aodev->rc = ERROR_FAIL;
+    }
+
+    device_hotplug_done(egc, aodev);
+}
+
 static void device_hotplug_done(libxl__egc *egc, libxl__ao_device *aodev)
 {
     STATE_AO_GC(aodev->ao);
@@ -818,6 +942,11 @@ static void device_hotplug_done(libxl__egc *egc, libxl__ao_device *aodev)
     xs_transaction_t t = 0;
     int rc;
 
+    /* Clean events and check reentrancy */
+    libxl__ev_time_deregister(gc, &aodev->timeout);
+    assert(!libxl__ev_child_inuse(&aodev->child));
+
+    /* Clean xenstore if it's a disconnection */
     if (aodev->action == DEVICE_DISCONNECT) {
         for (;;) {
             rc = libxl__xs_transaction_start(gc, &t);
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 3d87030..786b534 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -74,6 +74,7 @@
 
 #define LIBXL_INIT_TIMEOUT 10
 #define LIBXL_DESTROY_TIMEOUT 10
+#define LIBXL_HOTPLUG_TIMEOUT 10
 #define LIBXL_DEVICE_MODEL_START_TIMEOUT 10
 #define LIBXL_QEMU_BODGE_TIMEOUT 2
 #define LIBXL_XENCONSOLE_LIMIT 1048576
@@ -1792,11 +1793,14 @@ struct libxl__ao_device {
     int active;
     int rc;
     libxl__ev_devstate backend_ds;
-    /* Bodge for Qemu devices */
+    /* Bodge for Qemu devices, also used for timeout of hotplug execution */
     libxl__ev_time timeout;
     /* Used internally to have a reference to the upper libxl__ao_devices
      * struct when present */
     libxl__ao_devices *aodevs;
+    /* device hotplug execution */
+    const char *what;
+    libxl__ev_child child;
 };
 
 /* Helper struct to simply the plug/unplug of multiple devices at the same
@@ -1926,6 +1930,20 @@ _hidden void libxl__wait_device_connection(libxl__egc*,
 _hidden void libxl__initiate_device_remove(libxl__egc *egc,
                                            libxl__ao_device *aodev);
 
+/*
+ * libxl__get_hotplug_script_info returns the args and env that should
+ * be passed to the hotplug script for the requested device.
+ *
+ * Since a device might not need to execute any hotplug script, this function
+ * can return the following values:
+ * < 0: Error
+ * 0: No need to execute hotplug script
+ * 1: Execute hotplug script
+ */
+_hidden int libxl__get_hotplug_script_info(libxl__gc *gc, libxl__device *dev,
+                                           char ***args, char ***env,
+                                           libxl__device_action action);
+
 /*----- local disk attach: attach a disk locally to run the bootloader -----*/
 
 typedef struct libxl__disk_local_state libxl__disk_local_state;
diff --git a/tools/libxl/libxl_linux.c b/tools/libxl/libxl_linux.c
index 0169b2f..97b3fd4 100644
--- a/tools/libxl/libxl_linux.c
+++ b/tools/libxl/libxl_linux.c
@@ -77,3 +77,100 @@ char *libxl__devid_to_localdev(libxl__gc *gc, int devid)
                 "%d", minor & (nr_parts - 1));
     return ret;
 }
+
+/* Hotplug scripts helpers */
+
+static char **get_hotplug_env(libxl__gc *gc, libxl__device *dev)
+{
+    char *be_path = libxl__device_backend_path(gc, dev);
+    char *script;
+    const char *type = libxl__device_kind_to_string(dev->backend_kind);
+    char **env;
+    int nr = 0;
+
+    script = libxl__xs_read(gc, XBT_NULL,
+                            GCSPRINTF("%s/%s", be_path, "script"));
+    if (!script) {
+        LOGEV(ERROR, errno, "unable to read script from %s", be_path);
+        return NULL;
+    }
+
+    const int arraysize = 9;
+    GCNEW_ARRAY(env, arraysize);
+    env[nr++] = "script";
+    env[nr++] = script;
+    env[nr++] = "XENBUS_TYPE";
+    env[nr++] = libxl__strdup(gc, type);
+    env[nr++] = "XENBUS_PATH";
+    env[nr++] = GCSPRINTF("backend/%s/%u/%d", type, dev->domid, dev->devid);
+    env[nr++] = "XENBUS_BASE_PATH";
+    env[nr++] = "backend";
+    env[nr++] = NULL;
+    assert(nr == arraysize);
+
+    return env;
+}
+
+/* Hotplug scripts caller functions */
+
+static int libxl__hotplug_disk(libxl__gc *gc, libxl__device *dev,
+                               char ***args, char ***env,
+                               libxl__device_action action)
+{
+    char *be_path = libxl__device_backend_path(gc, dev);
+    char *script;
+    int nr = 0, rc = 0;
+
+    script = libxl__xs_read(gc, XBT_NULL,
+                            GCSPRINTF("%s/%s", be_path, "script"));
+    if (!script) {
+        LOGEV(ERROR, errno, "unable to read script from %s", be_path);
+        rc = ERROR_FAIL;
+        goto error;
+    }
+
+    *env = get_hotplug_env(gc, dev);
+    if (!*env) {
+        rc = ERROR_FAIL;
+        goto error;
+    }
+
+    const int arraysize = 3;
+    GCNEW_ARRAY(*args, arraysize);
+    (*args)[nr++] = script;
+    (*args)[nr++] = action == DEVICE_CONNECT ? "add" : "remove";
+    (*args)[nr++] = NULL;
+    assert(nr == arraysize);
+
+    rc = 1;
+
+error:
+    return rc;
+}
+
+int libxl__get_hotplug_script_info(libxl__gc *gc, libxl__device *dev,
+                                   char ***args, char ***env,
+                                   libxl__device_action action)
+{
+    char *disable_udev = libxl__xs_read(gc, XBT_NULL, DISABLE_UDEV_PATH);
+    int rc;
+
+    /* Check if we have to run hotplug scripts */
+    if (!disable_udev) {
+        rc = 0;
+        goto out;
+    }
+
+    switch (dev->backend_kind) {
+    case LIBXL__DEVICE_KIND_VBD:
+        rc = libxl__hotplug_disk(gc, dev, args, env, action);
+        break;
+    default:
+        /* No need to execute any hotplug scripts */
+        rc = 0;
+        break;
+    }
+
+out:
+    return rc;
+}
diff --git a/tools/libxl/libxl_netbsd.c b/tools/libxl/libxl_netbsd.c
index dbf5f71..a2f8d3f 100644
--- a/tools/libxl/libxl_netbsd.c
+++ b/tools/libxl/libxl_netbsd.c
@@ -30,3 +30,11 @@ char *libxl__devid_to_localdev(libxl__gc *gc, int devid)
     /* TODO */
     return NULL;
 }
+
+/* Hotplug scripts caller functions */
+int libxl__get_hotplug_script_info(libxl__gc *gc, libxl__device *dev,
+                                   char ***args, char ***env,
+                                   libxl__device_action action)
+{
+    return 0;
+}
-- 
1.7.7.5 (Apple Git-26)

  parent reply	other threads:[~2012-07-20 14:12 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-20 14:12 [PATCH v10 01/19] execute hotplug scripts from libxl v10 Roger Pau Monne
2012-07-20 14:12 ` [PATCH v10 01/19] libxl: check backend state before setting it to "closing" Roger Pau Monne
2012-07-20 14:12 ` [PATCH v10 02/19] libxl: change ao_device_remove to ao_device Roger Pau Monne
2012-07-20 16:35   ` Ian Jackson
2012-07-20 14:12 ` [PATCH v10 03/19] libxl: move device model creation prototypes Roger Pau Monne
2012-07-20 14:12 ` [PATCH v10 04/19] libxl: convert libxl_domain_destroy to an async op Roger Pau Monne
2012-07-20 14:12 ` [PATCH v10 05/19] libxl: move bootloader data strucutres and prototypes Roger Pau Monne
2012-07-20 17:21   ` Ian Jackson
2012-07-20 14:12 ` [PATCH v10 06/19] libxl: refactor disk addition to take a helper Roger Pau Monne
2012-07-20 17:24   ` Ian Jackson
2012-07-20 14:12 ` [PATCH v10 07/19] libxl: convert libxl__device_disk_local_attach to an async op Roger Pau Monne
2012-07-20 18:03   ` Ian Jackson
2012-07-23 11:32     ` Roger Pau Monne
2012-07-20 14:12 ` [PATCH v10 08/19] libxl: rename vifs to nics Roger Pau Monne
2012-07-20 14:12 ` [PATCH v10 09/19] libxl: convert libxl_device_disk_add to an async op Roger Pau Monne
2012-07-20 18:04   ` Ian Jackson
2012-07-20 14:12 ` [PATCH v10 10/19] libxl: convert libxl_device_nic_add to an async operation Roger Pau Monne
2012-07-20 14:12 ` [PATCH v10 11/19] libxl: add option to choose who executes hotplug scripts Roger Pau Monne
2012-07-20 14:12 ` [PATCH v10 12/19] libxl: rename _IOEMU nic type to VIF_IOEMU Roger Pau Monne
2012-07-20 16:34   ` Ian Campbell
2012-07-20 16:39     ` Ian Campbell
2012-07-20 14:12 ` [PATCH v10 13/19] libxl: set correct nic type depending on the guest Roger Pau Monne
2012-07-20 18:06   ` Ian Jackson
2012-07-20 14:12 ` [PATCH v10 14/19] libxl: use libxl__xs_path_cleanup on device_destroy Roger Pau Monne
2012-07-20 15:38   ` Ian Campbell
2012-07-20 14:12 ` Roger Pau Monne [this message]
2012-07-20 15:20   ` [PATCH v10 15/19] libxl: call hotplug scripts for disk devices from libxl Ian Campbell
2012-07-20 14:12 ` [PATCH v10 16/19] libxl: call hotplug scripts for nic " Roger Pau Monne
2012-07-20 16:01   ` Ian Campbell
2012-07-20 16:12     ` Ian Campbell
2012-07-20 16:36     ` Ian Campbell
2012-07-23  9:22     ` Roger Pau Monne
2012-07-20 16:03   ` Ian Campbell
2012-07-20 14:12 ` [PATCH v10 17/19] libxl: convert libxl_device_vkb_add to an async operation Roger Pau Monne
2012-07-20 18:08   ` Ian Jackson
2012-07-23  8:58     ` Roger Pau Monne
2012-07-23  9:26       ` Ian Campbell
2012-07-23 11:44       ` Ian Jackson
2012-07-20 14:12 ` [PATCH v10 18/19] libxl: convert libxl_device_vfb_add " Roger Pau Monne
2012-07-20 18:11   ` Ian Jackson
2012-07-23 11:58     ` Roger Pau Monne
2012-07-20 14:12 ` [PATCH v10 19/19] xl: main_blockdetach don't call destroy if remove succeeds Roger Pau Monne
2012-07-20 14:55   ` Ian Campbell
2012-07-23 12:17 ` [PATCH v10 01/19] execute hotplug scripts from libxl v10 Ian Campbell

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=1342793548-10239-16-git-send-email-roger.pau@citrix.com \
    --to=roger.pau@citrix.com \
    --cc=ian.jackson@eu.citrix.com \
    --cc=xen-devel@lists.xen.org \
    /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).