All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v9 00/15] execute hotplug scripts from libxl
@ 2012-07-13  9:44 Roger Pau Monne
  2012-07-13  9:44 ` [PATCH v9 01/17] libxl: change ao_device_remove to ao_device Roger Pau Monne
                   ` (16 more replies)
  0 siblings, 17 replies; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-13  9:44 UTC (permalink / raw)
  To: xen-devel

This series have been splitted into several patches, to make them 
easier to review. Also the amount of changes introduced is quite 
important, since apart from all the hotplug necessary functions and
modifications, libxl_domain_destroy has been converted to an async op.
This was necessary in order to have async operations during device
removal.

Also, as an important change, disk and nics are added at different
points for HVM and device model based guests, since we need the disk
in order to start Qemu, but the nic hotplug scripts should be called
at a later point, when Qemu has created the corresponding tap device.

This version includes changes requested by Ian Campbell, and two new 
patches that convert vkb and vfb to async functions. Also since Qdisk, 
vfb and vkb don't follow the disconnection protocol (probably because 
Qemu is already dead when that happens), we don't wait for them to 
reach state "closed", and just clean the relevant xenstore entries.

 [PATCH v9 01/15] libxl: change ao_device_remove to ao_device
*[PATCH v9 02/15] libxl: move device model creation prototypes
*[PATCH v9 03/15] libxl: convert libxl_domain_destroy to an async op
*[PATCH v9 04/15] libxl: move bootloader data strucutres and
 [PATCH v9 05/15] libxl: refactor disk addition to take a helper
 [PATCH v9 06/15] libxl: convert libxl__device_disk_local_attach to
 [PATCH v9 07/15] libxl: rename vifs to nics
 [PATCH v9 08/15] libxl: convert libxl_device_disk_add to an async op
*[PATCH v9 09/15] libxl: convert libxl_device_nic_add to an async
*[PATCH v9 10/15] libxl: add option to choose who executes hotplug
*[PATCH v9 11/15] libxl: rename _IOEMU nic type to VIF_IOEMU
 [PATCH v9 12/15] libxl: set correct nic type depending on the guest
*[PATCH v9 13/15] libxl: use libxl__xs_path_cleanup on device_destroy
*[PATCH v9 14/15] libxl: call hotplug scripts for disk devices from
*[PATCH v9 15/15] libxl: call hotplug scripts for nic devices from

* = Acked

New Patches:

 [PATCH v9 16/17] libxl: convert libxl_device_vkb_add to an async
 [PATCH v9 17/17] libxl: convert libxl_device_vfb_add to an async

^ permalink raw reply	[flat|nested] 40+ messages in thread

* [PATCH v9 01/17] libxl: change ao_device_remove to ao_device
  2012-07-13  9:44 [PATCH v9 00/15] execute hotplug scripts from libxl Roger Pau Monne
@ 2012-07-13  9:44 ` Roger Pau Monne
  2012-07-18 16:29   ` Ian Jackson
  2012-07-13  9:44 ` [PATCH v9 02/17] libxl: move device model creation prototypes Roger Pau Monne
                   ` (15 subsequent siblings)
  16 siblings, 1 reply; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-13  9:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Roger Pau Monne

Introduce a new structure to track state of device backends, that will
be used in following patches on this series.

This structure if used for both device creation and device
destruction and removes libxl__ao_device_remove.

Changes since v8:

 * Don't wait for QDISK, VKBD or VFB to disconnect, since Qemu doesn't
   honour the disconnection protocol.

Changes since v6:

 * Use libxl__xs_transaction helpers.

Changes since v5:

 * Added a common exit point for device addition/destruction that
   removes backend and frontend entries (on destruction).

 * Posponed the introduction of the base and active fields in the
   ao_device struct.

 * Don't call libxl__ev_devstate_init, since _wait will do it.

 * Removed "action being performed" comment.

Changes sinve v4:

 * Added a more detailed comment in _prepare and _initiate header.

 * Removed an unnecessary state check from
   libxl_initiate_device_remove.

Changes since v2:

 * Remove unnecessary comments in libxl__ao_device.

 * Change libxl__device_cb to device_addrm_aocomplete.

 * Rename aorm parameter in device_addrm_aocomplete to aodev.

 * Use a macro to define {nic,disk,vkb,vfb}_{remove,destroy}
   functions.

 * Rename libxl__init_ao_device to libxl__prepare_ao_device and add a
   comment explaining why we need to set active to 1.

 * Replace al uses of aorm with aodev.

Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Roger Pau Monne <roger.pau@citrix.com>
---
 tools/libxl/libxl.c          |  224 +++++++++++++++---------------------------
 tools/libxl/libxl.h          |   15 ++-
 tools/libxl/libxl_device.c   |  160 +++++++++++++++++++++---------
 tools/libxl/libxl_internal.h |   58 ++++++++++--
 tools/libxl/xl_cmdimpl.c     |    2 +-
 5 files changed, 258 insertions(+), 201 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 4277745..777484c 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1503,6 +1503,26 @@ int libxl_vncviewer_exec(libxl_ctx *ctx, uint32_t domid, int autopass)
 
 /******************************************************************************/
 
+/* generic callback for devices that only need to set ao_complete */
+static void device_addrm_aocomplete(libxl__egc *egc, libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+
+    if (aodev->rc) {
+        LOGE(ERROR, "unable to %s %s with id %u",
+                    aodev->action == DEVICE_CONNECT ? "add" : "remove",
+                    libxl__device_kind_to_string(aodev->dev->kind),
+                    aodev->dev->devid);
+        goto out;
+    }
+
+out:
+    libxl__ao_complete(egc, ao, aodev->rc);
+    return;
+}
+
+/******************************************************************************/
+
 int libxl__device_disk_setdefault(libxl__gc *gc, libxl_device_disk *disk)
 {
     int rc;
@@ -1680,42 +1700,6 @@ int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *dis
     return rc;
 }
 
-int libxl_device_disk_remove(libxl_ctx *ctx, uint32_t domid,
-                             libxl_device_disk *disk,
-                             const libxl_asyncop_how *ao_how)
-{
-    AO_CREATE(ctx, domid, ao_how);
-    libxl__device device;
-    int rc;
-
-    rc = libxl__device_from_disk(gc, domid, disk, &device);
-    if (rc != 0) goto out;
-
-    rc = libxl__initiate_device_remove(egc, ao, &device);
-    if (rc) goto out;
-
-    return AO_INPROGRESS;
-
-out:
-    return AO_ABORT(rc);
-}
-
-int libxl_device_disk_destroy(libxl_ctx *ctx, uint32_t domid,
-                              libxl_device_disk *disk)
-{
-    GC_INIT(ctx);
-    libxl__device device;
-    int rc;
-
-    rc = libxl__device_from_disk(gc, domid, disk, &device);
-    if (rc != 0) goto out;
-
-    rc = libxl__device_destroy(gc, &device);
-out:
-    GC_FREE;
-    return rc;
-}
-
 static void libxl__device_disk_from_xs_be(libxl__gc *gc,
                                           const char *be_path,
                                           libxl_device_disk *disk)
@@ -2080,8 +2064,9 @@ int libxl__device_disk_local_detach(libxl__gc *gc, libxl_device_disk *disk)
             if (disk->vdev != NULL) {
                 libxl_device_disk_remove(gc->owner, LIBXL_TOOLSTACK_DOMID,
                         disk, 0);
+                /* fixme-ao */
                 rc = libxl_device_disk_destroy(gc->owner,
-                        LIBXL_TOOLSTACK_DOMID, disk);
+                        LIBXL_TOOLSTACK_DOMID, disk, 0);
             }
             break;
         default:
@@ -2249,42 +2234,6 @@ out:
     return rc;
 }
 
-int libxl_device_nic_remove(libxl_ctx *ctx, uint32_t domid,
-                            libxl_device_nic *nic,
-                            const libxl_asyncop_how *ao_how)
-{
-    AO_CREATE(ctx, domid, ao_how);
-    libxl__device device;
-    int rc;
-
-    rc = libxl__device_from_nic(gc, domid, nic, &device);
-    if (rc != 0) goto out;
-
-    rc = libxl__initiate_device_remove(egc, ao, &device);
-    if (rc) goto out;
-
-    return AO_INPROGRESS;
-
-out:
-    return AO_ABORT(rc);
-}
-
-int libxl_device_nic_destroy(libxl_ctx *ctx, uint32_t domid,
-                                  libxl_device_nic *nic)
-{
-    GC_INIT(ctx);
-    libxl__device device;
-    int rc;
-
-    rc = libxl__device_from_nic(gc, domid, nic, &device);
-    if (rc != 0) goto out;
-
-    rc = libxl__device_destroy(gc, &device);
-out:
-    GC_FREE;
-    return rc;
-}
-
 static void libxl__device_nic_from_xs_be(libxl__gc *gc,
                                          const char *be_path,
                                          libxl_device_nic *nic)
@@ -2611,42 +2560,6 @@ out:
     return rc;
 }
 
-int libxl_device_vkb_remove(libxl_ctx *ctx, uint32_t domid,
-                            libxl_device_vkb *vkb,
-                            const libxl_asyncop_how *ao_how)
-{
-    AO_CREATE(ctx, domid, ao_how);
-    libxl__device device;
-    int rc;
-
-    rc = libxl__device_from_vkb(gc, domid, vkb, &device);
-    if (rc != 0) goto out;
-
-    rc = libxl__initiate_device_remove(egc, ao, &device);
-    if (rc) goto out;
-
-    return AO_INPROGRESS;
-
-out:
-    return AO_ABORT(rc);
-}
-
-int libxl_device_vkb_destroy(libxl_ctx *ctx, uint32_t domid,
-                                  libxl_device_vkb *vkb)
-{
-    GC_INIT(ctx);
-    libxl__device device;
-    int rc;
-
-    rc = libxl__device_from_vkb(gc, domid, vkb, &device);
-    if (rc != 0) goto out;
-
-    rc = libxl__device_destroy(gc, &device);
-out:
-    GC_FREE;
-    return rc;
-}
-
 /******************************************************************************/
 
 int libxl__device_vfb_setdefault(libxl__gc *gc, libxl_device_vfb *vfb)
@@ -2744,41 +2657,66 @@ out:
     return rc;
 }
 
-int libxl_device_vfb_remove(libxl_ctx *ctx, uint32_t domid,
-                            libxl_device_vfb *vfb,
-                            const libxl_asyncop_how *ao_how)
-{
-    AO_CREATE(ctx, domid, ao_how);
-    libxl__device device;
-    int rc;
-
-    rc = libxl__device_from_vfb(gc, domid, vfb, &device);
-    if (rc != 0) goto out;
-
-    rc = libxl__initiate_device_remove(egc, ao, &device);
-    if (rc) goto out;
-
-    return AO_INPROGRESS;
-
-out:
-    return AO_ABORT(rc);
-}
-
-int libxl_device_vfb_destroy(libxl_ctx *ctx, uint32_t domid,
-                                  libxl_device_vfb *vfb)
-{
-    GC_INIT(ctx);
-    libxl__device device;
-    int rc;
-
-    rc = libxl__device_from_vfb(gc, domid, vfb, &device);
-    if (rc != 0) goto out;
+/******************************************************************************/
 
-    rc = libxl__device_destroy(gc, &device);
-out:
-    GC_FREE;
-    return rc;
-}
+/* Macro for defining device remove/destroy functions in a compact way */
+/* The following functions are defined:
+ * libxl_device_disk_remove
+ * libxl_device_disk_destroy
+ * libxl_device_nic_remove
+ * libxl_device_nic_destroy
+ * libxl_device_vkb_remove
+ * libxl_device_vkb_destroy
+ * libxl_device_vfb_remove
+ * libxl_device_vfb_destroy
+ */
+#define DEFINE_DEVICE_REMOVE(type, removedestroy, f)                    \
+    int libxl_device_##type##_##removedestroy(libxl_ctx *ctx,           \
+        uint32_t domid, libxl_device_##type *type,                      \
+        const libxl_asyncop_how *ao_how)                                \
+    {                                                                   \
+        AO_CREATE(ctx, domid, ao_how);                                  \
+        libxl__device *device;                                          \
+        libxl__ao_device *aodev;                                        \
+        int rc;                                                         \
+                                                                        \
+        GCNEW(device);                                                  \
+        rc = libxl__device_from_##type(gc, domid, type, device);        \
+        if (rc != 0) goto out;                                          \
+                                                                        \
+        GCNEW(aodev);                                                   \
+        libxl__prepare_ao_device(ao, aodev);                            \
+        aodev->action = DEVICE_DISCONNECT;                              \
+        aodev->dev = device;                                            \
+        aodev->callback = device_addrm_aocomplete;                      \
+        aodev->force = f;                                               \
+        libxl__initiate_device_remove(egc, aodev);                      \
+                                                                        \
+    out:                                                                \
+        if (rc) return AO_ABORT(rc);                                    \
+        return AO_INPROGRESS;                                           \
+    }
+
+/* Define all remove/destroy functions and undef the macro */
+
+/* disk */
+DEFINE_DEVICE_REMOVE(disk, remove, 0)
+DEFINE_DEVICE_REMOVE(disk, destroy, 1)
+
+/* nic */
+DEFINE_DEVICE_REMOVE(nic, remove, 0)
+DEFINE_DEVICE_REMOVE(nic, destroy, 1)
+
+/* vkb */
+DEFINE_DEVICE_REMOVE(vkb, remove, 0)
+DEFINE_DEVICE_REMOVE(vkb, destroy, 1)
+
+/* vfb */
+
+DEFINE_DEVICE_REMOVE(vfb, remove, 0)
+DEFINE_DEVICE_REMOVE(vfb, destroy, 1)
+
+#undef DEFINE_DEVICE_REMOVE
 
 /******************************************************************************/
 
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index f5a8f87..c2d5c06 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -679,7 +679,8 @@ int libxl_device_disk_remove(libxl_ctx *ctx, uint32_t domid,
                              libxl_device_disk *disk,
                              const libxl_asyncop_how *ao_how);
 int libxl_device_disk_destroy(libxl_ctx *ctx, uint32_t domid,
-                              libxl_device_disk *disk);
+                              libxl_device_disk *disk,
+                              const libxl_asyncop_how *ao_how);
 
 libxl_device_disk *libxl_device_disk_list(libxl_ctx *ctx, uint32_t domid, int *num);
 int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
@@ -696,7 +697,9 @@ int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic);
 int libxl_device_nic_remove(libxl_ctx *ctx, uint32_t domid,
                             libxl_device_nic *nic,
                             const libxl_asyncop_how *ao_how);
-int libxl_device_nic_destroy(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic);
+int libxl_device_nic_destroy(libxl_ctx *ctx, uint32_t domid,
+                             libxl_device_nic *nic,
+                             const libxl_asyncop_how *ao_how);
 
 libxl_device_nic *libxl_device_nic_list(libxl_ctx *ctx, uint32_t domid, int *num);
 int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
@@ -707,14 +710,18 @@ int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb);
 int libxl_device_vkb_remove(libxl_ctx *ctx, uint32_t domid,
                             libxl_device_vkb *vkb,
                             const libxl_asyncop_how *ao_how);
-int libxl_device_vkb_destroy(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb);
+int libxl_device_vkb_destroy(libxl_ctx *ctx, uint32_t domid,
+                             libxl_device_vkb *vkb,
+                             const libxl_asyncop_how *ao_how);
 
 /* Framebuffer */
 int libxl_device_vfb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb);
 int libxl_device_vfb_remove(libxl_ctx *ctx, uint32_t domid,
                             libxl_device_vfb *vfb,
                             const libxl_asyncop_how *ao_how);
-int libxl_device_vfb_destroy(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb);
+int libxl_device_vfb_destroy(libxl_ctx *ctx, uint32_t domid,
+                             libxl_device_vfb *vfb,
+                             const libxl_asyncop_how *ao_how);
 
 /* PCI Passthrough */
 int libxl_device_pci_add(libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev);
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 3da60e1..84286b2 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -361,11 +361,13 @@ int libxl__device_disk_dev_number(const char *virtpath, int *pdisk,
     return -1;
 }
 
+/* Device AO operations */
 
-typedef struct {
-    libxl__ao *ao;
-    libxl__ev_devstate ds;
-} libxl__ao_device_remove;
+void libxl__prepare_ao_device(libxl__ao *ao, libxl__ao_device *aodev)
+{
+    aodev->ao = ao;
+    aodev->rc = 0;
+}
 
 int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
 {
@@ -441,34 +443,51 @@ out:
 
 /* Callbacks for device related operations */
 
-static void device_remove_callback(libxl__egc *egc, libxl__ev_devstate *ds,
+/* 
+ * device_backend_callback is the main callback entry point, for both device
+ * addition and removal. It gets called if we reach the desired state
+ * (XenbusStateClosed or XenbusStateInitWait). After that, all this
+ * functions get called in the order displayed below.
+ *
+ * If new device types are added, they should only need to modify the
+ * specific hotplug scripts call, which can be found in each OS specific
+ * file. If this new devices don't need a hotplug script, no modification
+ * should be needed.
+ */
+
+static void device_backend_callback(libxl__egc *egc, libxl__ev_devstate *ds,
                                    int rc);
 
-static void device_remove_cleanup(libxl__gc *gc,
-                                  libxl__ao_device_remove *aorm);
+static void device_backend_cleanup(libxl__gc *gc,
+                                   libxl__ao_device *aodev);
 
-int libxl__initiate_device_remove(libxl__egc *egc, libxl__ao *ao,
-                                  libxl__device *dev)
+static void device_xsentries_remove(libxl__egc *egc, libxl__ao_device *aodev);
+
+void libxl__initiate_device_remove(libxl__egc *egc,
+                                   libxl__ao_device *aodev)
 {
-    AO_GC;
+    STATE_AO_GC(aodev->ao);
     libxl_ctx *ctx = libxl__gc_owner(gc);
-    xs_transaction_t t;
-    char *be_path = libxl__device_backend_path(gc, dev);
+    xs_transaction_t t = 0;
+    char *be_path = libxl__device_backend_path(gc, aodev->dev);
     char *state_path = libxl__sprintf(gc, "%s/state", be_path);
-    char *state = libxl__xs_read(gc, XBT_NULL, state_path);
     int rc = 0;
-    libxl__ao_device_remove *aorm = 0;
-
-    if (!state)
-        goto out_ok;
-    if (atoi(state) != 4) {
-        libxl__device_destroy_tapdisk(gc, be_path);
-        xs_rm(ctx->xsh, XBT_NULL, be_path);
-        goto out_ok;
+
+    if (aodev->dev->backend_kind == LIBXL__DEVICE_KIND_QDISK ||
+        aodev->dev->backend_kind == LIBXL__DEVICE_KIND_VFB ||
+        aodev->dev->backend_kind == LIBXL__DEVICE_KIND_VKBD) {
+        /*
+         * Qdisk, VFB and VKBD don't honor the disconnect mechanism,
+         * so there's no point on waiting for them to reach state "closed".
+         */
+        goto out;
     }
 
 retry_transaction:
     t = xs_transaction_start(ctx->xsh);
+    if (aodev->force)
+        libxl__xs_path_cleanup(gc, t,
+                               libxl__device_frontend_path(gc, aodev->dev));
     xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/online", be_path), "0", strlen("0"));
     xs_write(ctx->xsh, t, state_path, "5", strlen("5"));
     if (!xs_transaction_end(ctx->xsh, t, 0)) {
@@ -476,45 +495,94 @@ retry_transaction:
             goto retry_transaction;
         else {
             rc = ERROR_FAIL;
-            goto out_fail;
+            goto out;
         }
     }
 
     libxl__device_destroy_tapdisk(gc, be_path);
 
-    aorm = libxl__zalloc(gc, sizeof(*aorm));
-    aorm->ao = ao;
-    libxl__ev_devstate_init(&aorm->ds);
-
-    rc = libxl__ev_devstate_wait(gc, &aorm->ds, device_remove_callback,
+    rc = libxl__ev_devstate_wait(gc, &aodev->backend_ds,
+                                 device_backend_callback,
                                  state_path, XenbusStateClosed,
                                  LIBXL_DESTROY_TIMEOUT * 1000);
-    if (rc) goto out_fail;
-
-    return 0;
+    if (rc) {
+        LOG(ERROR, "unable to remove device %s", be_path);
+        goto out;
+    }
 
- out_fail:
-    assert(rc);
-    device_remove_cleanup(gc, aorm);
-    return rc;
+    return;
 
- out_ok:
-    libxl__ao_complete(egc, ao, 0);
-    return 0;
+out:
+    aodev->rc = rc;
+    device_xsentries_remove(egc, aodev);
+    return;
 }
 
-static void device_remove_callback(libxl__egc *egc, libxl__ev_devstate *ds,
+static void device_backend_callback(libxl__egc *egc, libxl__ev_devstate *ds,
                                    int rc) {
-    libxl__ao_device_remove *aorm = CONTAINER_OF(ds, *aorm, ds);
-    libxl__gc *gc = &aorm->ao->gc;
-    libxl__ao_complete(egc, aorm->ao, rc);
-    device_remove_cleanup(gc, aorm);
+    libxl__ao_device *aodev = CONTAINER_OF(ds, *aodev, backend_ds);
+    STATE_AO_GC(aodev->ao);
+
+    device_backend_cleanup(gc, aodev);
+
+    if (rc == ERROR_TIMEDOUT && aodev->action == DEVICE_DISCONNECT &&
+        !aodev->force) {
+        aodev->force = 1;
+        libxl__initiate_device_remove(egc, aodev);
+        return;
+    }
+
+    /* Some devices (vkbd) fail to disconnect properly,
+     * but we shouldn't alarm the user if it's during
+     * domain destruction.
+     */
+    if (rc && aodev->action == DEVICE_CONNECT) {
+        LOG(ERROR, "unable to connect device with path %s",
+                   libxl__device_backend_path(gc, aodev->dev));
+        goto out;
+    } else if (rc) {
+        LOG(DEBUG, "unable to disconnect device with path %s",
+                   libxl__device_backend_path(gc, aodev->dev));
+        goto out;
+    }
+
+out:
+    aodev->rc = rc;
+    device_xsentries_remove(egc, aodev);
+    return;
 }
 
-static void device_remove_cleanup(libxl__gc *gc,
-                                  libxl__ao_device_remove *aorm) {
-    if (!aorm) return;
-    libxl__ev_devstate_cancel(gc, &aorm->ds);
+static void device_backend_cleanup(libxl__gc *gc, libxl__ao_device *aodev)
+{
+    if (!aodev) return;
+    libxl__ev_devstate_cancel(gc, &aodev->backend_ds);
+}
+
+static void device_xsentries_remove(libxl__egc *egc, libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+    char *be_path = libxl__device_backend_path(gc, aodev->dev);
+    char *fe_path = libxl__device_frontend_path(gc, aodev->dev);
+    xs_transaction_t t = 0;
+    int rc;
+
+    if (aodev->action == DEVICE_DISCONNECT) {
+        for (;;) {
+            rc = libxl__xs_transaction_start(gc, &t);
+            if (rc) goto out;
+
+            libxl__xs_path_cleanup(gc, t, fe_path);
+            libxl__xs_path_cleanup(gc, t, be_path);
+
+            rc = libxl__xs_transaction_commit(gc, &t);
+            if (!rc) break;
+            if (rc < 0) goto out;
+        }
+    }
+
+out:
+    aodev->callback(egc, aodev);
+    return;
 }
 
 int libxl__wait_for_device_model(libxl__gc *gc,
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 2781398..339f9a6 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -899,13 +899,6 @@ _hidden const char *libxl__device_nic_devname(libxl__gc *gc,
                                               uint32_t devid,
                                               libxl_nic_type type);
 
-/* Arranges that dev will be removed from its guest.  When
- * this is done, the ao will be completed.  An error
- * return from libxl__initiate_device_remove means that the ao
- * will _not_ be completed and the caller must do so. */
-_hidden int libxl__initiate_device_remove(libxl__egc*, libxl__ao*,
-                                          libxl__device *dev);
-
 /*
  * libxl__ev_devstate - waits a given time for a device to
  * reach a given state.  Follows the libxl_ev_* conventions.
@@ -2007,6 +2000,57 @@ _hidden void libxl__bootloader_init(libxl__bootloader_state *bl);
  * If callback is passed rc==0, will have updated st->info appropriately */
 _hidden void libxl__bootloader_run(libxl__egc*, libxl__bootloader_state *st);
 
+/*----- device addition/removal -----*/
+
+/* Action to perform (either connect or disconnect) */
+typedef enum {
+    DEVICE_CONNECT,
+    DEVICE_DISCONNECT
+} libxl__device_action;
+
+typedef struct libxl__ao_device libxl__ao_device;
+typedef void libxl__device_callback(libxl__egc*, libxl__ao_device*);
+
+/* This functions sets the necessary libxl__ao_device struct values to use
+ * safely inside functions. It marks the operation as "active"
+ * since we need to be sure that all device status structs are set
+ * to active before start queueing events, or we might call
+ * ao_complete before all devices had finished
+ *
+ * libxl__initiate_device_{remove/addition} should not be called without
+ * calling libxl__prepare_ao_device first, since it initializes the private
+ * fields of the struct libxl__ao_device to what this functions expect.
+ *
+ * Once _prepare has been called on a libxl__ao_device, it is safe to just
+ * discard this struct, there's no need to call any destroy function.
+ * _prepare can also be called multiple times with the same libxl__ao_device.
+ */
+_hidden void libxl__prepare_ao_device(libxl__ao *ao, libxl__ao_device *aodev);
+
+struct libxl__ao_device {
+    /* filled in by user */
+    libxl__ao *ao;
+    libxl__device_action action;
+    libxl__device *dev;
+    int force;
+    libxl__device_callback *callback;
+    /* private for implementation */
+    int rc;
+    libxl__ev_devstate backend_ds;
+};
+
+/* Arranges that dev will be removed to the guest, and the
+ * hotplug scripts will be executed (if necessary). When
+ * this is done (or an error happens), the callback in
+ * aodev->callback will be called.
+ *
+ * The libxl__ao_device passed to this function should be
+ * prepared using libxl__prepare_ao_device prior to calling
+ * this function.
+ */
+_hidden void libxl__initiate_device_remove(libxl__egc *egc,
+                                           libxl__ao_device *aodev);
+
 /*----- Domain creation -----*/
 
 typedef struct libxl__domain_create_state libxl__domain_create_state;
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index e2aa8592..29523e1 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -5416,7 +5416,7 @@ int main_blockdetach(int argc, char **argv)
     if (libxl_device_disk_remove(ctx, domid, &disk, 0)) {
         fprintf(stderr, "libxl_device_disk_remove failed.\n");
     } else
-        libxl_device_disk_destroy(ctx, domid, &disk);
+        libxl_device_disk_destroy(ctx, domid, &disk, 0);
     return 0;
 }
 
-- 
1.7.7.5 (Apple Git-26)

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v9 02/17] libxl: move device model creation prototypes
  2012-07-13  9:44 [PATCH v9 00/15] execute hotplug scripts from libxl Roger Pau Monne
  2012-07-13  9:44 ` [PATCH v9 01/17] libxl: change ao_device_remove to ao_device Roger Pau Monne
@ 2012-07-13  9:44 ` Roger Pau Monne
  2012-07-13  9:44 ` [PATCH v9 03/17] libxl: convert libxl_domain_destroy to an async op Roger Pau Monne
                   ` (14 subsequent siblings)
  16 siblings, 0 replies; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-13  9:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Roger Pau Monne

Move prototypes regarding device model creation, since they will
depend on domain destruction in future patches.

This patch is pure code motion.

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/libxl/libxl_internal.h |   75 ++++++++++++++++++++---------------------
 1 files changed, 37 insertions(+), 38 deletions(-)

diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 339f9a6..61fd100 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1143,44 +1143,6 @@ static inline int libxl__spawn_inuse(libxl__spawn_state *ss)
 _hidden int libxl__spawn_record_pid(libxl__gc*, libxl__spawn_state*,
                                     pid_t innerchild);
 
-/*----- device model creation -----*/
-
-/* First layer; wraps libxl__spawn_spawn. */
-
-typedef struct libxl__dm_spawn_state libxl__dm_spawn_state;
-
-typedef void libxl__dm_spawn_cb(libxl__egc *egc, libxl__dm_spawn_state*,
-                                int rc /* if !0, error was logged */);
-
-struct libxl__dm_spawn_state {
-    /* mixed - spawn.ao must be initialised by user; rest is private: */
-    libxl__spawn_state spawn;
-    /* filled in by user, must remain valid: */
-    uint32_t guest_domid; /* domain being served */
-    libxl_domain_config *guest_config;
-    libxl__domain_build_state *build_state; /* relates to guest_domid */
-    libxl__dm_spawn_cb *callback;
-};
-
-_hidden void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state*);
-
-/* Stubdom device models. */
-
-typedef struct {
-    /* Mixed - user must fill in public parts EXCEPT callback,
-     * which may be undefined on entry.  (See above for details) */
-    libxl__dm_spawn_state dm; /* the stub domain device model */
-    /* filled in by user, must remain valid: */
-    libxl__dm_spawn_cb *callback; /* called as callback(,&sdss->dm,) */
-    /* private to libxl__spawn_stub_dm: */
-    libxl_domain_config dm_config;
-    libxl__domain_build_state dm_state;
-    libxl__dm_spawn_state pvqemu;
-} libxl__stub_dm_spawn_state;
-
-_hidden void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state*);
-
-
 /*
  * libxl__wait_for_offspring - Wait for child state
  * gc: allocation pool
@@ -2051,6 +2013,43 @@ struct libxl__ao_device {
 _hidden void libxl__initiate_device_remove(libxl__egc *egc,
                                            libxl__ao_device *aodev);
 
+/*----- device model creation -----*/
+
+/* First layer; wraps libxl__spawn_spawn. */
+
+typedef struct libxl__dm_spawn_state libxl__dm_spawn_state;
+
+typedef void libxl__dm_spawn_cb(libxl__egc *egc, libxl__dm_spawn_state*,
+                                int rc /* if !0, error was logged */);
+
+struct libxl__dm_spawn_state {
+    /* mixed - spawn.ao must be initialised by user; rest is private: */
+    libxl__spawn_state spawn;
+    /* filled in by user, must remain valid: */
+    uint32_t guest_domid; /* domain being served */
+    libxl_domain_config *guest_config;
+    libxl__domain_build_state *build_state; /* relates to guest_domid */
+    libxl__dm_spawn_cb *callback;
+};
+
+_hidden void libxl__spawn_local_dm(libxl__egc *egc, libxl__dm_spawn_state*);
+
+/* Stubdom device models. */
+
+typedef struct {
+    /* Mixed - user must fill in public parts EXCEPT callback,
+     * which may be undefined on entry.  (See above for details) */
+    libxl__dm_spawn_state dm; /* the stub domain device model */
+    /* filled in by user, must remain valid: */
+    libxl__dm_spawn_cb *callback; /* called as callback(,&sdss->dm,) */
+    /* private to libxl__spawn_stub_dm: */
+    libxl_domain_config dm_config;
+    libxl__domain_build_state dm_state;
+    libxl__dm_spawn_state pvqemu;
+} libxl__stub_dm_spawn_state;
+
+_hidden void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state*);
+
 /*----- Domain creation -----*/
 
 typedef struct libxl__domain_create_state libxl__domain_create_state;
-- 
1.7.7.5 (Apple Git-26)

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v9 03/17] libxl: convert libxl_domain_destroy to an async op
  2012-07-13  9:44 [PATCH v9 00/15] execute hotplug scripts from libxl Roger Pau Monne
  2012-07-13  9:44 ` [PATCH v9 01/17] libxl: change ao_device_remove to ao_device Roger Pau Monne
  2012-07-13  9:44 ` [PATCH v9 02/17] libxl: move device model creation prototypes Roger Pau Monne
@ 2012-07-13  9:44 ` Roger Pau Monne
  2012-07-13  9:44 ` [PATCH v9 04/17] libxl: move bootloader data strucutres and prototypes Roger Pau Monne
                   ` (13 subsequent siblings)
  16 siblings, 0 replies; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-13  9:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Roger Pau Monne

This change introduces some new structures, and breaks the mutual
dependency that libxl_domain_destroy and libxl__destroy_device_model
had. This is done by checking if the domid passed to
libxl_domain_destroy has a stubdom, and then having the bulk of the
destroy machinery in a separate function (libxl__destroy_domid) that
doesn't check for stubdom presence, since we check for it in the upper
level function. The reason behind this change is the need to use
structures for ao operations, and it was impossible to have two
different self-referencing structs.

All uses of libxl_domain_destroy have been changed, and either
replaced by the new libxl_domain_destroy ao function or by the
internal libxl__domain_destroy that can be used inside an already
running ao.

Changes since v6:

 * Fixed typos.

Changes since v5:

 * Introduced a new struct, called libxl__ao_devices that will be used
   to simplify the addition/removal of multiple devices at the same
   time.

 * With this function we can use a generic callback for ao_device,
   libxl__ao_devices_callback, that will check if the device is the
   last one and call ao_devices->callback appropiately.

Changes since v4:

 * Fixed spelling mistakes.

 * Always use "force = 1" in device destruction in
   libxl__destroy_domid function.

 * Changed name of domain destroy callbacks to include "destroy".

 * Changed the use of rc to catch syscall errors.

 * Use libxl__remove_file instead of unlink.

 * Changed variable name of number of devices returned by
   libxl__xs_directory.

 * Simplify libxl__ao_device_check_last return.

 * Correctly propagate error returned from libxl__num_devices.

 * Add a comment about the use of libxl__device_destroy to destroy the
   console.

 * Fixed some uses of LIBXL__LOG.

Changes since v3:

 * Fixed python bindings.

Changes since v2:

 * Remove printfs.

 * Replace aorm with aodev.

 * Define an auxiliary libxl__ao_device *aodev to avoid using the long
   expression: drs->aorm[numdev]...

 * Added a common callback for both domain and stubdomain destruction
   that checks if both domains are finished and handles errors
   correctly.

 * Change libxl__ao_device_check_last logic a bit and add a comment
   describing how does it work.

 * Fixed spelling mistakes.

 * Use a do-while for xs transaction in device_remove_callback.

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/libxl/libxl.c               |  176 +++++++++++++++++++++++++++++++++++--
 tools/libxl/libxl.h               |    3 +-
 tools/libxl/libxl_create.c        |   29 +++++-
 tools/libxl/libxl_device.c        |  150 +++++++++++++++++++++++++++----
 tools/libxl/libxl_dm.c            |   85 +++++++++----------
 tools/libxl/libxl_internal.h      |  116 ++++++++++++++++++++++++-
 tools/libxl/xl_cmdimpl.c          |   12 ++--
 tools/python/xen/lowlevel/xl/xl.c |    2 +-
 8 files changed, 489 insertions(+), 84 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 777484c..50e9127 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1216,11 +1216,133 @@ void libxl_evdisable_disk_eject(libxl_ctx *ctx, libxl_evgen_disk_eject *evg) {
     GC_FREE;
 }    
 
-int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid)
+/* Callbacks for libxl_domain_destroy */
+
+static void domain_destroy_cb(libxl__egc *egc, libxl__domain_destroy_state *dds,
+                              int rc);
+
+int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid,
+                         const libxl_asyncop_how *ao_how)
 {
-    GC_INIT(ctx);
+    AO_CREATE(ctx, domid, ao_how);
+    libxl__domain_destroy_state *dds;
+
+    GCNEW(dds);
+    dds->ao = ao;
+    dds->domid = domid;
+    dds->callback = domain_destroy_cb;
+    libxl__domain_destroy(egc, dds);
+
+    return AO_INPROGRESS;
+}
+
+static void domain_destroy_cb(libxl__egc *egc, libxl__domain_destroy_state *dds,
+                              int rc)
+{
+    STATE_AO_GC(dds->ao);
+
+    if (rc)
+        LOG(ERROR, "destruction of domain %u failed", dds->domid);
+
+    libxl__ao_complete(egc, ao, rc);
+}
+
+/* Callbacks for libxl__domain_destroy */
+
+static void stubdom_destroy_callback(libxl__egc *egc,
+                                     libxl__destroy_domid_state *dis,
+                                     int rc);
+
+static void domain_destroy_callback(libxl__egc *egc,
+                                    libxl__destroy_domid_state *dis,
+                                    int rc);
+
+static void destroy_finish_check(libxl__egc *egc,
+                                 libxl__domain_destroy_state *dds);
+
+void libxl__domain_destroy(libxl__egc *egc, libxl__domain_destroy_state *dds)
+{
+    STATE_AO_GC(dds->ao);
+    uint32_t stubdomid = libxl_get_stubdom_id(CTX, dds->domid);
+
+    if (stubdomid) {
+        dds->stubdom.ao = ao;
+        dds->stubdom.domid = stubdomid;
+        dds->stubdom.callback = stubdom_destroy_callback;
+        libxl__destroy_domid(egc, &dds->stubdom);
+    } else {
+        dds->stubdom_finished = 1;
+    }
+
+    dds->domain.ao = ao;
+    dds->domain.domid = dds->domid;
+    dds->domain.callback = domain_destroy_callback;
+    libxl__destroy_domid(egc, &dds->domain);
+}
+
+static void stubdom_destroy_callback(libxl__egc *egc,
+                                     libxl__destroy_domid_state *dis,
+                                     int rc)
+{
+    STATE_AO_GC(dis->ao);
+    libxl__domain_destroy_state *dds = CONTAINER_OF(dis, *dds, stubdom);
+    const char *savefile;
+
+    if (rc) {
+        LOG(ERROR, "unable to destroy stubdom with domid %u", dis->domid);
+        dds->rc = rc;
+    }
+
+    dds->stubdom_finished = 1;
+    savefile = libxl__device_model_savefile(gc, dis->domid);
+    rc = libxl__remove_file(gc, savefile);
+    /*
+     * On suspend libxl__domain_save_device_model will have already
+     * unlinked the save file.
+     */
+    if (rc) {
+        LOG(ERROR, "failed to remove device-model savefile %s", savefile);
+    }
+
+    destroy_finish_check(egc, dds);
+}
+
+static void domain_destroy_callback(libxl__egc *egc,
+                                    libxl__destroy_domid_state *dis,
+                                    int rc)
+{
+    STATE_AO_GC(dis->ao);
+    libxl__domain_destroy_state *dds = CONTAINER_OF(dis, *dds, domain);
+
+    if (rc) {
+        LOG(ERROR, "unable to destroy guest with domid %u", dis->domid);
+        dds->rc = rc;
+    }
+
+    dds->domain_finished = 1;
+    destroy_finish_check(egc, dds);
+}
+
+static void destroy_finish_check(libxl__egc *egc,
+                                 libxl__domain_destroy_state *dds)
+{
+    if (!(dds->domain_finished && dds->stubdom_finished))
+        return;
+
+    dds->callback(egc, dds, dds->rc);
+}
+
+/* Callbacks for libxl__destroy_domid */
+static void devices_destroy_cb(libxl__egc *egc,
+                               libxl__devices_remove_state *drs,
+                               int rc);
+
+void libxl__destroy_domid(libxl__egc *egc, libxl__destroy_domid_state *dis)
+{
+    STATE_AO_GC(dis->ao);
+    libxl_ctx *ctx = CTX;
+    uint32_t domid = dis->domid;
     char *dom_path;
-    char *vm_path;
     char *pid;
     int rc, dm_present;
 
@@ -1231,12 +1353,15 @@ int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid)
     case ERROR_INVAL:
         LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "non-existant domain %d", domid);
     default:
-        return rc;
+        goto out;
     }
 
     switch (libxl__domain_type(gc, domid)) {
     case LIBXL_DOMAIN_TYPE_HVM:
-        dm_present = 1;
+        if (!libxl_get_stubdom_id(CTX, domid))
+            dm_present = 1;
+        else
+            dm_present = 0;
         break;
     case LIBXL_DOMAIN_TYPE_PV:
         pid = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "/local/domain/%d/image/device-model-pid", domid));
@@ -1267,7 +1392,37 @@ int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid)
 
         libxl__qmp_cleanup(gc, domid);
     }
-    if (libxl__devices_destroy(gc, domid) < 0)
+    dis->drs.ao = ao;
+    dis->drs.domid = domid;
+    dis->drs.callback = devices_destroy_cb;
+    dis->drs.force = 1;
+    libxl__devices_destroy(egc, &dis->drs);
+    return;
+
+out:
+    assert(rc);
+    dis->callback(egc, dis, rc);
+    return;
+}
+
+static void devices_destroy_cb(libxl__egc *egc,
+                               libxl__devices_remove_state *drs,
+                               int rc)
+{
+    STATE_AO_GC(drs->ao);
+    libxl__destroy_domid_state *dis = CONTAINER_OF(drs, *dis, drs);
+    libxl_ctx *ctx = CTX;
+    uint32_t domid = dis->domid;
+    char *dom_path;
+    char *vm_path;
+
+    dom_path = libxl__xs_get_dompath(gc, domid);
+    if (!dom_path) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    if (rc < 0)
         LIBXL__LOG(ctx, LIBXL__LOG_ERROR, 
                    "libxl__devices_destroy failed for %d", domid);
 
@@ -1280,6 +1435,10 @@ int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid)
         LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "xs_rm failed for %s", dom_path);
 
     xs_rm(ctx->xsh, XBT_NULL, libxl__xs_libxl_path(gc, domid));
+    xs_rm(ctx->xsh, XBT_NULL, libxl__sprintf(gc,
+                                "/local/domain/0/device-model/%d", domid));
+    xs_rm(ctx->xsh, XBT_NULL, libxl__sprintf(gc,
+                                "/local/domain/%d/hvmloader", domid));
 
     libxl__userdata_destroyall(gc, domid);
 
@@ -1290,9 +1449,10 @@ int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid)
         goto out;
     }
     rc = 0;
+
 out:
-    GC_FREE;
-    return rc;
+    dis->callback(egc, dis, rc);
+    return;
 }
 
 int libxl_console_exec(libxl_ctx *ctx, uint32_t domid, int cons_num,
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index c2d5c06..5c819f1 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -527,7 +527,8 @@ int libxl_domain_remus_start(libxl_ctx *ctx, libxl_domain_remus_info *info,
 
 int libxl_domain_shutdown(libxl_ctx *ctx, uint32_t domid);
 int libxl_domain_reboot(libxl_ctx *ctx, uint32_t domid);
-int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid);
+int libxl_domain_destroy(libxl_ctx *ctx, uint32_t domid,
+                         const libxl_asyncop_how *ao_how);
 int libxl_domain_preserve(libxl_ctx *ctx, uint32_t domid, libxl_domain_create_info *info, const char *name_suffix, libxl_uuid new_uuid);
 
 /* get max. number of cpus supported by hypervisor */
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 294a73f..16d32c2 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -571,6 +571,12 @@ static void domcreate_complete(libxl__egc *egc,
                                libxl__domain_create_state *dcs,
                                int rc);
 
+/* If creation is not successful, this callback will be executed
+ * when domain destruction is finished */
+static void domcreate_destruction_cb(libxl__egc *egc,
+                                     libxl__domain_destroy_state *dds,
+                                     int rc);
+
 static void initiate_domain_create(libxl__egc *egc,
                                    libxl__domain_create_state *dcs)
 {
@@ -996,16 +1002,31 @@ static void domcreate_complete(libxl__egc *egc,
 
     if (rc) {
         if (dcs->guest_domid) {
-            int rc2 = libxl_domain_destroy(CTX, dcs->guest_domid);
-            if (rc2)
-                LOG(ERROR, "unable to destroy domain %d following"
-                    " failed creation", dcs->guest_domid);
+            dcs->dds.ao = ao;
+            dcs->dds.domid = dcs->guest_domid;
+            dcs->dds.callback = domcreate_destruction_cb;
+            libxl__domain_destroy(egc, &dcs->dds);
+            return;
         }
         dcs->guest_domid = -1;
     }
     dcs->callback(egc, dcs, rc, dcs->guest_domid);
 }
 
+static void domcreate_destruction_cb(libxl__egc *egc,
+                                     libxl__domain_destroy_state *dds,
+                                     int rc)
+{
+    STATE_AO_GC(dds->ao);
+    libxl__domain_create_state *dcs = CONTAINER_OF(dds, *dcs, dds);
+
+    if (rc)
+        LOG(ERROR, "unable to destroy domain %u following failed creation",
+                   dds->domid);
+
+    dcs->callback(egc, dcs, ERROR_FAIL, dcs->guest_domid);
+}
+
 /*----- application-facing domain creation interface -----*/
 
 typedef struct {
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 84286b2..766f9f2 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -58,6 +58,48 @@ int libxl__parse_backend_path(libxl__gc *gc,
     return libxl__device_kind_from_string(strkind, &dev->backend_kind);
 }
 
+static int libxl__num_devices(libxl__gc *gc, uint32_t domid)
+{
+    char *path;
+    unsigned int num_kinds, num_devs;
+    char **kinds = NULL, **devs = NULL;
+    int i, j, rc = 0;
+    libxl__device dev;
+    libxl__device_kind kind;
+    int numdevs = 0;
+
+    path = GCSPRINTF("/local/domain/%d/device", domid);
+    kinds = libxl__xs_directory(gc, XBT_NULL, path, &num_kinds);
+    if (!kinds) {
+        if (errno != ENOENT) {
+            LOGE(ERROR, "unable to get xenstore device listing %s", path);
+            rc = ERROR_FAIL;
+            goto out;
+        }
+        num_kinds = 0;
+    }
+    for (i = 0; i < num_kinds; i++) {
+        if (libxl__device_kind_from_string(kinds[i], &kind))
+            continue;
+
+        path = GCSPRINTF("/local/domain/%d/device/%s", domid, kinds[i]);
+        devs = libxl__xs_directory(gc, XBT_NULL, path, &num_devs);
+        if (!devs)
+            continue;
+        for (j = 0; j < num_devs; j++) {
+            path = GCSPRINTF("/local/domain/%d/device/%s/%s/backend",
+                             domid, kinds[i], devs[j]);
+            path = libxl__xs_read(gc, XBT_NULL, path);
+            if (path && libxl__parse_backend_path(gc, path, &dev) == 0) {
+                numdevs++;
+            }
+        }
+    }
+out:
+    if (rc) return rc;
+    return numdevs;
+}
+
 int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
         libxl__device *device, char **bents, char **fents)
 {
@@ -367,6 +409,37 @@ void libxl__prepare_ao_device(libxl__ao *ao, libxl__ao_device *aodev)
 {
     aodev->ao = ao;
     aodev->rc = 0;
+    aodev->active = 1;
+}
+
+void libxl__prepare_ao_devices(libxl__ao *ao, libxl__ao_devices *aodevs)
+{
+    AO_GC;
+
+    GCNEW_ARRAY(aodevs->array, aodevs->size);
+    for (int i = 0; i < aodevs->size; i++) {
+        aodevs->array[i].aodevs = aodevs;
+        libxl__prepare_ao_device(ao, &aodevs->array[i]);
+    }
+}
+
+void libxl__ao_devices_callback(libxl__egc *egc, libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+    libxl__ao_devices *aodevs = aodev->aodevs;
+    int i, error = 0;
+
+    aodev->active = 0;
+    for (i = 0; i < aodevs->size; i++) {
+        if (aodevs->array[i].active)
+            return;
+
+        if (aodevs->array[i].rc)
+            error = aodevs->array[i].rc;
+    }
+
+    aodevs->callback(egc, aodevs, error);
+    return;
 }
 
 int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
@@ -383,16 +456,35 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
     return 0;
 }
 
-int libxl__devices_destroy(libxl__gc *gc, uint32_t domid)
+/* Callback for device destruction */
+
+static void devices_remove_callback(libxl__egc *egc, libxl__ao_devices *aodevs,
+                                    int rc);
+
+void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
 {
+    STATE_AO_GC(drs->ao);
     libxl_ctx *ctx = libxl__gc_owner(gc);
+    uint32_t domid = drs->domid;
     char *path;
-    unsigned int num_kinds, num_devs;
+    unsigned int num_kinds, num_dev_xsentries;
     char **kinds = NULL, **devs = NULL;
-    int i, j;
-    libxl__device dev;
+    int i, j, numdev = 0, rc = 0;
+    libxl__device *dev;
+    libxl__ao_devices *aodevs = &drs->aodevs;
+    libxl__ao_device *aodev;
     libxl__device_kind kind;
 
+    aodevs->size = libxl__num_devices(gc, drs->domid);
+    if (aodevs->size < 0) {
+        LOG(ERROR, "unable to get number of devices for domain %u", drs->domid);
+        rc = aodevs->size;
+        goto out;
+    }
+
+    libxl__prepare_ao_devices(drs->ao, aodevs);
+    aodevs->callback = devices_remove_callback;
+
     path = libxl__sprintf(gc, "/local/domain/%d/device", domid);
     kinds = libxl__xs_directory(gc, XBT_NULL, path, &num_kinds);
     if (!kinds) {
@@ -408,19 +500,25 @@ int libxl__devices_destroy(libxl__gc *gc, uint32_t domid)
             continue;
 
         path = libxl__sprintf(gc, "/local/domain/%d/device/%s", domid, kinds[i]);
-        devs = libxl__xs_directory(gc, XBT_NULL, path, &num_devs);
+        devs = libxl__xs_directory(gc, XBT_NULL, path, &num_dev_xsentries);
         if (!devs)
             continue;
-        for (j = 0; j < num_devs; j++) {
+        for (j = 0; j < num_dev_xsentries; j++) {
             path = libxl__sprintf(gc, "/local/domain/%d/device/%s/%s/backend",
                                   domid, kinds[i], devs[j]);
             path = libxl__xs_read(gc, XBT_NULL, path);
-            if (path && libxl__parse_backend_path(gc, path, &dev) == 0) {
-                dev.domid = domid;
-                dev.kind = kind;
-                dev.devid = atoi(devs[j]);
-
-                libxl__device_destroy(gc, &dev);
+            GCNEW(dev);
+            if (path && libxl__parse_backend_path(gc, path, dev) == 0) {
+                aodev = &aodevs->array[numdev];
+                dev->domid = domid;
+                dev->kind = kind;
+                dev->devid = atoi(devs[j]);
+                aodev->action = DEVICE_DISCONNECT;
+                aodev->dev = dev;
+                aodev->callback = libxl__ao_devices_callback;
+                aodev->force = drs->force;
+                libxl__initiate_device_remove(egc, aodev);
+                numdev++;
             }
         }
     }
@@ -428,17 +526,22 @@ int libxl__devices_destroy(libxl__gc *gc, uint32_t domid)
     /* console 0 frontend directory is not under /local/domain/<domid>/device */
     path = libxl__sprintf(gc, "/local/domain/%d/console/backend", domid);
     path = libxl__xs_read(gc, XBT_NULL, path);
+    GCNEW(dev);
     if (path && strcmp(path, "") &&
-        libxl__parse_backend_path(gc, path, &dev) == 0) {
-        dev.domid = domid;
-        dev.kind = LIBXL__DEVICE_KIND_CONSOLE;
-        dev.devid = 0;
+        libxl__parse_backend_path(gc, path, dev) == 0) {
+        dev->domid = domid;
+        dev->kind = LIBXL__DEVICE_KIND_CONSOLE;
+        dev->devid = 0;
 
-        libxl__device_destroy(gc, &dev);
+        /* Currently console devices can be destroyed synchronously by just
+         * removing xenstore entries, this is what libxl__device_destroy does.
+         */
+        libxl__device_destroy(gc, dev);
     }
 
 out:
-    return 0;
+    if (!numdev) drs->callback(egc, drs, rc);
+    return;
 }
 
 /* Callbacks for device related operations */
@@ -543,6 +646,7 @@ static void device_backend_callback(libxl__egc *egc, libxl__ev_devstate *ds,
     } else if (rc) {
         LOG(DEBUG, "unable to disconnect device with path %s",
                    libxl__device_backend_path(gc, aodev->dev));
+        rc = 0;
         goto out;
     }
 
@@ -585,6 +689,16 @@ out:
     return;
 }
 
+static void devices_remove_callback(libxl__egc *egc, libxl__ao_devices *aodevs,
+                                    int rc)
+{
+    libxl__devices_remove_state *drs = CONTAINER_OF(aodevs, *drs, aodevs);
+    STATE_AO_GC(drs->ao);
+
+    drs->callback(egc, drs, rc);
+    return;
+}
+
 int libxl__wait_for_device_model(libxl__gc *gc,
                                  uint32_t domid, char *state,
                                  libxl__spawn_starting *spawning,
diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index dadad76..6a041f9 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -694,6 +694,10 @@ static void spawn_stubdom_pvqemu_cb(libxl__egc *egc,
                                 libxl__dm_spawn_state *stubdom_dmss,
                                 int rc);
 
+static void spaw_stubdom_pvqemu_destroy_cb(libxl__egc *egc,
+                                           libxl__destroy_domid_state *dis,
+                                           int rc);
+
 void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state *sdss)
 {
     STATE_AO_GC(sdss->dm.spawn.ao);
@@ -914,12 +918,31 @@ static void spawn_stubdom_pvqemu_cb(libxl__egc *egc,
 
  out:
     if (rc) {
-        if (dm_domid)
-            libxl_domain_destroy(CTX, dm_domid);
+        if (dm_domid) {
+            sdss->dis.ao = ao;
+            sdss->dis.domid = dm_domid;
+            sdss->dis.callback = spaw_stubdom_pvqemu_destroy_cb;
+            libxl__destroy_domid(egc, &sdss->dis);
+            return;
+        }
     }
     sdss->callback(egc, &sdss->dm, rc);
 }
 
+static void spaw_stubdom_pvqemu_destroy_cb(libxl__egc *egc,
+                                           libxl__destroy_domid_state *dis,
+                                           int rc)
+{
+    libxl__stub_dm_spawn_state *sdss = CONTAINER_OF(dis, *sdss, dis);
+    STATE_AO_GC(sdss->dis.ao);
+
+    if (rc)
+        LOG(ERROR, "destruction of domain %u after failed creation failed",
+                   sdss->pvqemu.guest_domid);
+
+    sdss->callback(egc, &sdss->dm, rc);
+}
+
 /* callbacks passed to libxl__spawn_spawn */
 static void device_model_confirm(libxl__egc *egc, libxl__spawn_state *spawn,
                                  const char *xsdata);
@@ -1115,55 +1138,27 @@ static void device_model_spawn_outcome(libxl__egc *egc,
 
 int libxl__destroy_device_model(libxl__gc *gc, uint32_t domid)
 {
-    libxl_ctx *ctx = libxl__gc_owner(gc);
     char *pid;
     int ret;
 
     pid = libxl__xs_read(gc, XBT_NULL, libxl__sprintf(gc, "/local/domain/%d/image/device-model-pid", domid));
-    if (!pid) {
-        int stubdomid = libxl_get_stubdom_id(ctx, domid);
-        const char *savefile;
-
-        if (!stubdomid) {
-            LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "Couldn't find device model's pid");
-            ret = ERROR_INVAL;
-            goto out;
-        }
-        LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Device model is a stubdom, domid=%d", stubdomid);
-        ret = libxl_domain_destroy(ctx, stubdomid);
-        if (ret)
-            goto out;
-
-        savefile = libxl__device_model_savefile(gc, domid);
-        ret = unlink(savefile);
-        /*
-         * On suspend libxl__domain_save_device_model will have already
-         * unlinked the save file.
-         */
-        if (ret && errno == ENOENT) ret = 0;
-        if (ret) {
-            LIBXL__LOG_ERRNO(ctx, XTL_ERROR,
-                             "failed to remove device-model savefile %s\n",
-                             savefile);
-            goto out;
-        }
+    if (!pid || !atoi(pid)) {
+        LOG(ERROR, "could not find device-model's pid for dom %u", domid);
+        ret = ERROR_FAIL;
+        goto out;
+    }
+    ret = kill(atoi(pid), SIGHUP);
+    if (ret < 0 && errno == ESRCH) {
+        LOG(ERROR, "Device Model already exited");
+        ret = 0;
+    } else if (ret == 0) {
+        LOG(DEBUG, "Device Model signaled");
+        ret = 0;
     } else {
-        ret = kill(atoi(pid), SIGHUP);
-        if (ret < 0 && errno == ESRCH) {
-            LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Device Model already exited");
-            ret = 0;
-        } else if (ret == 0) {
-            LIBXL__LOG(ctx, LIBXL__LOG_DEBUG, "Device Model signaled");
-            ret = 0;
-        } else {
-            LIBXL__LOG_ERRNO(ctx, LIBXL__LOG_ERROR, "failed to kill Device Model [%d]",
-                    atoi(pid));
-            ret = ERROR_FAIL;
-            goto out;
-        }
+        LOGE(ERROR, "failed to kill Device Model [%d]", atoi(pid));
+        ret = ERROR_FAIL;
+        goto out;
     }
-    xs_rm(ctx->xsh, XBT_NULL, libxl__sprintf(gc, "/local/domain/0/device-model/%d", domid));
-    xs_rm(ctx->xsh, XBT_NULL, libxl__sprintf(gc, "/local/domain/%d/hvmloader", domid));
 
 out:
     return ret;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 61fd100..7aa46b8 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -868,7 +868,6 @@ _hidden char *libxl__device_frontend_path(libxl__gc *gc, libxl__device *device);
 _hidden int libxl__parse_backend_path(libxl__gc *gc, const char *path,
                                       libxl__device *dev);
 _hidden int libxl__device_destroy(libxl__gc *gc, libxl__device *dev);
-_hidden int libxl__devices_destroy(libxl__gc *gc, uint32_t domid);
 _hidden int libxl__wait_for_backend(libxl__gc *gc, char *be_path, char *state);
 
 /*
@@ -1971,6 +1970,7 @@ typedef enum {
 } libxl__device_action;
 
 typedef struct libxl__ao_device libxl__ao_device;
+typedef struct libxl__ao_devices libxl__ao_devices;
 typedef void libxl__device_callback(libxl__egc*, libxl__ao_device*);
 
 /* This functions sets the necessary libxl__ao_device struct values to use
@@ -1989,6 +1989,20 @@ typedef void libxl__device_callback(libxl__egc*, libxl__ao_device*);
  */
 _hidden void libxl__prepare_ao_device(libxl__ao *ao, libxl__ao_device *aodev);
 
+/* Prepare a bunch of devices for addition/removal. Every ao_device in
+ * ao_devices is set to 'active', and the ao_device 'base' field is set to
+ * the one pointed by aodevs.
+ */
+_hidden void libxl__prepare_ao_devices(libxl__ao *ao,
+                                       libxl__ao_devices *aodevs);
+
+/* Generic callback to use when adding/removing several devices, this will
+ * check if the given aodev is the last one, and call the callback in the
+ * parent libxl__ao_devices struct, passing the appropriate error if found.
+ */
+_hidden void libxl__ao_devices_callback(libxl__egc *egc,
+                                        libxl__ao_device *aodev);
+
 struct libxl__ao_device {
     /* filled in by user */
     libxl__ao *ao;
@@ -1997,8 +2011,25 @@ struct libxl__ao_device {
     int force;
     libxl__device_callback *callback;
     /* private for implementation */
+    int active;
     int rc;
     libxl__ev_devstate backend_ds;
+    /* Used internally to have a reference to the upper libxl__ao_devices
+     * struct when present */
+    libxl__ao_devices *aodevs;
+};
+
+/* Helper struct to simply the plug/unplug of multiple devices at the same
+ * time.
+ *
+ * This structure holds several devices, and the callback is only called
+ * when all the devices inside of the array have finished.
+ */
+typedef void libxl__devices_callback(libxl__egc*, libxl__ao_devices*, int rc);
+struct libxl__ao_devices {
+    libxl__ao_device *array;
+    int size;
+    libxl__devices_callback *callback;
 };
 
 /* Arranges that dev will be removed to the guest, and the
@@ -2013,6 +2044,86 @@ struct libxl__ao_device {
 _hidden void libxl__initiate_device_remove(libxl__egc *egc,
                                            libxl__ao_device *aodev);
 
+/*----- Domain destruction -----*/
+
+/* Domain destruction has been split into two functions:
+ *
+ * libxl__domain_destroy is the main destroy function, which detects
+ * stubdoms and calls libxl__destroy_domid on the domain and its
+ * stubdom if present, creating a different libxl__destroy_domid_state
+ * for each one of them.
+ *
+ * libxl__destroy_domid actually destroys the domain, but it
+ * doesn't check for stubdomains, since that would involve
+ * recursion, which we want to avoid.
+ */
+
+typedef struct libxl__domain_destroy_state libxl__domain_destroy_state;
+typedef struct libxl__destroy_domid_state libxl__destroy_domid_state;
+typedef struct libxl__devices_remove_state libxl__devices_remove_state;
+
+typedef void libxl__domain_destroy_cb(libxl__egc *egc,
+                                      libxl__domain_destroy_state *dds,
+                                      int rc);
+
+typedef void libxl__domid_destroy_cb(libxl__egc *egc,
+                                     libxl__destroy_domid_state *dis,
+                                     int rc);
+
+typedef void libxl__devices_remove_callback(libxl__egc *egc,
+                                            libxl__devices_remove_state *drs,
+                                            int rc);
+
+struct libxl__devices_remove_state {
+    /* filled in by user */
+    libxl__ao *ao;
+    uint32_t domid;
+    libxl__devices_remove_callback *callback;
+    int force; /* libxl_device_TYPE_destroy rather than _remove */
+    /* private */
+    libxl__ao_devices aodevs;
+    int num_devices;
+};
+
+struct libxl__destroy_domid_state {
+    /* filled in by user */
+    libxl__ao *ao;
+    uint32_t domid;
+    libxl__domid_destroy_cb *callback;
+    /* private to implementation */
+    libxl__devices_remove_state drs;
+};
+
+struct libxl__domain_destroy_state {
+    /* filled by the user */
+    libxl__ao *ao;
+    uint32_t domid;
+    libxl__domain_destroy_cb *callback;
+    /* Private */
+    int rc;
+    uint32_t stubdomid;
+    libxl__destroy_domid_state stubdom;
+    int stubdom_finished;
+    libxl__destroy_domid_state domain;
+    int domain_finished;
+};
+
+/*
+ * Entry point for domain destruction
+ * This function checks for stubdom presence and then calls
+ * libxl__destroy_domid on the passed domain and its stubdom if found.
+ */
+_hidden void libxl__domain_destroy(libxl__egc *egc,
+                                   libxl__domain_destroy_state *dds);
+
+/* Used to destroy a domain with the passed id (it doesn't check for stubs) */
+_hidden void libxl__destroy_domid(libxl__egc *egc,
+                                  libxl__destroy_domid_state *dis);
+
+/* Entry point for devices destruction */
+_hidden void libxl__devices_destroy(libxl__egc *egc,
+                                    libxl__devices_remove_state *drs);
+
 /*----- device model creation -----*/
 
 /* First layer; wraps libxl__spawn_spawn. */
@@ -2046,6 +2157,7 @@ typedef struct {
     libxl_domain_config dm_config;
     libxl__domain_build_state dm_state;
     libxl__dm_spawn_state pvqemu;
+    libxl__destroy_domid_state dis;
 } libxl__stub_dm_spawn_state;
 
 _hidden void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state*);
@@ -2073,6 +2185,8 @@ struct libxl__domain_create_state {
         /* If we're not doing stubdom, we use only dmss.dm,
          * for the non-stubdom device model. */
     libxl__save_helper_state shs;
+    /* necessary if the domain creation failed and we have to destroy it */
+    libxl__domain_destroy_state dds;
 };
 
 /*----- Domain suspend (save) functions -----*/
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 29523e1..61791e1 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -1401,7 +1401,7 @@ static int handle_domain_death(uint32_t *r_domid,
     case LIBXL_ACTION_ON_SHUTDOWN_DESTROY:
         LOG("Domain %d needs to be cleaned up: destroying the domain",
             *r_domid);
-        libxl_domain_destroy(ctx, *r_domid);
+        libxl_domain_destroy(ctx, *r_domid, 0);
         *r_domid = INVALID_DOMID;
         break;
 
@@ -2016,7 +2016,7 @@ start:
 error_out:
     release_lock();
     if (libxl_domid_valid_guest(domid)) {
-        libxl_domain_destroy(ctx, domid);
+        libxl_domain_destroy(ctx, domid, 0);
         domid = INVALID_DOMID;
     }
 
@@ -2581,7 +2581,7 @@ static void destroy_domain(const char *p)
         fprintf(stderr, "Cannot destroy privileged domain 0.\n\n");
         exit(-1);
     }
-    rc = libxl_domain_destroy(ctx, domid);
+    rc = libxl_domain_destroy(ctx, domid, 0);
     if (rc) { fprintf(stderr,"destroy failed (rc=%d)\n",rc); exit(-1); }
 }
 
@@ -2855,7 +2855,7 @@ static int save_domain(const char *p, const char *filename, int checkpoint,
     if (checkpoint)
         libxl_domain_resume(ctx, domid, 1);
     else
-        libxl_domain_destroy(ctx, domid);
+        libxl_domain_destroy(ctx, domid, 0);
 
     exit(0);
 }
@@ -3112,7 +3112,7 @@ static void migrate_domain(const char *domain_spec, const char *rune,
     }
 
     fprintf(stderr, "migration sender: Target reports successful startup.\n");
-    libxl_domain_destroy(ctx, domid); /* bang! */
+    libxl_domain_destroy(ctx, domid, 0); /* bang! */
     fprintf(stderr, "Migration successful.\n");
     exit(0);
 
@@ -3265,7 +3265,7 @@ static void migrate_receive(int debug, int daemonize, int monitor,
     if (rc) {
         fprintf(stderr, "migration target: Failure, destroying our copy.\n");
 
-        rc2 = libxl_domain_destroy(ctx, domid);
+        rc2 = libxl_domain_destroy(ctx, domid, 0);
         if (rc2) {
             fprintf(stderr, "migration target: Failed to destroy our copy"
                     " (code %d).\n", rc2);
diff --git a/tools/python/xen/lowlevel/xl/xl.c b/tools/python/xen/lowlevel/xl/xl.c
index b68b55a..553fc58 100644
--- a/tools/python/xen/lowlevel/xl/xl.c
+++ b/tools/python/xen/lowlevel/xl/xl.c
@@ -437,7 +437,7 @@ static PyObject *pyxl_domain_destroy(XlObject *self, PyObject *args)
     int domid;
     if ( !PyArg_ParseTuple(args, "i", &domid) )
         return NULL;
-    if ( libxl_domain_destroy(self->ctx, domid) ) {
+    if ( libxl_domain_destroy(self->ctx, domid, 0) ) {
         PyErr_SetString(xl_error_obj, "cannot destroy domain");
         return NULL;
     }
-- 
1.7.7.5 (Apple Git-26)

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v9 04/17] libxl: move bootloader data strucutres and prototypes
  2012-07-13  9:44 [PATCH v9 00/15] execute hotplug scripts from libxl Roger Pau Monne
                   ` (2 preceding siblings ...)
  2012-07-13  9:44 ` [PATCH v9 03/17] libxl: convert libxl_domain_destroy to an async op Roger Pau Monne
@ 2012-07-13  9:44 ` Roger Pau Monne
  2012-07-13  9:44 ` [PATCH v9 05/17] libxl: refactor disk addition to take a helper Roger Pau Monne
                   ` (12 subsequent siblings)
  16 siblings, 0 replies; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-13  9:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Roger Pau Monne

Move bootloader and related data after all the device stuff, since
libxl__bootloader_state will depend on libxl__ao_device (to perform
the local attach of a device).

This is pure code motion.

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/libxl/libxl_internal.h |  166 +++++++++++++++++++++---------------------
 1 files changed, 83 insertions(+), 83 deletions(-)

diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 7aa46b8..7a75809 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1740,6 +1740,89 @@ _hidden const char *libxl__xen_script_dir_path(void);
 _hidden const char *libxl__lock_dir_path(void);
 _hidden const char *libxl__run_dir_path(void);
 
+/*----- device addition/removal -----*/
+
+/* Action to perform (either connect or disconnect) */
+typedef enum {
+    DEVICE_CONNECT,
+    DEVICE_DISCONNECT
+} libxl__device_action;
+
+typedef struct libxl__ao_device libxl__ao_device;
+typedef struct libxl__ao_devices libxl__ao_devices;
+typedef void libxl__device_callback(libxl__egc*, libxl__ao_device*);
+
+/* This functions sets the necessary libxl__ao_device struct values to use
+ * safely inside functions. It marks the operation as "active"
+ * since we need to be sure that all device status structs are set
+ * to active before start queueing events, or we might call
+ * ao_complete before all devices had finished
+ *
+ * libxl__initiate_device_{remove/addition} should not be called without
+ * calling libxl__prepare_ao_device first, since it initializes the private
+ * fields of the struct libxl__ao_device to what this functions expect.
+ *
+ * Once _prepare has been called on a libxl__ao_device, it is safe to just
+ * discard this struct, there's no need to call any destroy function.
+ * _prepare can also be called multiple times with the same libxl__ao_device.
+ */
+_hidden void libxl__prepare_ao_device(libxl__ao *ao, libxl__ao_device *aodev);
+
+/* Prepare a bunch of devices for addition/removal. Every ao_device in
+ * ao_devices is set to 'active', and the ao_device 'base' field is set to
+ * the one pointed by aodevs.
+ */
+_hidden void libxl__prepare_ao_devices(libxl__ao *ao,
+                                       libxl__ao_devices *aodevs);
+
+/* Generic callback to use when adding/removing several devices, this will
+ * check if the given aodev is the last one, and call the callback in the
+ * parent libxl__ao_devices struct, passing the appropriate error if found.
+ */
+_hidden void libxl__ao_devices_callback(libxl__egc *egc,
+                                        libxl__ao_device *aodev);
+
+struct libxl__ao_device {
+    /* filled in by user */
+    libxl__ao *ao;
+    libxl__device_action action;
+    libxl__device *dev;
+    int force;
+    libxl__device_callback *callback;
+    /* private for implementation */
+    int active;
+    int rc;
+    libxl__ev_devstate backend_ds;
+    /* Used internally to have a reference to the upper libxl__ao_devices
+     * struct when present */
+    libxl__ao_devices *aodevs;
+};
+
+/* Helper struct to simply the plug/unplug of multiple devices at the same
+ * time.
+ *
+ * This structure holds several devices, and the callback is only called
+ * when all the devices inside of the array have finished.
+ */
+typedef void libxl__devices_callback(libxl__egc*, libxl__ao_devices*, int rc);
+struct libxl__ao_devices {
+    libxl__ao_device *array;
+    int size;
+    libxl__devices_callback *callback;
+};
+
+/* Arranges that dev will be removed to the guest, and the
+ * hotplug scripts will be executed (if necessary). When
+ * this is done (or an error happens), the callback in
+ * aodev->callback will be called.
+ *
+ * The libxl__ao_device passed to this function should be
+ * prepared using libxl__prepare_ao_device prior to calling
+ * this function.
+ */
+_hidden void libxl__initiate_device_remove(libxl__egc *egc,
+                                           libxl__ao_device *aodev);
+
 /*----- datacopier: copies data from one fd to another -----*/
 
 typedef struct libxl__datacopier_state libxl__datacopier_state;
@@ -1961,89 +2044,6 @@ _hidden void libxl__bootloader_init(libxl__bootloader_state *bl);
  * If callback is passed rc==0, will have updated st->info appropriately */
 _hidden void libxl__bootloader_run(libxl__egc*, libxl__bootloader_state *st);
 
-/*----- device addition/removal -----*/
-
-/* Action to perform (either connect or disconnect) */
-typedef enum {
-    DEVICE_CONNECT,
-    DEVICE_DISCONNECT
-} libxl__device_action;
-
-typedef struct libxl__ao_device libxl__ao_device;
-typedef struct libxl__ao_devices libxl__ao_devices;
-typedef void libxl__device_callback(libxl__egc*, libxl__ao_device*);
-
-/* This functions sets the necessary libxl__ao_device struct values to use
- * safely inside functions. It marks the operation as "active"
- * since we need to be sure that all device status structs are set
- * to active before start queueing events, or we might call
- * ao_complete before all devices had finished
- *
- * libxl__initiate_device_{remove/addition} should not be called without
- * calling libxl__prepare_ao_device first, since it initializes the private
- * fields of the struct libxl__ao_device to what this functions expect.
- *
- * Once _prepare has been called on a libxl__ao_device, it is safe to just
- * discard this struct, there's no need to call any destroy function.
- * _prepare can also be called multiple times with the same libxl__ao_device.
- */
-_hidden void libxl__prepare_ao_device(libxl__ao *ao, libxl__ao_device *aodev);
-
-/* Prepare a bunch of devices for addition/removal. Every ao_device in
- * ao_devices is set to 'active', and the ao_device 'base' field is set to
- * the one pointed by aodevs.
- */
-_hidden void libxl__prepare_ao_devices(libxl__ao *ao,
-                                       libxl__ao_devices *aodevs);
-
-/* Generic callback to use when adding/removing several devices, this will
- * check if the given aodev is the last one, and call the callback in the
- * parent libxl__ao_devices struct, passing the appropriate error if found.
- */
-_hidden void libxl__ao_devices_callback(libxl__egc *egc,
-                                        libxl__ao_device *aodev);
-
-struct libxl__ao_device {
-    /* filled in by user */
-    libxl__ao *ao;
-    libxl__device_action action;
-    libxl__device *dev;
-    int force;
-    libxl__device_callback *callback;
-    /* private for implementation */
-    int active;
-    int rc;
-    libxl__ev_devstate backend_ds;
-    /* Used internally to have a reference to the upper libxl__ao_devices
-     * struct when present */
-    libxl__ao_devices *aodevs;
-};
-
-/* Helper struct to simply the plug/unplug of multiple devices at the same
- * time.
- *
- * This structure holds several devices, and the callback is only called
- * when all the devices inside of the array have finished.
- */
-typedef void libxl__devices_callback(libxl__egc*, libxl__ao_devices*, int rc);
-struct libxl__ao_devices {
-    libxl__ao_device *array;
-    int size;
-    libxl__devices_callback *callback;
-};
-
-/* Arranges that dev will be removed to the guest, and the
- * hotplug scripts will be executed (if necessary). When
- * this is done (or an error happens), the callback in
- * aodev->callback will be called.
- *
- * The libxl__ao_device passed to this function should be
- * prepared using libxl__prepare_ao_device prior to calling
- * this function.
- */
-_hidden void libxl__initiate_device_remove(libxl__egc *egc,
-                                           libxl__ao_device *aodev);
-
 /*----- Domain destruction -----*/
 
 /* Domain destruction has been split into two functions:
-- 
1.7.7.5 (Apple Git-26)

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v9 05/17] libxl: refactor disk addition to take a helper
  2012-07-13  9:44 [PATCH v9 00/15] execute hotplug scripts from libxl Roger Pau Monne
                   ` (3 preceding siblings ...)
  2012-07-13  9:44 ` [PATCH v9 04/17] libxl: move bootloader data strucutres and prototypes Roger Pau Monne
@ 2012-07-13  9:44 ` Roger Pau Monne
  2012-07-17 16:46   ` Ian Jackson
  2012-07-13  9:44 ` [PATCH v9 06/17] libxl: convert libxl__device_disk_local_attach to an async op Roger Pau Monne
                   ` (11 subsequent siblings)
  16 siblings, 1 reply; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-13  9:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Roger Pau Monne

Change libxl__device_disk_add to no longer take a xs transaction and
instead pass a helper for the local attach case that's used to get the
free vdev.

This function contains some non-functional changes due to an
indentation change.

Changes since v7:

 * Fixed the use of the transaction inside device_disk_add (which in
   v7 was fixed in the next patch).

Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Roger Pau Monne <roger.pau@citrix.com>
---
 tools/libxl/libxl.c          |  260 ++++++++++++++++++++++--------------------
 tools/libxl/libxl_internal.h |    2 +-
 2 files changed, 139 insertions(+), 123 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 50e9127..cad1c3a 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1733,115 +1733,146 @@ int libxl__device_from_disk(libxl__gc *gc, uint32_t domid,
     return 0;
 }
 
-int libxl__device_disk_add(libxl__gc *gc, uint32_t domid,
-        xs_transaction_t t, libxl_device_disk *disk)
-{
-    flexarray_t *front;
-    flexarray_t *back;
+/* Specific function called directly only by local disk attach,
+ * all other users should instead use the regular
+ * libxl__device_disk_add wrapper
+ */
+static int device_disk_add(libxl__gc *gc, uint32_t domid,
+                           libxl_device_disk *disk,
+                           char *(*fn)(libxl__gc *, const char *,
+                                              xs_transaction_t),
+                           const char *blkdev_start)
+{
+    flexarray_t *front = NULL;
+    flexarray_t *back = NULL;
     char *dev;
     libxl__device device;
     int major, minor, rc;
     libxl_ctx *ctx = gc->owner;
+    xs_transaction_t t = XBT_NULL;
 
-    rc = libxl__device_disk_setdefault(gc, disk);
-    if (rc) goto out;
+    for (;;) {
+        rc = libxl__xs_transaction_start(gc, &t);
+        if (rc) goto out;
+
+        if (fn) {
+            assert(blkdev_start);
+            disk->vdev = fn(gc, blkdev_start, t);
+            if (disk->vdev == NULL) {
+                LOG(ERROR, "libxl__alloc_vdev failed");
+                rc = ERROR_FAIL;
+                goto out;
+            }
+        }
 
-    front = flexarray_make(16, 1);
-    if (!front) {
-        rc = ERROR_NOMEM;
-        goto out;
-    }
-    back = flexarray_make(16, 1);
-    if (!back) {
-        rc = ERROR_NOMEM;
-        goto out_free;
-    }
+        rc = libxl__device_disk_setdefault(gc, disk);
+        if (rc) goto out;
 
-    if (disk->script) {
-        LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "External block scripts"
-                   " not yet supported, sorry");
-        rc = ERROR_INVAL;
-        goto out_free;
-    }
+        if (front)
+            flexarray_free(front);
+        front = flexarray_make(16, 1);
+        if (!front) {
+            rc = ERROR_NOMEM;
+            goto out;
+        }
+        if (back)
+            flexarray_free(back);
+        back = flexarray_make(16, 1);
+        if (!back) {
+            rc = ERROR_NOMEM;
+            goto out_free;
+        }
 
-    rc = libxl__device_from_disk(gc, domid, disk, &device);
-    if (rc != 0) {
-        LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Invalid or unsupported"
-               " virtual disk identifier %s", disk->vdev);
-        goto out_free;
-    }
+        if (disk->script) {
+            LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "External block scripts"
+                       " not yet supported, sorry");
+            rc = ERROR_INVAL;
+            goto out_free;
+        }
 
-    switch (disk->backend) {
-        case LIBXL_DISK_BACKEND_PHY:
-            dev = disk->pdev_path;
-    do_backend_phy:
-            libxl__device_physdisk_major_minor(dev, &major, &minor);
-            flexarray_append(back, "physical-device");
-            flexarray_append(back, libxl__sprintf(gc, "%x:%x", major, minor));
+        rc = libxl__device_from_disk(gc, domid, disk, &device);
+        if (rc != 0) {
+            LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Invalid or unsupported"
+                   " virtual disk identifier %s", disk->vdev);
+            goto out_free;
+        }
 
-            flexarray_append(back, "params");
-            flexarray_append(back, dev);
+        switch (disk->backend) {
+            case LIBXL_DISK_BACKEND_PHY:
+                dev = disk->pdev_path;
+        do_backend_phy:
+                libxl__device_physdisk_major_minor(dev, &major, &minor);
+                flexarray_append(back, "physical-device");
+                flexarray_append(back, libxl__sprintf(gc, "%x:%x", major, minor));
 
-            assert(device.backend_kind == LIBXL__DEVICE_KIND_VBD);
-            break;
-        case LIBXL_DISK_BACKEND_TAP:
-            dev = libxl__blktap_devpath(gc, disk->pdev_path, disk->format);
-            if (!dev) {
-                LOG(ERROR, "failed to get blktap devpath for %p\n",
-                    disk->pdev_path);
-                rc = ERROR_FAIL;
-                goto out_free;
-            }
-            flexarray_append(back, "tapdisk-params");
-            flexarray_append(back, libxl__sprintf(gc, "%s:%s",
-                libxl__device_disk_string_of_format(disk->format),
-                disk->pdev_path));
+                flexarray_append(back, "params");
+                flexarray_append(back, dev);
 
-            /* now create a phy device to export the device to the guest */
-            goto do_backend_phy;
-        case LIBXL_DISK_BACKEND_QDISK:
-            flexarray_append(back, "params");
-            flexarray_append(back, libxl__sprintf(gc, "%s:%s",
-                          libxl__device_disk_string_of_format(disk->format), disk->pdev_path));
-            assert(device.backend_kind == LIBXL__DEVICE_KIND_QDISK);
-            break;
-        default:
-            LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unrecognized disk backend type: %d\n", disk->backend);
-            rc = ERROR_INVAL;
-            goto out_free;
-    }
+                assert(device.backend_kind == LIBXL__DEVICE_KIND_VBD);
+                break;
+            case LIBXL_DISK_BACKEND_TAP:
+                dev = libxl__blktap_devpath(gc, disk->pdev_path, disk->format);
+                if (!dev) {
+                    LOG(ERROR, "failed to get blktap devpath for %p\n",
+                        disk->pdev_path);
+                    rc = ERROR_FAIL;
+                    goto out_free;
+                }
+                flexarray_append(back, "tapdisk-params");
+                flexarray_append(back, libxl__sprintf(gc, "%s:%s",
+                    libxl__device_disk_string_of_format(disk->format),
+                    disk->pdev_path));
+
+                /* now create a phy device to export the device to the guest */
+                goto do_backend_phy;
+            case LIBXL_DISK_BACKEND_QDISK:
+                flexarray_append(back, "params");
+                flexarray_append(back, libxl__sprintf(gc, "%s:%s",
+                              libxl__device_disk_string_of_format(disk->format), disk->pdev_path));
+                assert(device.backend_kind == LIBXL__DEVICE_KIND_QDISK);
+                break;
+            default:
+                LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unrecognized disk backend type: %d\n", disk->backend);
+                rc = ERROR_INVAL;
+                goto out_free;
+        }
 
-    flexarray_append(back, "frontend-id");
-    flexarray_append(back, libxl__sprintf(gc, "%d", domid));
-    flexarray_append(back, "online");
-    flexarray_append(back, "1");
-    flexarray_append(back, "removable");
-    flexarray_append(back, libxl__sprintf(gc, "%d", (disk->removable) ? 1 : 0));
-    flexarray_append(back, "bootable");
-    flexarray_append(back, libxl__sprintf(gc, "%d", 1));
-    flexarray_append(back, "state");
-    flexarray_append(back, libxl__sprintf(gc, "%d", 1));
-    flexarray_append(back, "dev");
-    flexarray_append(back, disk->vdev);
-    flexarray_append(back, "type");
-    flexarray_append(back, libxl__device_disk_string_of_backend(disk->backend));
-    flexarray_append(back, "mode");
-    flexarray_append(back, disk->readwrite ? "w" : "r");
-    flexarray_append(back, "device-type");
-    flexarray_append(back, disk->is_cdrom ? "cdrom" : "disk");
+        flexarray_append(back, "frontend-id");
+        flexarray_append(back, libxl__sprintf(gc, "%d", domid));
+        flexarray_append(back, "online");
+        flexarray_append(back, "1");
+        flexarray_append(back, "removable");
+        flexarray_append(back, libxl__sprintf(gc, "%d", (disk->removable) ? 1 : 0));
+        flexarray_append(back, "bootable");
+        flexarray_append(back, libxl__sprintf(gc, "%d", 1));
+        flexarray_append(back, "state");
+        flexarray_append(back, libxl__sprintf(gc, "%d", 1));
+        flexarray_append(back, "dev");
+        flexarray_append(back, disk->vdev);
+        flexarray_append(back, "type");
+        flexarray_append(back, libxl__device_disk_string_of_backend(disk->backend));
+        flexarray_append(back, "mode");
+        flexarray_append(back, disk->readwrite ? "w" : "r");
+        flexarray_append(back, "device-type");
+        flexarray_append(back, disk->is_cdrom ? "cdrom" : "disk");
+
+        flexarray_append(front, "backend-id");
+        flexarray_append(front, libxl__sprintf(gc, "%d", disk->backend_domid));
+        flexarray_append(front, "state");
+        flexarray_append(front, libxl__sprintf(gc, "%d", 1));
+        flexarray_append(front, "virtual-device");
+        flexarray_append(front, libxl__sprintf(gc, "%d", device.devid));
+        flexarray_append(front, "device-type");
+        flexarray_append(front, disk->is_cdrom ? "cdrom" : "disk");
 
-    flexarray_append(front, "backend-id");
-    flexarray_append(front, libxl__sprintf(gc, "%d", disk->backend_domid));
-    flexarray_append(front, "state");
-    flexarray_append(front, libxl__sprintf(gc, "%d", 1));
-    flexarray_append(front, "virtual-device");
-    flexarray_append(front, libxl__sprintf(gc, "%d", device.devid));
-    flexarray_append(front, "device-type");
-    flexarray_append(front, disk->is_cdrom ? "cdrom" : "disk");
+        libxl__device_generic_add(gc, t, &device,
+                            libxl__xs_kvs_of_flexarray(gc, back, back->count),
+                            libxl__xs_kvs_of_flexarray(gc, front, front->count));
 
-    libxl__device_generic_add(gc, t, &device,
-                             libxl__xs_kvs_of_flexarray(gc, back, back->count),
-                             libxl__xs_kvs_of_flexarray(gc, front, front->count));
+        rc = libxl__xs_transaction_commit(gc, &t);
+        if (!rc) break;
+        if (rc < 0) goto out_free;
+    }
 
     rc = 0;
 
@@ -1849,13 +1880,20 @@ out_free:
     flexarray_free(back);
     flexarray_free(front);
 out:
+    libxl__xs_transaction_abort(gc, &t);
     return rc;
 }
 
+int libxl__device_disk_add(libxl__gc *gc, uint32_t domid,
+                           libxl_device_disk *disk)
+{
+    return device_disk_add(gc, domid, disk, NULL, NULL);
+}
+
 int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
 {
     GC_INIT(ctx);
-    int rc = libxl__device_disk_add(gc, domid, XBT_NULL, disk);
+    int rc = libxl__device_disk_add(gc, domid, disk);
     GC_FREE;
     return rc;
 }
@@ -2113,9 +2151,8 @@ char * libxl__device_disk_local_attach(libxl__gc *gc,
     libxl_ctx *ctx = gc->owner;
     char *dev = NULL, *be_path = NULL;
     char *ret = NULL;
-    int rc, xs_ret;
+    int rc;
     libxl__device device;
-    xs_transaction_t t = XBT_NULL;
 
     if (in_disk->pdev_path == NULL)
         return NULL;
@@ -2159,27 +2196,9 @@ char * libxl__device_disk_local_attach(libxl__gc *gc,
             break;
         case LIBXL_DISK_BACKEND_QDISK:
             if (disk->format != LIBXL_DISK_FORMAT_RAW) {
-                do {
-                    t = xs_transaction_start(ctx->xsh);
-                    if (t == XBT_NULL) {
-                        LOG(ERROR, "failed to start a xenstore transaction");
-                        goto out;
-                    }
-                    disk->vdev = libxl__alloc_vdev(gc, blkdev_start, t);
-                    if (disk->vdev == NULL) {
-                        LOG(ERROR, "libxl__alloc_vdev failed");
-                        goto out;
-                    }
-                    if (libxl__device_disk_add(gc, LIBXL_TOOLSTACK_DOMID,
-                                t, disk)) {
-                        LOG(ERROR, "libxl_device_disk_add failed");
-                        goto out;
-                    }
-                    xs_ret = xs_transaction_end(ctx->xsh, t, 0);
-                } while (xs_ret == 0 && errno == EAGAIN);
-                t = XBT_NULL;
-                if (xs_ret == 0) {
-                    LOGE(ERROR, "xenstore transaction failed");
+                if (device_disk_add(gc, LIBXL_TOOLSTACK_DOMID, disk,
+                                    libxl__alloc_vdev, blkdev_start)) {
+                    LOG(ERROR, "libxl_device_disk_add failed");
                     goto out;
                 }
                 dev = GCSPRINTF("/dev/%s", disk->vdev);
@@ -2208,10 +2227,7 @@ char * libxl__device_disk_local_attach(libxl__gc *gc,
     return ret;
 
  out:
-    if (t != XBT_NULL)
-        xs_transaction_end(ctx->xsh, t, 1);
-    else
-        libxl__device_disk_local_detach(gc, disk);
+    libxl__device_disk_local_detach(gc, disk);
     return NULL;
 }
 
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 7a75809..1befdc5 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1291,7 +1291,7 @@ _hidden int libxl__device_from_disk(libxl__gc *gc, uint32_t domid,
                                    libxl_device_disk *disk,
                                    libxl__device *device);
 _hidden int libxl__device_disk_add(libxl__gc *gc, uint32_t domid,
-        xs_transaction_t t, libxl_device_disk *disk);
+                                   libxl_device_disk *disk);
 
 /*
  * Make a disk available in this (the control) domain. Returns path to
-- 
1.7.7.5 (Apple Git-26)

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v9 06/17] libxl: convert libxl__device_disk_local_attach to an async op
  2012-07-13  9:44 [PATCH v9 00/15] execute hotplug scripts from libxl Roger Pau Monne
                   ` (4 preceding siblings ...)
  2012-07-13  9:44 ` [PATCH v9 05/17] libxl: refactor disk addition to take a helper Roger Pau Monne
@ 2012-07-13  9:44 ` Roger Pau Monne
  2012-07-19 16:16   ` Ian Jackson
  2012-07-13  9:44 ` [PATCH v9 07/17] libxl: rename vifs to nics Roger Pau Monne
                   ` (10 subsequent siblings)
  16 siblings, 1 reply; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-13  9:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Stefano Stabellini, Ian Jackson, Roger Pau Monne

This will be needed in future patches, when libxl__device_disk_add
becomes async also. Create a new status structure that defines the
local attach of a disk device and use it in
libxl__device_disk_local_attach.

This is done in this patch to split the changes introduced when
libxl__device_disk_add becomes async.

Changes since v6:

 * Added better comments.

 * Instead of passing the xs_transaction arround several functions,
   put all the xs related operations inside device_disk_add.

 * Make sure libxl__device_disk_local_initiate_detach either calls the
   async device destroy function, or the callback.

Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Cc: Stefano Stabellini <stefano.stabellini@eu.citrix.com>
Signed-off-by: Roger Pau Monne <roger.pau@citrix.com>
---
 tools/libxl/libxl.c            |   99 +++++++++++++++++++++++++++++++--------
 tools/libxl/libxl_bootloader.c |   93 +++++++++++++++++++++++++++++++------
 tools/libxl/libxl_internal.h   |   66 +++++++++++++++++++++------
 3 files changed, 208 insertions(+), 50 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index cad1c3a..e1404a2 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2143,19 +2143,30 @@ static char * libxl__alloc_vdev(libxl__gc *gc, const char *blkdev_start,
     return NULL;
 }
 
-char * libxl__device_disk_local_attach(libxl__gc *gc,
-        const libxl_device_disk *in_disk,
-        libxl_device_disk *disk,
-        const char *blkdev_start)
+void libxl__device_disk_local_init(libxl__disk_local_state *dls, libxl__ao *ao,
+                                   libxl_device_disk *disk,
+                                   const char *blkdev_start,
+                                   libxl__disk_local_state_callback *callback)
 {
-    libxl_ctx *ctx = gc->owner;
+    dls->ao = ao;
+    dls->in_disk = disk;
+    dls->blkdev_start = blkdev_start;
+    dls->callback = callback;
+}
+
+void libxl__device_disk_local_initiate_attach(libxl__egc *egc,
+                                     libxl__disk_local_state *dls)
+{
+    STATE_AO_GC(dls->ao);
+    libxl_ctx *ctx = CTX;
     char *dev = NULL, *be_path = NULL;
-    char *ret = NULL;
     int rc;
     libxl__device device;
+    const libxl_device_disk *in_disk = dls->in_disk;
+    libxl_device_disk *disk = &dls->disk;
+    const char *blkdev_start = dls->blkdev_start;
 
-    if (in_disk->pdev_path == NULL)
-        return NULL;
+    assert(in_disk->pdev_path);
 
     memcpy(disk, in_disk, sizeof(libxl_device_disk));
     disk->pdev_path = libxl__strdup(gc, in_disk->pdev_path);
@@ -2191,6 +2202,7 @@ char * libxl__device_disk_local_attach(libxl__gc *gc,
             default:
                 LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
                            "unrecognized disk format: %d", disk->format);
+                rc = ERROR_FAIL;
                 break;
             }
             break;
@@ -2199,6 +2211,7 @@ char * libxl__device_disk_local_attach(libxl__gc *gc,
                 if (device_disk_add(gc, LIBXL_TOOLSTACK_DOMID, disk,
                                     libxl__alloc_vdev, blkdev_start)) {
                     LOG(ERROR, "libxl_device_disk_add failed");
+                    rc = ERROR_FAIL;
                     goto out;
                 }
                 dev = GCSPRINTF("/dev/%s", disk->vdev);
@@ -2210,6 +2223,7 @@ char * libxl__device_disk_local_attach(libxl__gc *gc,
         default:
             LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unrecognized disk backend "
                 "type: %d", disk->backend);
+            rc = ERROR_FAIL;
             break;
     }
 
@@ -2223,39 +2237,82 @@ char * libxl__device_disk_local_attach(libxl__gc *gc,
             goto out;
     }
     if (dev != NULL)
-        ret = strdup(dev);
-    return ret;
+        dls->diskpath = strdup(dev);
+
+    dls->callback(egc, dls, 0);
+    return;
 
  out:
-    libxl__device_disk_local_detach(gc, disk);
-    return NULL;
+    assert(rc);
+    dls->callback(egc, dls, rc);
 }
 
-int libxl__device_disk_local_detach(libxl__gc *gc, libxl_device_disk *disk)
+/* Callbacks for local detach */
+
+static void local_device_detach_cb(libxl__egc *egc, libxl__ao_device *aodev);
+
+void libxl__device_disk_local_initiate_detach(libxl__egc *egc,
+                                     libxl__disk_local_state *dls)
 {
+    STATE_AO_GC(dls->ao);
     int rc = 0;
+    libxl_device_disk *disk = &dls->disk;
+    libxl__device *device;
+    libxl__ao_device *aodev = &dls->aodev;
+
+    if (!dls->diskpath) {
+        dls->callback(egc, dls, rc);
+        return;
+    }
 
     switch (disk->backend) {
         case LIBXL_DISK_BACKEND_QDISK:
             if (disk->vdev != NULL) {
-                libxl_device_disk_remove(gc->owner, LIBXL_TOOLSTACK_DOMID,
-                        disk, 0);
-                /* fixme-ao */
-                rc = libxl_device_disk_destroy(gc->owner,
-                        LIBXL_TOOLSTACK_DOMID, disk, 0);
+                GCNEW(device);
+                rc = libxl__device_from_disk(gc, LIBXL_TOOLSTACK_DOMID,
+                                             disk, device);
+                if (rc != 0) goto out;
+
+                libxl__prepare_ao_device(ao, aodev);
+                aodev->action = DEVICE_DISCONNECT;
+                aodev->dev = device;
+                aodev->callback = local_device_detach_cb;
+                aodev->force = 0;
+                libxl__initiate_device_remove(egc, aodev);
+                return;
             }
-            break;
         default:
             /*
              * Nothing to do for PHYSTYPE_PHY.
              * For other device types assume that the blktap2 process is
              * needed by the soon to be started domain and do nothing.
              */
-            break;
+            dls->callback(egc, dls, rc);
+            return;
     }
 
+out:
+    assert(rc);
+    dls->callback(egc, dls, rc);
+    return;
+}
+
+static void local_device_detach_cb(libxl__egc *egc, libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+    libxl__disk_local_state *dls = CONTAINER_OF(aodev, *dls, aodev);
 
-    return rc;
+    if (aodev->rc) {
+        LOGE(ERROR, "unable to %s %s with id %u",
+                    aodev->action == DEVICE_CONNECT ? "add" : "remove",
+                    libxl__device_kind_to_string(aodev->dev->kind),
+                    aodev->dev->devid);
+        goto out;
+    }
+
+out:
+    dls->callback(egc, dls, aodev->rc);
+    return;
 }
 
 /******************************************************************************/
diff --git a/tools/libxl/libxl_bootloader.c b/tools/libxl/libxl_bootloader.c
index 7ebc0df..7ba3502 100644
--- a/tools/libxl/libxl_bootloader.c
+++ b/tools/libxl/libxl_bootloader.c
@@ -75,7 +75,7 @@ static void make_bootloader_args(libxl__gc *gc, libxl__bootloader_state *bl,
         }
     }
 
-    ARG(bl->diskpath);
+    ARG(bl->dls.diskpath);
 
     /* Sentinel for execv */
     ARG(NULL);
@@ -206,8 +206,9 @@ static int parse_bootloader_result(libxl__egc *egc,
 void libxl__bootloader_init(libxl__bootloader_state *bl)
 {
     assert(bl->ao);
-    bl->diskpath = NULL;
+    bl->dls.diskpath = NULL;
     bl->openpty.ao = bl->ao;
+    bl->dls.ao = bl->ao;
     bl->ptys[0].master = bl->ptys[0].slave = 0;
     bl->ptys[1].master = bl->ptys[1].slave = 0;
     libxl__ev_child_init(&bl->child);
@@ -224,11 +225,6 @@ static void bootloader_cleanup(libxl__egc *egc, libxl__bootloader_state *bl)
     if (bl->outputpath) libxl__remove_file(gc, bl->outputpath);
     if (bl->outputdir) libxl__remove_directory(gc, bl->outputdir);
 
-    if (bl->diskpath) {
-        libxl__device_disk_local_detach(gc, &bl->localdisk);
-        free(bl->diskpath);
-        bl->diskpath = 0;
-    }
     libxl__domaindeathcheck_stop(gc,&bl->deathcheck);
     libxl__datacopier_kill(&bl->keystrokes);
     libxl__datacopier_kill(&bl->display);
@@ -249,10 +245,35 @@ static void bootloader_setpaths(libxl__gc *gc, libxl__bootloader_state *bl)
     bl->outputpath = GCSPRINTF(XEN_RUN_DIR "/bootloader.%"PRIu32".out", domid);
 }
 
+/* Callbacks */
+
+static void bootloader_finished_cb(libxl__egc *egc,
+                                   libxl__disk_local_state *dls,
+                                   int rc);
+
 static void bootloader_callback(libxl__egc *egc, libxl__bootloader_state *bl,
                                 int rc)
 {
     bootloader_cleanup(egc, bl);
+
+    bl->dls.callback = bootloader_finished_cb;
+    libxl__device_disk_local_initiate_detach(egc, &bl->dls);
+}
+
+static void bootloader_finished_cb(libxl__egc *egc,
+                                   libxl__disk_local_state *dls,
+                                   int rc)
+{
+    STATE_AO_GC(dls->ao);
+    libxl__bootloader_state *bl = CONTAINER_OF(dls, *bl, dls);
+
+    free(bl->dls.diskpath);
+    bl->dls.diskpath = 0;
+
+    if (rc) {
+        LOG(ERROR, "unable to detach locally attached disk");
+    }
+
     bl->callback(egc, bl, rc);
 }
 
@@ -275,6 +296,16 @@ static void bootloader_abort(libxl__egc *egc,
 
 /*----- main flow of control -----*/
 
+/* Callbacks */
+
+static void bootloader_disk_attached_cb(libxl__egc *egc,
+                                        libxl__disk_local_state *dls,
+                                        int rc);
+
+static void bootloader_disk_failed_cb(libxl__egc *egc,
+                                      libxl__disk_local_state *dls,
+                                      int rc);
+
 void libxl__bootloader_run(libxl__egc *egc, libxl__bootloader_state *bl)
 {
     STATE_AO_GC(bl->ao);
@@ -282,7 +313,6 @@ void libxl__bootloader_run(libxl__egc *egc, libxl__bootloader_state *bl)
     uint32_t domid = bl->domid;
     char *logfile_tmp = NULL;
     int rc, r;
-    const char *bootloader;
 
     libxl__bootloader_init(bl);
 
@@ -344,11 +374,32 @@ void libxl__bootloader_run(libxl__egc *egc, libxl__bootloader_state *bl)
         goto out;
     }
 
-    bl->diskpath = libxl__device_disk_local_attach(gc, bl->disk, &bl->localdisk,
-            info->blkdev_start);
-    if (!bl->diskpath) {
-        rc = ERROR_FAIL;
-        goto out;
+    libxl__device_disk_local_init(&bl->dls, ao, bl->disk, info->blkdev_start,
+                                  bootloader_disk_attached_cb);
+    libxl__device_disk_local_initiate_attach(egc, &bl->dls);
+    return;
+
+ out:
+    assert(rc);
+ out_ok:
+    free(logfile_tmp);
+    bootloader_callback(egc, bl, rc);
+}
+
+static void bootloader_disk_attached_cb(libxl__egc *egc,
+                                        libxl__disk_local_state *dls,
+                                        int rc)
+{
+    STATE_AO_GC(dls->ao);
+    libxl__bootloader_state *bl = CONTAINER_OF(dls, *bl, dls);
+    const libxl_domain_build_info *info = bl->info;
+    const char *bootloader;
+
+    if (rc) {
+        LOG(ERROR, "failed to attach local disk for bootloader execution");
+        dls->callback = bootloader_disk_failed_cb;
+        libxl__device_disk_local_initiate_detach(egc, dls);
+        return;
     }
 
     LOG(DEBUG, "Config bootloader value: %s", info->u.pv.bootloader);
@@ -389,11 +440,23 @@ void libxl__bootloader_run(libxl__egc *egc, libxl__bootloader_state *bl)
 
  out:
     assert(rc);
- out_ok:
-    free(logfile_tmp);
     bootloader_callback(egc, bl, rc);
 }
 
+static void bootloader_disk_failed_cb(libxl__egc *egc,
+                                      libxl__disk_local_state *dls,
+                                      int rc)
+{
+    STATE_AO_GC(dls->ao);
+    libxl__bootloader_state *bl = CONTAINER_OF(dls, *bl, dls);
+
+    if (rc) {
+        LOG(ERROR, "failed to detach locally attached disk");
+    }
+
+    bootloader_callback(egc, bl, ERROR_FAIL);
+}
+
 static void bootloader_gotptys(libxl__egc *egc, libxl__openpty_state *op)
 {
     libxl__bootloader_state *bl = CONTAINER_OF(op, *bl, openpty);
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 1befdc5..8e256d9 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1293,17 +1293,6 @@ _hidden int libxl__device_from_disk(libxl__gc *gc, uint32_t domid,
 _hidden int libxl__device_disk_add(libxl__gc *gc, uint32_t domid,
                                    libxl_device_disk *disk);
 
-/*
- * Make a disk available in this (the control) domain. Returns path to
- * a device.
- */
-_hidden char * libxl__device_disk_local_attach(libxl__gc *gc,
-        const libxl_device_disk *in_disk,
-        libxl_device_disk *new_disk,
-        const char *blkdev_start);
-_hidden int libxl__device_disk_local_detach(libxl__gc *gc,
-        libxl_device_disk *disk);
-
 _hidden char *libxl__uuid2string(libxl__gc *gc, const libxl_uuid uuid);
 
 struct libxl__xen_console_reader {
@@ -1823,6 +1812,56 @@ struct libxl__ao_devices {
 _hidden void libxl__initiate_device_remove(libxl__egc *egc,
                                            libxl__ao_device *aodev);
 
+/*----- local disk attach: attach a disk locally to run the bootloader -----*/
+
+typedef struct libxl__disk_local_state libxl__disk_local_state;
+typedef void libxl__disk_local_state_callback(libxl__egc*,
+                                              libxl__disk_local_state*,
+                                              int rc);
+
+/* A libxl__disk_local_state may be in the following states:
+ * Undefined, Idle, Attaching, Attached, Detaching, Detached.
+ */
+struct libxl__disk_local_state {
+    /* filled by the user */
+    libxl__ao *ao;
+    const libxl_device_disk *in_disk;
+    libxl_device_disk disk;
+    const char *blkdev_start;
+    libxl__disk_local_state_callback *callback;
+    /* filled by libxl__device_disk_local_initiate_attach */
+    char *diskpath;
+    /* private for implementation of local detach */
+    libxl__ao_device aodev;
+};
+
+/* Initializes the state of a libxl__disk_local_state to init,
+ * can be called multiple times.
+ * State Undefined -> Idle
+ */
+_hidden void libxl__device_disk_local_init(libxl__disk_local_state *dls,
+                                           libxl__ao *ao,
+                                           libxl_device_disk *disk,
+                                           const char *blkdev_start,
+                                           libxl__disk_local_state_callback
+                                           *callback);
+
+/* Make a disk available in this (the control) domain. Always calls
+ * dls->callback when finished.
+ * State Idle -> Attached
+ */
+_hidden void libxl__device_disk_local_initiate_attach(libxl__egc *egc,
+                                                libxl__disk_local_state *dls);
+
+/* Disconnects a disk device form the control domain. If the passed
+ * dls is not attached (or has already been detached),
+ * libxl__device_disk_local_initiate_detach will just call the callback
+ * directly.
+ * State Idle/Attached -> Idle
+ */
+_hidden void libxl__device_disk_local_initiate_detach(libxl__egc *egc,
+                                                libxl__disk_local_state *dls);
+
 /*----- datacopier: copies data from one fd to another -----*/
 
 typedef struct libxl__datacopier_state libxl__datacopier_state;
@@ -2012,10 +2051,10 @@ struct libxl__bootloader_state {
     /* Should be zeroed by caller on entry.  Will be filled in by
      * bootloader machinery; represents the local attachment of the
      * disk for the benefit of the bootloader.  Must be detached by
-     * the caller using libxl__device_disk_local_detach, but only
+     * the caller using libxl__device_disk_local_initiate_detach, but only
      * after the domain's kernel and initramfs have been loaded into
      * memory and the file references disposed of. */
-    libxl_device_disk localdisk;
+    libxl__disk_local_state dls;
     uint32_t domid;
     /* outputs:
      *  - caller must initialise kernel and ramdisk to point to file
@@ -2027,7 +2066,6 @@ struct libxl__bootloader_state {
     const char *cmdline;
     /* private to libxl__run_bootloader */
     char *outputpath, *outputdir, *logfile;
-    char *diskpath; /* not from gc, represents actually attached disk */
     libxl__openpty_state openpty;
     libxl__openpty_result ptys[2];  /* [0] is for bootloader */
     libxl__ev_child child;
-- 
1.7.7.5 (Apple Git-26)

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v9 07/17] libxl: rename vifs to nics
  2012-07-13  9:44 [PATCH v9 00/15] execute hotplug scripts from libxl Roger Pau Monne
                   ` (5 preceding siblings ...)
  2012-07-13  9:44 ` [PATCH v9 06/17] libxl: convert libxl__device_disk_local_attach to an async op Roger Pau Monne
@ 2012-07-13  9:44 ` Roger Pau Monne
  2012-07-19 15:12   ` Ian Jackson
  2012-07-13  9:44 ` [PATCH v9 08/17] libxl: convert libxl_device_disk_add to an async op Roger Pau Monne
                   ` (9 subsequent siblings)
  16 siblings, 1 reply; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-13  9:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Roger Pau Monne

This change renames functions and struct values that used to contain
vifs in their names to nics, that provides a more clear name to
define network interfaces without referring to the backend that is
behind them.

This is not a functional change.

Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Roger Pau Monne <roger.pau@citrix.com>
---
 tools/libxl/libxl.h        |    4 +-
 tools/libxl/libxl_create.c |   10 ++++----
 tools/libxl/libxl_dm.c     |   54 ++++++++++++++++++++++----------------------
 tools/libxl/libxl_json.c   |    8 +++---
 tools/libxl/xl_cmdimpl.c   |   14 +++++-----
 tools/libxl/xl_sxp.c       |   20 ++++++++--------
 6 files changed, 55 insertions(+), 55 deletions(-)

diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 5c819f1..c730ac5 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -470,10 +470,10 @@ typedef struct {
     libxl_domain_create_info c_info;
     libxl_domain_build_info b_info;
 
-    int num_disks, num_vifs, num_pcidevs, num_vfbs, num_vkbs;
+    int num_disks, num_nics, num_pcidevs, num_vfbs, num_vkbs;
 
     libxl_device_disk *disks;
-    libxl_device_nic *vifs;
+    libxl_device_nic *nics;
     libxl_device_pci *pcidevs;
     libxl_device_vfb *vfbs;
     libxl_device_vkb *vkbs;
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 16d32c2..a4b8248 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -39,9 +39,9 @@ void libxl_domain_config_dispose(libxl_domain_config *d_config)
         libxl_device_disk_dispose(&d_config->disks[i]);
     free(d_config->disks);
 
-    for (i=0; i<d_config->num_vifs; i++)
-        libxl_device_nic_dispose(&d_config->vifs[i]);
-    free(d_config->vifs);
+    for (i=0; i<d_config->num_nics; i++)
+        libxl_device_nic_dispose(&d_config->nics[i]);
+    free(d_config->nics);
 
     for (i=0; i<d_config->num_pcidevs; i++)
         libxl_device_pci_dispose(&d_config->pcidevs[i]);
@@ -870,8 +870,8 @@ static void domcreate_rebuild_done(libxl__egc *egc,
             goto error_out;
         }
     }
-    for (i = 0; i < d_config->num_vifs; i++) {
-        ret = libxl_device_nic_add(ctx, domid, &d_config->vifs[i]);
+    for (i = 0; i < d_config->num_nics; i++) {
+        ret = libxl_device_nic_add(ctx, domid, &d_config->nics[i]);
         if (ret) {
             LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
                        "cannot add nic %d to domain: %d", i, ret);
diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index 6a041f9..4baf3f7 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -102,10 +102,10 @@ static char ** libxl__build_device_model_args_old(libxl__gc *gc,
 {
     const libxl_domain_create_info *c_info = &guest_config->c_info;
     const libxl_domain_build_info *b_info = &guest_config->b_info;
-    const libxl_device_nic *vifs = guest_config->vifs;
+    const libxl_device_nic *nics = guest_config->nics;
     const libxl_vnc_info *vnc = libxl__dm_vnc(guest_config);
     const libxl_sdl_info *sdl = dm_sdl(guest_config);
-    const int num_vifs = guest_config->num_vifs;
+    const int num_nics = guest_config->num_nics;
     const char *keymap = dm_keymap(guest_config);
     int i;
     flexarray_t *dm_args;
@@ -159,7 +159,7 @@ static char ** libxl__build_device_model_args_old(libxl__gc *gc,
         flexarray_vappend(dm_args, "-k", keymap, NULL);
     }
     if (b_info->type == LIBXL_DOMAIN_TYPE_HVM) {
-        int ioemu_vifs = 0;
+        int ioemu_nics = 0;
         int nr_set_cpus = 0;
         char *s;
 
@@ -214,31 +214,31 @@ static char ** libxl__build_device_model_args_old(libxl__gc *gc,
                               libxl__sprintf(gc, "%s", s), NULL);
         free(s);
 
-        for (i = 0; i < num_vifs; i++) {
-            if (vifs[i].nictype == LIBXL_NIC_TYPE_IOEMU) {
+        for (i = 0; i < num_nics; i++) {
+            if (nics[i].nictype == LIBXL_NIC_TYPE_IOEMU) {
                 char *smac = libxl__sprintf(gc,
-                                   LIBXL_MAC_FMT, LIBXL_MAC_BYTES(vifs[i].mac));
+                                   LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nics[i].mac));
                 const char *ifname = libxl__device_nic_devname(gc,
-                                                domid, vifs[i].devid,
+                                                domid, nics[i].devid,
                                                 LIBXL_NIC_TYPE_IOEMU);
                 flexarray_vappend(dm_args,
                                   "-net",
                                   GCSPRINTF(
                                       "nic,vlan=%d,macaddr=%s,model=%s",
-                                      vifs[i].devid, smac, vifs[i].model),
+                                      nics[i].devid, smac, nics[i].model),
                                   "-net",
                                   GCSPRINTF(
                                       "tap,vlan=%d,ifname=%s,bridge=%s,"
                                       "script=%s,downscript=%s",
-                                      vifs[i].devid, ifname, vifs[i].bridge,
+                                      nics[i].devid, ifname, nics[i].bridge,
                                       libxl_tapif_script(gc),
                                       libxl_tapif_script(gc)),
                                   NULL);
-                ioemu_vifs++;
+                ioemu_nics++;
             }
         }
         /* If we have no emulated nics, tell qemu not to create any */
-        if ( ioemu_vifs == 0 ) {
+        if ( ioemu_nics == 0 ) {
             flexarray_vappend(dm_args, "-net", "none", NULL);
         }
         if (libxl_defbool_val(b_info->u.hvm.gfx_passthru)) {
@@ -330,9 +330,9 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
     const libxl_domain_create_info *c_info = &guest_config->c_info;
     const libxl_domain_build_info *b_info = &guest_config->b_info;
     const libxl_device_disk *disks = guest_config->disks;
-    const libxl_device_nic *vifs = guest_config->vifs;
+    const libxl_device_nic *nics = guest_config->nics;
     const int num_disks = guest_config->num_disks;
-    const int num_vifs = guest_config->num_vifs;
+    const int num_nics = guest_config->num_nics;
     const libxl_vnc_info *vnc = libxl__dm_vnc(guest_config);
     const libxl_sdl_info *sdl = dm_sdl(guest_config);
     const char *keymap = dm_keymap(guest_config);
@@ -409,7 +409,7 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
     }
 
     if (b_info->type == LIBXL_DOMAIN_TYPE_HVM) {
-        int ioemu_vifs = 0;
+        int ioemu_nics = 0;
 
         if (b_info->u.hvm.serial) {
             flexarray_vappend(dm_args, "-serial", b_info->u.hvm.serial, NULL);
@@ -468,30 +468,30 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
                 flexarray_append(dm_args, libxl__sprintf(gc, "%d",
                                                          b_info->max_vcpus));
         }
-        for (i = 0; i < num_vifs; i++) {
-            if (vifs[i].nictype == LIBXL_NIC_TYPE_IOEMU) {
+        for (i = 0; i < num_nics; i++) {
+            if (nics[i].nictype == LIBXL_NIC_TYPE_IOEMU) {
                 char *smac = libxl__sprintf(gc,
-                                LIBXL_MAC_FMT, LIBXL_MAC_BYTES(vifs[i].mac));
+                                LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nics[i].mac));
                 const char *ifname = libxl__device_nic_devname(gc,
-                                                guest_domid, vifs[i].devid,
+                                                guest_domid, nics[i].devid,
                                                 LIBXL_NIC_TYPE_IOEMU);
                 flexarray_append(dm_args, "-device");
                 flexarray_append(dm_args,
                    libxl__sprintf(gc, "%s,id=nic%d,netdev=net%d,mac=%s",
-                                                vifs[i].model, vifs[i].devid,
-                                                vifs[i].devid, smac));
+                                                nics[i].model, nics[i].devid,
+                                                nics[i].devid, smac));
                 flexarray_append(dm_args, "-netdev");
                 flexarray_append(dm_args, GCSPRINTF(
                                           "type=tap,id=net%d,ifname=%s,"
                                           "script=%s,downscript=%s",
-                                          vifs[i].devid, ifname,
+                                          nics[i].devid, ifname,
                                           libxl_tapif_script(gc),
                                           libxl_tapif_script(gc)));
-                ioemu_vifs++;
+                ioemu_nics++;
             }
         }
         /* If we have no emulated nics, tell qemu not to create any */
-        if ( ioemu_vifs == 0 ) {
+        if ( ioemu_nics == 0 ) {
             flexarray_append(dm_args, "-net");
             flexarray_append(dm_args, "none");
         }
@@ -753,8 +753,8 @@ void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state *sdss)
     dm_config->disks = guest_config->disks;
     dm_config->num_disks = guest_config->num_disks;
 
-    dm_config->vifs = guest_config->vifs;
-    dm_config->num_vifs = guest_config->num_vifs;
+    dm_config->nics = guest_config->nics;
+    dm_config->num_nics = guest_config->num_nics;
 
     ret = libxl__domain_create_info_setdefault(gc, &dm_config->c_info);
     if (ret) goto out;
@@ -827,8 +827,8 @@ retry_transaction:
         if (ret)
             goto out_free;
     }
-    for (i = 0; i < dm_config->num_vifs; i++) {
-        ret = libxl_device_nic_add(ctx, dm_domid, &dm_config->vifs[i]);
+    for (i = 0; i < dm_config->num_nics; i++) {
+        ret = libxl_device_nic_add(ctx, dm_domid, &dm_config->nics[i]);
         if (ret)
             goto out_free;
     }
diff --git a/tools/libxl/libxl_json.c b/tools/libxl/libxl_json.c
index e870606..caa8312 100644
--- a/tools/libxl/libxl_json.c
+++ b/tools/libxl/libxl_json.c
@@ -822,15 +822,15 @@ yajl_gen_status libxl_domain_config_gen_json(yajl_gen hand,
     if (s != yajl_gen_status_ok)
         goto out;
 
-    s = yajl_gen_string(hand, (const unsigned char *)"vifs",
-                        sizeof("vifs")-1);
+    s = yajl_gen_string(hand, (const unsigned char *)"nics",
+                        sizeof("nics")-1);
     if (s != yajl_gen_status_ok)
         goto out;
     s = yajl_gen_array_open(hand);
     if (s != yajl_gen_status_ok)
         goto out;
-    for (i = 0; i < p->num_vifs; i++) {
-        s = libxl_device_nic_gen_json(hand, &p->vifs[i]);
+    for (i = 0; i < p->num_nics; i++) {
+        s = libxl_device_nic_gen_json(hand, &p->nics[i]);
         if (s != yajl_gen_status_ok)
             goto out;
     }
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 61791e1..8c04fe6 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -920,17 +920,17 @@ static void parse_config_data(const char *config_source,
     }
 
     if (!xlu_cfg_get_list (config, "vif", &nics, 0, 0)) {
-        d_config->num_vifs = 0;
-        d_config->vifs = NULL;
-        while ((buf = xlu_cfg_get_listitem (nics, d_config->num_vifs)) != NULL) {
+        d_config->num_nics = 0;
+        d_config->nics = NULL;
+        while ((buf = xlu_cfg_get_listitem (nics, d_config->num_nics)) != NULL) {
             libxl_device_nic *nic;
             char *buf2 = strdup(buf);
             char *p, *p2;
 
-            d_config->vifs = (libxl_device_nic *) realloc(d_config->vifs, sizeof (libxl_device_nic) * (d_config->num_vifs+1));
-            nic = d_config->vifs + d_config->num_vifs;
+            d_config->nics = (libxl_device_nic *) realloc(d_config->nics, sizeof (libxl_device_nic) * (d_config->num_nics+1));
+            nic = d_config->nics + d_config->num_nics;
             libxl_device_nic_init(nic);
-            nic->devid = d_config->num_vifs;
+            nic->devid = d_config->num_nics;
 
             if (default_vifscript) {
                 free(nic->script);
@@ -1003,7 +1003,7 @@ static void parse_config_data(const char *config_source,
             } while ((p = strtok(NULL, ",")) != NULL);
 skip:
             free(buf2);
-            d_config->num_vifs++;
+            d_config->num_nics++;
         }
     }
 
diff --git a/tools/libxl/xl_sxp.c b/tools/libxl/xl_sxp.c
index 6e0a389..91f8f75 100644
--- a/tools/libxl/xl_sxp.c
+++ b/tools/libxl/xl_sxp.c
@@ -175,20 +175,20 @@ void printf_info_sexp(int domid, libxl_domain_config *d_config)
         printf("\t)\n");
     }
 
-    for (i = 0; i < d_config->num_vifs; i++) {
+    for (i = 0; i < d_config->num_nics; i++) {
         printf("\t(device\n");
         printf("\t\t(vif\n");
-        if (d_config->vifs[i].ifname)
-            printf("\t\t\t(vifname %s)\n", d_config->vifs[i].ifname);
-        printf("\t\t\t(backend_domid %d)\n", d_config->vifs[i].backend_domid);
+        if (d_config->nics[i].ifname)
+            printf("\t\t\t(vifname %s)\n", d_config->nics[i].ifname);
+        printf("\t\t\t(backend_domid %d)\n", d_config->nics[i].backend_domid);
         printf("\t\t\t(frontend_domid %d)\n", domid);
-        printf("\t\t\t(devid %d)\n", d_config->vifs[i].devid);
-        printf("\t\t\t(mtu %d)\n", d_config->vifs[i].mtu);
-        printf("\t\t\t(model %s)\n", d_config->vifs[i].model);
+        printf("\t\t\t(devid %d)\n", d_config->nics[i].devid);
+        printf("\t\t\t(mtu %d)\n", d_config->nics[i].mtu);
+        printf("\t\t\t(model %s)\n", d_config->nics[i].model);
         printf("\t\t\t(mac %02x%02x%02x%02x%02x%02x)\n",
-               d_config->vifs[i].mac[0], d_config->vifs[i].mac[1],
-               d_config->vifs[i].mac[2], d_config->vifs[i].mac[3],
-               d_config->vifs[i].mac[4], d_config->vifs[i].mac[5]);
+               d_config->nics[i].mac[0], d_config->nics[i].mac[1],
+               d_config->nics[i].mac[2], d_config->nics[i].mac[3],
+               d_config->nics[i].mac[4], d_config->nics[i].mac[5]);
         printf("\t\t)\n");
         printf("\t)\n");
     }
-- 
1.7.7.5 (Apple Git-26)

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v9 08/17] libxl: convert libxl_device_disk_add to an async op
  2012-07-13  9:44 [PATCH v9 00/15] execute hotplug scripts from libxl Roger Pau Monne
                   ` (6 preceding siblings ...)
  2012-07-13  9:44 ` [PATCH v9 07/17] libxl: rename vifs to nics Roger Pau Monne
@ 2012-07-13  9:44 ` Roger Pau Monne
  2012-07-19 15:58   ` Ian Jackson
  2012-07-20  9:41   ` Ian Campbell
  2012-07-13  9:44 ` [PATCH v9 09/17] libxl: convert libxl_device_nic_add to an async operation Roger Pau Monne
                   ` (8 subsequent siblings)
  16 siblings, 2 replies; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-13  9:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Roger Pau Monne

This patch converts libxl_device_disk_add to an ao operation that
waits for device backend to reach state XenbusStateInitWait and then
marks the operation as completed. This is not really useful now, but
will be used by later patches that will launch hotplug scripts after
we reached the desired xenbus state.

As usual, libxl_device_disk_add callers have been modified, and the
internal function libxl__device_disk_add has been used if the call was
inside an already running ao.

Changes since v8:

 * Added a macro to define libxl_device_{type}_add functions, since
   they are all equal (just like for device removal/destroy).

Changes since v6:

 * Fixed comments.

 * Rename libxl__initiate_device_connection to
   libxl__wait_device_connection.

 * Cancel backend devstate watch if local attach of disk fails.

Changes since v5:

 * Change the disk addition to use the new ao_devices structure.

 * Change name and comment of _initiate_device_add to
   _initiate_device_connect.

Changes since v4:

 * Added more comments about libxl__device_disk_add and
   libxl__add_disks.

 * Removed stray hunk in Makefile.

 * Fixed _prepare call libxl__add_disks (separate into a different
   loop).

 * Moved some code to check if disks have finished to a macro that
   generates a custom function, which will also be used for vif
   interfaces.

Changes since v2:

 * Remove state read from libxl__initiate_device_add

Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Roger Pau Monne <roger.pau@citrix.com>
---
 tools/libxl/libxl.c          |  148 ++++++++++++++++++++++++++++++------------
 tools/libxl/libxl.h          |    4 +-
 tools/libxl/libxl_create.c   |   42 +++++++++---
 tools/libxl/libxl_device.c   |   63 ++++++++++++++++++
 tools/libxl/libxl_dm.c       |   73 +++++++++++++++------
 tools/libxl/libxl_internal.h |   42 +++++++++++-
 tools/libxl/xl_cmdimpl.c     |    2 +-
 7 files changed, 299 insertions(+), 75 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index e1404a2..5b24719 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1737,16 +1737,18 @@ int libxl__device_from_disk(libxl__gc *gc, uint32_t domid,
  * all other users should instead use the regular
  * libxl__device_disk_add wrapper
  */
-static int device_disk_add(libxl__gc *gc, uint32_t domid,
-                           libxl_device_disk *disk,
-                           char *(*fn)(libxl__gc *, const char *,
+static void device_disk_add(libxl__egc *egc, uint32_t domid,
+                            libxl_device_disk *disk,
+                            libxl__ao_device *aodev,
+                            char *(*fn)(libxl__gc *, const char *,
                                               xs_transaction_t),
-                           const char *blkdev_start)
+                            const char *blkdev_start)
 {
+    STATE_AO_GC(aodev->ao);
     flexarray_t *front = NULL;
     flexarray_t *back = NULL;
     char *dev;
-    libxl__device device;
+    libxl__device *device;
     int major, minor, rc;
     libxl_ctx *ctx = gc->owner;
     xs_transaction_t t = XBT_NULL;
@@ -1790,7 +1792,8 @@ static int device_disk_add(libxl__gc *gc, uint32_t domid,
             goto out_free;
         }
 
-        rc = libxl__device_from_disk(gc, domid, disk, &device);
+        GCNEW(device);
+        rc = libxl__device_from_disk(gc, domid, disk, device);
         if (rc != 0) {
             LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "Invalid or unsupported"
                    " virtual disk identifier %s", disk->vdev);
@@ -1808,7 +1811,7 @@ static int device_disk_add(libxl__gc *gc, uint32_t domid,
                 flexarray_append(back, "params");
                 flexarray_append(back, dev);
 
-                assert(device.backend_kind == LIBXL__DEVICE_KIND_VBD);
+                assert(device->backend_kind == LIBXL__DEVICE_KIND_VBD);
                 break;
             case LIBXL_DISK_BACKEND_TAP:
                 dev = libxl__blktap_devpath(gc, disk->pdev_path, disk->format);
@@ -1829,7 +1832,7 @@ static int device_disk_add(libxl__gc *gc, uint32_t domid,
                 flexarray_append(back, "params");
                 flexarray_append(back, libxl__sprintf(gc, "%s:%s",
                               libxl__device_disk_string_of_format(disk->format), disk->pdev_path));
-                assert(device.backend_kind == LIBXL__DEVICE_KIND_QDISK);
+                assert(device->backend_kind == LIBXL__DEVICE_KIND_QDISK);
                 break;
             default:
                 LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "unrecognized disk backend type: %d\n", disk->backend);
@@ -1861,11 +1864,11 @@ static int device_disk_add(libxl__gc *gc, uint32_t domid,
         flexarray_append(front, "state");
         flexarray_append(front, libxl__sprintf(gc, "%d", 1));
         flexarray_append(front, "virtual-device");
-        flexarray_append(front, libxl__sprintf(gc, "%d", device.devid));
+        flexarray_append(front, libxl__sprintf(gc, "%d", device->devid));
         flexarray_append(front, "device-type");
         flexarray_append(front, disk->is_cdrom ? "cdrom" : "disk");
 
-        libxl__device_generic_add(gc, t, &device,
+        libxl__device_generic_add(gc, t, device,
                             libxl__xs_kvs_of_flexarray(gc, back, back->count),
                             libxl__xs_kvs_of_flexarray(gc, front, front->count));
 
@@ -1874,6 +1877,10 @@ static int device_disk_add(libxl__gc *gc, uint32_t domid,
         if (rc < 0) goto out_free;
     }
 
+    aodev->dev = device;
+    aodev->action = DEVICE_CONNECT;
+    libxl__wait_device_connection(egc, aodev);
+
     rc = 0;
 
 out_free:
@@ -1881,21 +1888,15 @@ out_free:
     flexarray_free(front);
 out:
     libxl__xs_transaction_abort(gc, &t);
-    return rc;
-}
-
-int libxl__device_disk_add(libxl__gc *gc, uint32_t domid,
-                           libxl_device_disk *disk)
-{
-    return device_disk_add(gc, domid, disk, NULL, NULL);
+    aodev->rc = rc;
+    if (rc) aodev->callback(egc, aodev);
+    return;
 }
 
-int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
+void libxl__device_disk_add(libxl__egc *egc, uint32_t domid,
+                           libxl_device_disk *disk, libxl__ao_device *aodev)
 {
-    GC_INIT(ctx);
-    int rc = libxl__device_disk_add(gc, domid, disk);
-    GC_FREE;
-    return rc;
+    device_disk_add(egc, domid, disk, aodev, NULL, NULL);
 }
 
 static void libxl__device_disk_from_xs_be(libxl__gc *gc,
@@ -2098,11 +2099,13 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk)
     ret = 0;
 
     libxl_device_disk_remove(ctx, domid, disks + i, 0);
-    libxl_device_disk_add(ctx, domid, disk);
+    /* fixme-ao */
+    libxl_device_disk_add(ctx, domid, disk, 0);
     stubdomid = libxl_get_stubdom_id(ctx, domid);
     if (stubdomid) {
         libxl_device_disk_remove(ctx, stubdomid, disks + i, 0);
-        libxl_device_disk_add(ctx, stubdomid, disk);
+        /* fixme-ao */
+        libxl_device_disk_add(ctx, stubdomid, disk, 0);
     }
 out:
     for (i = 0; i < num; i++)
@@ -2154,14 +2157,17 @@ void libxl__device_disk_local_init(libxl__disk_local_state *dls, libxl__ao *ao,
     dls->callback = callback;
 }
 
+/* Callbacks */
+
+static void local_device_attach_cb(libxl__egc *egc, libxl__ao_device *aodev);
+
 void libxl__device_disk_local_initiate_attach(libxl__egc *egc,
                                      libxl__disk_local_state *dls)
 {
     STATE_AO_GC(dls->ao);
     libxl_ctx *ctx = CTX;
-    char *dev = NULL, *be_path = NULL;
+    char *dev = NULL;
     int rc;
-    libxl__device device;
     const libxl_device_disk *in_disk = dls->in_disk;
     libxl_device_disk *disk = &dls->disk;
     const char *blkdev_start = dls->blkdev_start;
@@ -2208,13 +2214,12 @@ void libxl__device_disk_local_initiate_attach(libxl__egc *egc,
             break;
         case LIBXL_DISK_BACKEND_QDISK:
             if (disk->format != LIBXL_DISK_FORMAT_RAW) {
-                if (device_disk_add(gc, LIBXL_TOOLSTACK_DOMID, disk,
-                                    libxl__alloc_vdev, blkdev_start)) {
-                    LOG(ERROR, "libxl_device_disk_add failed");
-                    rc = ERROR_FAIL;
-                    goto out;
-                }
-                dev = GCSPRINTF("/dev/%s", disk->vdev);
+                libxl__prepare_ao_device(ao, &dls->aodev);
+                dls->aodev.callback = local_device_attach_cb;
+                device_disk_add(egc, LIBXL_TOOLSTACK_DOMID, disk,
+                                &dls->aodev, libxl__alloc_vdev,
+                                blkdev_start);
+                return;
             } else {
                 dev = disk->pdev_path;
             }
@@ -2227,15 +2232,46 @@ void libxl__device_disk_local_initiate_attach(libxl__egc *egc,
             break;
     }
 
-    if (disk->vdev != NULL) {
-        rc = libxl__device_from_disk(gc, LIBXL_TOOLSTACK_DOMID, disk, &device);
-        if (rc < 0)
-            goto out;
-        be_path = libxl__device_backend_path(gc, &device);
-        rc = libxl__wait_for_backend(gc, be_path, "4");
-        if (rc < 0)
-            goto out;
+    if (dev != NULL)
+        dls->diskpath = strdup(dev);
+
+    dls->callback(egc, dls, 0);
+    return;
+
+ out:
+    assert(rc);
+    dls->callback(egc, dls, rc);
+}
+
+static void local_device_attach_cb(libxl__egc *egc, libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+    libxl__disk_local_state *dls = CONTAINER_OF(aodev, *dls, aodev);
+    char *dev = NULL, *be_path = NULL;
+    int rc;
+    libxl__device device;
+    libxl_device_disk *disk = &dls->disk;
+
+    rc = aodev->rc;
+    if (rc) {
+        LOGE(ERROR, "unable to %s %s with id %u",
+                    aodev->action == DEVICE_CONNECT ? "add" : "remove",
+                    libxl__device_kind_to_string(aodev->dev->kind),
+                    aodev->dev->devid);
+        goto out;
     }
+
+    dev = GCSPRINTF("/dev/%s", disk->vdev);
+    LOG(DEBUG, "locally attaching qdisk %s", dev);
+
+    rc = libxl__device_from_disk(gc, LIBXL_TOOLSTACK_DOMID, disk, &device);
+    if (rc < 0)
+        goto out;
+    be_path = libxl__device_backend_path(gc, &device);
+    rc = libxl__wait_for_backend(gc, be_path, "4");
+    if (rc < 0)
+        goto out;
+
     if (dev != NULL)
         dls->diskpath = strdup(dev);
 
@@ -2953,6 +2989,36 @@ DEFINE_DEVICE_REMOVE(vfb, destroy, 1)
 
 /******************************************************************************/
 
+/* Macro for defining device addition functions in a compact way */
+/* The following functions are defined:
+ * libxl_device_disk_add
+ */
+
+#define DEFINE_DEVICE_ADD(type)                                         \
+    int libxl_device_##type##_add(libxl_ctx *ctx,                       \
+        uint32_t domid, libxl_device_##type *type,                      \
+        const libxl_asyncop_how *ao_how)                                \
+    {                                                                   \
+        AO_CREATE(ctx, domid, ao_how);                                  \
+        libxl__ao_device *aodev;                                        \
+                                                                        \
+        GCNEW(aodev);                                                   \
+        libxl__prepare_ao_device(ao, aodev);                            \
+        aodev->callback = device_addrm_aocomplete;                      \
+        libxl__device_##type##_add(egc, domid, type, aodev);            \
+                                                                        \
+        return AO_INPROGRESS;                                           \
+    }
+
+/* Define alladd functions and undef the macro */
+
+/* disk */
+DEFINE_DEVICE_ADD(disk)
+
+#undef DEFINE_DEVICE_ADD
+
+/******************************************************************************/
+
 int libxl_domain_setmaxmem(libxl_ctx *ctx, uint32_t domid, uint32_t max_memkb)
 {
     GC_INIT(ctx);
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index c730ac5..f3161d5 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -675,7 +675,9 @@ void libxl_vcpuinfo_list_free(libxl_vcpuinfo *, int nr_vcpus);
  */
 
 /* Disks */
-int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk);
+int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid,
+                          libxl_device_disk *disk,
+                          const libxl_asyncop_how *ao_how);
 int libxl_device_disk_remove(libxl_ctx *ctx, uint32_t domid,
                              libxl_device_disk *disk,
                              const libxl_asyncop_how *ao_how);
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index a4b8248..181eb53 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -558,6 +558,10 @@ static void domcreate_bootloader_console_available(libxl__egc *egc,
 static void domcreate_bootloader_done(libxl__egc *egc,
                                       libxl__bootloader_state *bl,
                                       int rc);
+
+static void domcreate_launch_dm(libxl__egc *egc, libxl__ao_devices *aodevs,
+                                int ret);
+
 static void domcreate_console_available(libxl__egc *egc,
                                         libxl__domain_create_state *dcs);
 
@@ -845,12 +849,10 @@ static void domcreate_rebuild_done(libxl__egc *egc,
                                    int ret)
 {
     STATE_AO_GC(dcs->ao);
-    int i;
 
     /* convenience aliases */
     const uint32_t domid = dcs->guest_domid;
     libxl_domain_config *const d_config = dcs->guest_config;
-    libxl__domain_build_state *const state = &dcs->build_state;
     libxl_ctx *const ctx = CTX;
 
     if (ret) {
@@ -861,14 +863,34 @@ static void domcreate_rebuild_done(libxl__egc *egc,
 
     store_libxl_entry(gc, domid, &d_config->b_info);
 
-    for (i = 0; i < d_config->num_disks; i++) {
-        ret = libxl_device_disk_add(ctx, domid, &d_config->disks[i]);
-        if (ret) {
-            LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
-                       "cannot add disk %d to domain: %d", i, ret);
-            ret = ERROR_FAIL;
-            goto error_out;
-        }
+    dcs->aodevs.size = d_config->num_disks;
+    dcs->aodevs.callback = domcreate_launch_dm;
+    libxl__prepare_ao_devices(ao, &dcs->aodevs);
+    libxl__add_disks(egc, ao, domid, 0, d_config, &dcs->aodevs);
+
+    return;
+
+ error_out:
+    assert(ret);
+    domcreate_complete(egc, dcs, ret);
+}
+
+static void domcreate_launch_dm(libxl__egc *egc, libxl__ao_devices *aodevs,
+                                int ret)
+{
+    libxl__domain_create_state *dcs = CONTAINER_OF(aodevs, *dcs, aodevs);
+    STATE_AO_GC(dcs->ao);
+    int i;
+
+    /* convenience aliases */
+    const uint32_t domid = dcs->guest_domid;
+    libxl_domain_config *const d_config = dcs->guest_config;
+    libxl__domain_build_state *const state = &dcs->build_state;
+    libxl_ctx *const ctx = CTX;
+
+    if (ret) {
+        LOG(ERROR, "unable to add disk devices");
+        goto error_out;
     }
     for (i = 0; i < d_config->num_nics; i++) {
         ret = libxl_device_nic_add(ctx, domid, &d_config->nics[i]);
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 766f9f2..2a98112 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -442,6 +442,37 @@ void libxl__ao_devices_callback(libxl__egc *egc, libxl__ao_device *aodev)
     return;
 }
 
+/******************************************************************************/
+
+/* Macro for defining the functions that will add a bunch of disks when
+ * inside an async op.
+ * This macro is added to prevent repetition of code.
+ *
+ * The following functions are defined:
+ * libxl__add_disks
+ */
+
+#define DEFINE_DEVICES_ADD(type)                                               \
+    void libxl__add_##type##s(libxl__egc *egc, libxl__ao *ao, uint32_t domid,  \
+                              int start, libxl_domain_config *d_config,        \
+                              libxl__ao_devices *aodevs)                       \
+    {                                                                          \
+        AO_GC;                                                                 \
+        int i;                                                                 \
+        int end = start + d_config->num_##type##s;                             \
+        for (i = start; i < end; i++) {                                        \
+            aodevs->array[i].callback = libxl__ao_devices_callback;            \
+            libxl__device_##type##_add(egc, domid, &d_config->type##s[i-start],\
+                                       &aodevs->array[i]);                     \
+        }                                                                      \
+    }
+
+DEFINE_DEVICES_ADD(disk)
+
+#undef DEFINE_DEVICES_ADD
+
+/******************************************************************************/
+
 int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
 {
     libxl_ctx *ctx = libxl__gc_owner(gc);
@@ -566,6 +597,38 @@ static void device_backend_cleanup(libxl__gc *gc,
 
 static void device_xsentries_remove(libxl__egc *egc, libxl__ao_device *aodev);
 
+void libxl__wait_device_connection(libxl__egc *egc, libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+    char *be_path = libxl__device_backend_path(gc, aodev->dev);
+    char *state_path = libxl__sprintf(gc, "%s/state", be_path);
+    int rc = 0;
+
+    if (aodev->dev->backend_kind == LIBXL__DEVICE_KIND_QDISK) {
+        /*
+         * Qdisk will not switch to state InitWait, because
+         * Qemu hasn't been launched yet.
+         */
+         goto out;
+    }
+
+    rc = libxl__ev_devstate_wait(gc, &aodev->backend_ds,
+                                 device_backend_callback,
+                                 state_path, XenbusStateInitWait,
+                                 LIBXL_INIT_TIMEOUT * 1000);
+    if (rc) {
+        LOG(ERROR, "unable to initialize device %s", be_path);
+        goto out;
+    }
+
+    return;
+
+out:
+    aodev->rc = rc;
+    device_xsentries_remove(egc, aodev);
+    return;
+}
+
 void libxl__initiate_device_remove(libxl__egc *egc,
                                    libxl__ao_device *aodev)
 {
diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index 4baf3f7..9a5cb0a 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -694,6 +694,9 @@ static void spawn_stubdom_pvqemu_cb(libxl__egc *egc,
                                 libxl__dm_spawn_state *stubdom_dmss,
                                 int rc);
 
+static void spawn_stub_launch_dm(libxl__egc *egc,
+                                 libxl__ao_devices *aodevs, int ret);
+
 static void spaw_stubdom_pvqemu_destroy_cb(libxl__egc *egc,
                                            libxl__destroy_domid_state *dis,
                                            int rc);
@@ -702,10 +705,9 @@ void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state *sdss)
 {
     STATE_AO_GC(sdss->dm.spawn.ao);
     libxl_ctx *ctx = libxl__gc_owner(gc);
-    int i, num_console = STUBDOM_SPECIAL_CONSOLES, ret;
-    libxl__device_console *console;
-    libxl_device_vfb vfb;
-    libxl_device_vkb vkb;
+    int ret;
+    libxl_device_vfb *vfb;
+    libxl_device_vkb *vkb;
     char **args;
     struct xs_permissions perm[2];
     xs_transaction_t t;
@@ -761,10 +763,12 @@ void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state *sdss)
     ret = libxl__domain_build_info_setdefault(gc, &dm_config->b_info);
     if (ret) goto out;
 
-    libxl__vfb_and_vkb_from_hvm_guest_config(gc, guest_config, &vfb, &vkb);
-    dm_config->vfbs = &vfb;
+    GCNEW(vfb);
+    GCNEW(vkb);
+    libxl__vfb_and_vkb_from_hvm_guest_config(gc, guest_config, vfb, vkb);
+    dm_config->vfbs = vfb;
     dm_config->num_vfbs = 1;
-    dm_config->vkbs = &vkb;
+    dm_config->vkbs = vkb;
     dm_config->num_vkbs = 1;
 
     stubdom_state->pv_kernel.path
@@ -822,22 +826,54 @@ retry_transaction:
         if (errno == EAGAIN)
             goto retry_transaction;
 
-    for (i = 0; i < dm_config->num_disks; i++) {
-        ret = libxl_device_disk_add(ctx, dm_domid, &dm_config->disks[i]);
-        if (ret)
-            goto out_free;
-    }
+    sdss->aodevs.size = dm_config->num_disks;
+    sdss->aodevs.callback = spawn_stub_launch_dm;
+    libxl__prepare_ao_devices(ao, &sdss->aodevs);
+    libxl__add_disks(egc, ao, dm_domid, 0, dm_config, &sdss->aodevs);
+
+    free(args);
+    return;
+
+out_free:
+    free(args);
+out:
+    assert(ret);
+    spawn_stubdom_pvqemu_cb(egc, &sdss->pvqemu, ret);
+}
+
+static void spawn_stub_launch_dm(libxl__egc *egc,
+                                 libxl__ao_devices *aodevs, int ret)
+{
+    libxl__stub_dm_spawn_state *sdss = CONTAINER_OF(aodevs, *sdss, aodevs);
+    STATE_AO_GC(sdss->dm.spawn.ao);
+    libxl_ctx *ctx = libxl__gc_owner(gc);
+    int i, num_console = STUBDOM_SPECIAL_CONSOLES;
+    libxl__device_console *console;
+
+    /* convenience aliases */
+    libxl_domain_config *const dm_config = &sdss->dm_config;
+    libxl_domain_config *const guest_config = sdss->dm.guest_config;
+    const int guest_domid = sdss->dm.guest_domid;
+    libxl__domain_build_state *const d_state = sdss->dm.build_state;
+    libxl__domain_build_state *const stubdom_state = &sdss->dm_state;
+    uint32_t dm_domid = sdss->pvqemu.guest_domid;
+
+    if (ret) {
+        LOG(ERROR, "error connecting disk devices");
+        goto out;
+     }
+
     for (i = 0; i < dm_config->num_nics; i++) {
         ret = libxl_device_nic_add(ctx, dm_domid, &dm_config->nics[i]);
         if (ret)
-            goto out_free;
+            goto out;
     }
     ret = libxl_device_vfb_add(ctx, dm_domid, &dm_config->vfbs[0]);
     if (ret)
-        goto out_free;
+        goto out;
     ret = libxl_device_vkb_add(ctx, dm_domid, &dm_config->vkbs[0]);
     if (ret)
-        goto out_free;
+        goto out;
 
     if (guest_config->b_info.u.hvm.serial)
         num_console++;
@@ -845,7 +881,7 @@ retry_transaction:
     console = libxl__calloc(gc, num_console, sizeof(libxl__device_console));
     if (!console) {
         ret = ERROR_NOMEM;
-        goto out_free;
+        goto out;
     }
 
     for (i = 0; i < num_console; i++) {
@@ -881,7 +917,7 @@ retry_transaction:
         ret = libxl__device_console_add(gc, dm_domid, &console[i],
                         i == STUBDOM_CONSOLE_LOGGING ? stubdom_state : NULL);
         if (ret)
-            goto out_free;
+            goto out;
     }
 
     sdss->pvqemu.spawn.ao = ao;
@@ -892,11 +928,8 @@ retry_transaction:
 
     libxl__spawn_local_dm(egc, &sdss->pvqemu);
 
-    free(args);
     return;
 
-out_free:
-    free(args);
 out:
     assert(ret);
     spawn_stubdom_pvqemu_cb(egc, &sdss->pvqemu, ret);
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 8e256d9..981771a 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -72,6 +72,7 @@
 #include "_libxl_types_internal.h"
 #include "_libxl_types_internal_json.h"
 
+#define LIBXL_INIT_TIMEOUT 10
 #define LIBXL_DESTROY_TIMEOUT 10
 #define LIBXL_DEVICE_MODEL_START_TIMEOUT 10
 #define LIBXL_XENCONSOLE_LIMIT 1048576
@@ -1290,8 +1291,6 @@ _hidden void libxl__device_destroy_tapdisk(libxl__gc *gc, char *be_path);
 _hidden int libxl__device_from_disk(libxl__gc *gc, uint32_t domid,
                                    libxl_device_disk *disk,
                                    libxl__device *device);
-_hidden int libxl__device_disk_add(libxl__gc *gc, uint32_t domid,
-                                   libxl_device_disk *disk);
 
 _hidden char *libxl__uuid2string(libxl__gc *gc, const libxl_uuid uuid);
 
@@ -1800,6 +1799,28 @@ struct libxl__ao_devices {
     libxl__devices_callback *callback;
 };
 
+/* AO operation to connect a disk device, called by
+ * libxl_device_disk_add and libxl__add_disks. This function calls
+ * libxl__wait_device_connection to wait for the device to
+ * finish the connection (might involve executing hotplug scripts).
+ *
+ * Once finished, aodev->callback will be executed.
+ */
+_hidden void libxl__device_disk_add(libxl__egc *egc, uint32_t domid,
+                                    libxl_device_disk *disk,
+                                    libxl__ao_device *aodev);
+
+/* Waits for the passed device to reach state XenbusStateInitWait.
+ * This is not really useful by itself, but is important when executing
+ * hotplug scripts, since we need to be sure the device is in the correct
+ * state before executing them.
+ *
+ * Once finished, aodev->callback will be executed.
+ */
+_hidden void libxl__wait_device_connection(libxl__egc*,
+                                           libxl__ao_device *aodev);
+
+
 /* Arranges that dev will be removed to the guest, and the
  * hotplug scripts will be executed (if necessary). When
  * this is done (or an error happens), the callback in
@@ -1808,6 +1829,8 @@ struct libxl__ao_devices {
  * The libxl__ao_device passed to this function should be
  * prepared using libxl__prepare_ao_device prior to calling
  * this function.
+ *
+ * Once finished, aodev->callback will be executed.
  */
 _hidden void libxl__initiate_device_remove(libxl__egc *egc,
                                            libxl__ao_device *aodev);
@@ -2162,6 +2185,19 @@ _hidden void libxl__destroy_domid(libxl__egc *egc,
 _hidden void libxl__devices_destroy(libxl__egc *egc,
                                     libxl__devices_remove_state *drs);
 
+/* Helper function to add a bunch of disks. This should be used when
+ * the caller is inside an async op. "devices" will NOT be prepared by this
+ * function, so the caller must make sure to call _prepare before calling this
+ * function. The start parameter contains the position inside the aodevs array
+ * that should be used to store the state of this devices.
+ *
+ * The "callback" will be called for each device, and the user is responsible
+ * for calling libxl__ao_device_check_last on the callback.
+ */
+_hidden void libxl__add_disks(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
+                              int start, libxl_domain_config *d_config,
+                              libxl__ao_devices *aodevs);
+
 /*----- device model creation -----*/
 
 /* First layer; wraps libxl__spawn_spawn. */
@@ -2196,6 +2232,7 @@ typedef struct {
     libxl__domain_build_state dm_state;
     libxl__dm_spawn_state pvqemu;
     libxl__destroy_domid_state dis;
+    libxl__ao_devices aodevs;
 } libxl__stub_dm_spawn_state;
 
 _hidden void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state*);
@@ -2225,6 +2262,7 @@ struct libxl__domain_create_state {
     libxl__save_helper_state shs;
     /* necessary if the domain creation failed and we have to destroy it */
     libxl__domain_destroy_state dds;
+    libxl__ao_devices aodevs;
 };
 
 /*----- Domain suspend (save) functions -----*/
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 8c04fe6..f27e811 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -5355,7 +5355,7 @@ int main_blockattach(int argc, char **argv)
         return 0;
     }
 
-    if (libxl_device_disk_add(ctx, fe_domid, &disk)) {
+    if (libxl_device_disk_add(ctx, fe_domid, &disk, 0)) {
         fprintf(stderr, "libxl_device_disk_add failed.\n");
     }
     return 0;
-- 
1.7.7.5 (Apple Git-26)

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v9 09/17] libxl: convert libxl_device_nic_add to an async operation
  2012-07-13  9:44 [PATCH v9 00/15] execute hotplug scripts from libxl Roger Pau Monne
                   ` (7 preceding siblings ...)
  2012-07-13  9:44 ` [PATCH v9 08/17] libxl: convert libxl_device_disk_add to an async op Roger Pau Monne
@ 2012-07-13  9:44 ` Roger Pau Monne
  2012-07-13  9:44 ` [PATCH v9 10/17] libxl: add option to choose who executes hotplug scripts Roger Pau Monne
                   ` (7 subsequent siblings)
  16 siblings, 0 replies; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-13  9:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Roger Pau Monne

This patch converts libxl_device_nic_add to an ao operation that
waits for device backend to reach state XenbusStateInitWait and then
marks the operation as completed. This is not really useful now, but
will be used by latter patches that will launch hotplug scripts after
we reached the desired xenbus state.

Calls to libxl_device_nic_add have also been moved to occur after the
device model has been launched, so when hotplug scripts are called
from this functions the interfaces already exists.

As usual, libxl_device_nic_add callers have been modified, and the
internal function libxl__device_disk_add has been used if the call was
inside an already running ao.

Changes since v5:

 * Updated to use the new ao_devices struct.

 * Renamed ao_device in nic_add to aodev.

Changes since v4:

 * Used the macro defined in previous patch to define the generic
   callback to wait for nics to be connected.

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/libxl/libxl.c          |   29 +++++++++++++++++------
 tools/libxl/libxl.h          |    3 +-
 tools/libxl/libxl_create.c   |   51 +++++++++++++++++++++++++++++++++++------
 tools/libxl/libxl_device.c   |    2 +
 tools/libxl/libxl_dm.c       |   38 ++++++++++++++++++++++++++++--
 tools/libxl/libxl_internal.h |    9 +++++++
 tools/libxl/xl_cmdimpl.c     |    2 +-
 7 files changed, 113 insertions(+), 21 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 5b24719..bfe3c6c 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2402,12 +2402,13 @@ static int libxl__device_from_nic(libxl__gc *gc, uint32_t domid,
     return 0;
 }
 
-int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
+void libxl__device_nic_add(libxl__egc *egc, uint32_t domid,
+                           libxl_device_nic *nic, libxl__ao_device *aodev)
 {
-    GC_INIT(ctx);
+    STATE_AO_GC(aodev->ao);
     flexarray_t *front;
     flexarray_t *back;
-    libxl__device device;
+    libxl__device *device;
     char *dompath, **l;
     unsigned int nb, rc;
 
@@ -2438,7 +2439,8 @@ int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
         }
     }
 
-    rc = libxl__device_from_nic(gc, domid, nic, &device);
+    GCNEW(device);
+    rc = libxl__device_from_nic(gc, domid, nic, device);
     if ( rc != 0 ) goto out_free;
 
     flexarray_append(back, "frontend-id");
@@ -2479,6 +2481,9 @@ int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
     flexarray_append(back, libxl__strdup(gc, nic->bridge));
     flexarray_append(back, "handle");
     flexarray_append(back, libxl__sprintf(gc, "%d", nic->devid));
+    flexarray_append(back, "type");
+    flexarray_append(back, libxl__strdup(gc,
+                                     libxl_nic_type_to_string(nic->nictype)));
 
     flexarray_append(front, "backend-id");
     flexarray_append(front, libxl__sprintf(gc, "%d", nic->backend_domid));
@@ -2489,18 +2494,22 @@ int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic)
     flexarray_append(front, "mac");
     flexarray_append(front, libxl__sprintf(gc,
                                     LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nic->mac)));
-    libxl__device_generic_add(gc, XBT_NULL, &device,
+    libxl__device_generic_add(gc, XBT_NULL, device,
                              libxl__xs_kvs_of_flexarray(gc, back, back->count),
                              libxl__xs_kvs_of_flexarray(gc, front, front->count));
 
-    /* FIXME: wait for plug */
+    aodev->dev = device;
+    aodev->action = DEVICE_CONNECT;
+    libxl__wait_device_connection(egc, aodev);
+
     rc = 0;
 out_free:
     flexarray_free(back);
     flexarray_free(front);
 out:
-    GC_FREE;
-    return rc;
+    aodev->rc = rc;
+    if (rc) aodev->callback(egc, aodev);
+    return;
 }
 
 static void libxl__device_nic_from_xs_be(libxl__gc *gc,
@@ -2992,6 +3001,7 @@ DEFINE_DEVICE_REMOVE(vfb, destroy, 1)
 /* Macro for defining device addition functions in a compact way */
 /* The following functions are defined:
  * libxl_device_disk_add
+ * libxl_device_nic_add
  */
 
 #define DEFINE_DEVICE_ADD(type)                                         \
@@ -3015,6 +3025,9 @@ DEFINE_DEVICE_REMOVE(vfb, destroy, 1)
 /* disk */
 DEFINE_DEVICE_ADD(disk)
 
+/* nic */
+DEFINE_DEVICE_ADD(nic)
+
 #undef DEFINE_DEVICE_ADD
 
 /******************************************************************************/
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index f3161d5..d548090 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -696,7 +696,8 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
 int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk);
 
 /* Network Interfaces */
-int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic);
+int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic,
+                         const libxl_asyncop_how *ao_how);
 int libxl_device_nic_remove(libxl_ctx *ctx, uint32_t domid,
                             libxl_device_nic *nic,
                             const libxl_asyncop_how *ao_how);
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 181eb53..36f7366 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -562,6 +562,9 @@ static void domcreate_bootloader_done(libxl__egc *egc,
 static void domcreate_launch_dm(libxl__egc *egc, libxl__ao_devices *aodevs,
                                 int ret);
 
+static void domcreate_attach_pci(libxl__egc *egc, libxl__ao_devices *aodevs,
+                                 int ret);
+
 static void domcreate_console_available(libxl__egc *egc,
                                         libxl__domain_create_state *dcs);
 
@@ -893,13 +896,11 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__ao_devices *aodevs,
         goto error_out;
     }
     for (i = 0; i < d_config->num_nics; i++) {
-        ret = libxl_device_nic_add(ctx, domid, &d_config->nics[i]);
-        if (ret) {
-            LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
-                       "cannot add nic %d to domain: %d", i, ret);
-            ret = ERROR_FAIL;
-            goto error_out;
-        }
+        /* We have to init the nic here, because we still haven't
+         * called libxl_device_nic_add at this point, but qemu needs
+         * the nic information to be complete.
+         */
+        libxl__device_nic_setdefault(gc, &d_config->nics[i]);
     }
     switch (d_config->c_info.type) {
     case LIBXL_DOMAIN_TYPE_HVM:
@@ -972,7 +973,6 @@ static void domcreate_devmodel_started(libxl__egc *egc,
 {
     libxl__domain_create_state *dcs = CONTAINER_OF(dmss, *dcs, dmss.dm);
     STATE_AO_GC(dmss->spawn.ao);
-    int i;
     libxl_ctx *ctx = CTX;
     int domid = dcs->guest_domid;
 
@@ -992,6 +992,41 @@ static void domcreate_devmodel_started(libxl__egc *egc,
         }
     }
 
+    /* Plug nic interfaces */
+    if (d_config->num_nics > 0) {
+        /* Attach nics */
+        dcs->aodevs.size = d_config->num_nics;
+        dcs->aodevs.callback = domcreate_attach_pci;
+        libxl__prepare_ao_devices(ao, &dcs->aodevs);
+        libxl__add_nics(egc, ao, domid, 0, d_config, &dcs->aodevs);
+        return;
+    }
+
+    domcreate_attach_pci(egc, &dcs->aodevs, 0);
+    return;
+
+error_out:
+    assert(ret);
+    domcreate_complete(egc, dcs, ret);
+}
+
+static void domcreate_attach_pci(libxl__egc *egc, libxl__ao_devices *aodevs,
+                                 int ret)
+{
+    libxl__domain_create_state *dcs = CONTAINER_OF(aodevs, *dcs, aodevs);
+    STATE_AO_GC(dcs->ao);
+    int i;
+    libxl_ctx *ctx = CTX;
+    int domid = dcs->guest_domid;
+
+    /* convenience aliases */
+    libxl_domain_config *const d_config = dcs->guest_config;
+
+    if (ret) {
+        LOG(ERROR, "unable to add nic devices");
+        goto error_out;
+    }
+
     for (i = 0; i < d_config->num_pcidevs; i++)
         libxl__device_pci_add(gc, domid, &d_config->pcidevs[i], 1);
 
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 2a98112..76f1a12 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -450,6 +450,7 @@ void libxl__ao_devices_callback(libxl__egc *egc, libxl__ao_device *aodev)
  *
  * The following functions are defined:
  * libxl__add_disks
+ * libxl__add_nics
  */
 
 #define DEFINE_DEVICES_ADD(type)                                               \
@@ -468,6 +469,7 @@ void libxl__ao_devices_callback(libxl__egc *egc, libxl__ao_device *aodev)
     }
 
 DEFINE_DEVICES_ADD(disk)
+DEFINE_DEVICES_ADD(nic)
 
 #undef DEFINE_DEVICES_ADD
 
diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index 9a5cb0a..8f5618b 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -697,6 +697,10 @@ static void spawn_stubdom_pvqemu_cb(libxl__egc *egc,
 static void spawn_stub_launch_dm(libxl__egc *egc,
                                  libxl__ao_devices *aodevs, int ret);
 
+static void stubdom_pvqemu_cb(libxl__egc *egc,
+                              libxl__ao_devices *aodevs,
+                              int rc);
+
 static void spaw_stubdom_pvqemu_destroy_cb(libxl__egc *egc,
                                            libxl__destroy_domid_state *dis,
                                            int rc);
@@ -864,9 +868,11 @@ static void spawn_stub_launch_dm(libxl__egc *egc,
      }
 
     for (i = 0; i < dm_config->num_nics; i++) {
-        ret = libxl_device_nic_add(ctx, dm_domid, &dm_config->nics[i]);
-        if (ret)
-            goto out;
+         /* We have to init the nic here, because we still haven't
+         * called libxl_device_nic_add at this point, but qemu needs
+         * the nic information to be complete.
+         */
+        libxl__device_nic_setdefault(gc, &dm_config->nics[i]);
     }
     ret = libxl_device_vfb_add(ctx, dm_domid, &dm_config->vfbs[0]);
     if (ret)
@@ -943,9 +949,35 @@ static void spawn_stubdom_pvqemu_cb(libxl__egc *egc,
         CONTAINER_OF(stubdom_dmss, *sdss, pvqemu);
     STATE_AO_GC(sdss->dm.spawn.ao);
     uint32_t dm_domid = sdss->pvqemu.guest_domid;
+    libxl_domain_config *d_config = stubdom_dmss->guest_config;
 
     if (rc) goto out;
 
+    if (d_config->num_nics > 0) {
+        sdss->aodevs.size = d_config->num_nics;
+        sdss->aodevs.callback = stubdom_pvqemu_cb;
+        libxl__prepare_ao_devices(ao, &sdss->aodevs);
+        libxl__add_nics(egc, ao, dm_domid, 0, d_config, &sdss->aodevs);
+        return;
+    }
+
+out:
+    stubdom_pvqemu_cb(egc, &sdss->aodevs, rc);
+}
+
+static void stubdom_pvqemu_cb(libxl__egc *egc,
+                              libxl__ao_devices *aodevs,
+                              int rc)
+{
+    libxl__stub_dm_spawn_state *sdss = CONTAINER_OF(aodevs, *sdss, aodevs);
+    STATE_AO_GC(sdss->dm.spawn.ao);
+    uint32_t dm_domid = sdss->pvqemu.guest_domid;
+
+    if (rc) {
+        LOGE(ERROR, "error connecting nics devices");
+        goto out;
+    }
+
     rc = libxl_domain_unpause(CTX, dm_domid);
     if (rc) goto out;
 
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 981771a..6fee0d9 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1810,6 +1810,11 @@ _hidden void libxl__device_disk_add(libxl__egc *egc, uint32_t domid,
                                     libxl_device_disk *disk,
                                     libxl__ao_device *aodev);
 
+/* AO operation to connect a nic device */
+_hidden void libxl__device_nic_add(libxl__egc *egc, uint32_t domid,
+                                   libxl_device_nic *nic,
+                                   libxl__ao_device *aodev);
+
 /* Waits for the passed device to reach state XenbusStateInitWait.
  * This is not really useful by itself, but is important when executing
  * hotplug scripts, since we need to be sure the device is in the correct
@@ -2198,6 +2203,10 @@ _hidden void libxl__add_disks(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
                               int start, libxl_domain_config *d_config,
                               libxl__ao_devices *aodevs);
 
+_hidden void libxl__add_nics(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
+                             int start, libxl_domain_config *d_config,
+                             libxl__ao_devices *aodevs);
+
 /*----- device model creation -----*/
 
 /* First layer; wraps libxl__spawn_spawn. */
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index f27e811..183dd99 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -5244,7 +5244,7 @@ int main_networkattach(int argc, char **argv)
         return 0;
     }
 
-    if (libxl_device_nic_add(ctx, domid, &nic)) {
+    if (libxl_device_nic_add(ctx, domid, &nic, 0)) {
         fprintf(stderr, "libxl_device_nic_add failed.\n");
         return 1;
     }
-- 
1.7.7.5 (Apple Git-26)

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v9 10/17] libxl: add option to choose who executes hotplug scripts
  2012-07-13  9:44 [PATCH v9 00/15] execute hotplug scripts from libxl Roger Pau Monne
                   ` (8 preceding siblings ...)
  2012-07-13  9:44 ` [PATCH v9 09/17] libxl: convert libxl_device_nic_add to an async operation Roger Pau Monne
@ 2012-07-13  9:44 ` Roger Pau Monne
  2012-07-13  9:44 ` [PATCH v9 11/17] libxl: rename _IOEMU nic type to VIF_IOEMU Roger Pau Monne
                   ` (6 subsequent siblings)
  16 siblings, 0 replies; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-13  9:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Roger Pau Monne

Add and option to xl.conf file to decide if hotplug scripts are
executed from the toolstack (xl) or from udev as it used to be in the
past.

This option is only introduced in this patch, but it has no effect
since the code to call hotplug scripts from libxl is introduced in a
latter patch.

This choice will be saved in "libxl/disable_udev", as specified in the
DISABLE_UDEV_PATH constant.

Changes since v8:

 * Free list of returned VMs

 * Use libxl__xs_{write,rm}_checked.

 * Change initialization of dm_config->c_info.run_hotplug_scripts.

Changes since v2:

 * Change atoi(...) to !!atoi(...) to prevent returning negative
   values from xenstore (which will be handled as errors).

 * Check for errors on the return value of libxl__hotplug_settings.

Changes since v1:

 * Used an auxiliary function to check for the current setting.

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>
---
 docs/man/xl.conf.pod.5       |    8 ++++++++
 tools/examples/xl.conf       |    5 +++++
 tools/libxl/libxl_create.c   |   40 +++++++++++++++++++++++++++++++++++++++-
 tools/libxl/libxl_dm.c       |    3 +++
 tools/libxl/libxl_internal.c |   19 +++++++++++++++++++
 tools/libxl/libxl_internal.h |    3 +++
 tools/libxl/libxl_types.idl  |    1 +
 tools/libxl/xl.c             |    4 ++++
 tools/libxl/xl.h             |    1 +
 tools/libxl/xl_cmdimpl.c     |    1 +
 10 files changed, 84 insertions(+), 1 deletions(-)

diff --git a/docs/man/xl.conf.pod.5 b/docs/man/xl.conf.pod.5
index 149430c..23932be 100644
--- a/docs/man/xl.conf.pod.5
+++ b/docs/man/xl.conf.pod.5
@@ -55,6 +55,14 @@ default.
 
 Default: C<1>
 
+=item B<run_hotplug_scripts=BOOLEAN>
+
+If disabled hotplug scripts will be called from udev, as it used to
+be in the previous releases. With the default option, hotplug scripts
+will be launched by xl directly.
+
+Default: C<1>
+
 =item B<lockfile="PATH">
 
 Sets the path to the lock file used by xl to serialise certain
diff --git a/tools/examples/xl.conf b/tools/examples/xl.conf
index ebf057c..28ab796 100644
--- a/tools/examples/xl.conf
+++ b/tools/examples/xl.conf
@@ -15,3 +15,8 @@
 
 # first block device to be used for temporary VM disk mounts
 #blkdev_start="xvda"
+
+# default option to run hotplug scripts from xl
+# if disabled the old behaviour will be used, and hotplug scripts will be
+# launched by udev.
+#run_hotplug_scripts=1
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 36f7366..d3dc038 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -70,6 +70,8 @@ int libxl__domain_create_info_setdefault(libxl__gc *gc,
         libxl_defbool_setdefault(&c_info->oos, true);
     }
 
+    libxl_defbool_setdefault(&c_info->run_hotplug_scripts, true);
+
     return 0;
 }
 
@@ -382,7 +384,7 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_create_info *info,
                        uint32_t *domid)
 {
     libxl_ctx *ctx = libxl__gc_owner(gc);
-    int flags, ret, rc;
+    int flags, ret, rc, nb_vm;
     char *uuid_string;
     char *dom_path, *vm_path, *libxl_path;
     struct xs_permissions roperm[2];
@@ -390,6 +392,7 @@ int libxl__domain_make(libxl__gc *gc, libxl_domain_create_info *info,
     struct xs_permissions noperm[1];
     xs_transaction_t t = 0;
     xen_domain_handle_t handle;
+    libxl_vminfo *vm_list;
 
 
     assert(!libxl_domid_valid_guest(*domid));
@@ -503,6 +506,41 @@ retry_transaction:
             libxl__sprintf(gc, "%s/hvmloader/generation-id-address", dom_path),
                         rwperm, ARRAY_SIZE(rwperm));
 
+                    vm_list = libxl_list_vm(ctx, &nb_vm);
+    if (!vm_list) {
+        LOG(ERROR, "cannot get number of running guests");
+        rc = ERROR_FAIL;
+        goto out;
+    }
+    libxl_vminfo_list_free(vm_list, nb_vm);
+    int hotplug_setting = libxl__hotplug_settings(gc, t);
+    if (hotplug_setting < 0) {
+        LOG(ERROR, "unable to get current hotplug scripts execution setting");
+        rc = ERROR_FAIL;
+        goto out;
+    }
+    if (libxl_defbool_val(info->run_hotplug_scripts) != hotplug_setting &&
+        (nb_vm - 1)) {
+        LOG(ERROR, "cannot change hotplug execution option once set, "
+                    "please shutdown all guests before changing it");
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    if (libxl_defbool_val(info->run_hotplug_scripts)) {
+        rc = libxl__xs_write_checked(gc, t, DISABLE_UDEV_PATH, "1");
+        if (rc) {
+            LOGE(ERROR, "unable to write %s = 1", DISABLE_UDEV_PATH);
+            goto out;
+        }
+    } else {
+        rc = libxl__xs_rm_checked(gc, t, DISABLE_UDEV_PATH);
+        if (rc) {
+            LOGE(ERROR, "unable to delete %s", DISABLE_UDEV_PATH);
+            goto out;
+        }
+    }
+
     xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/uuid", vm_path), uuid_string, strlen(uuid_string));
     xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/name", vm_path), info->name, strlen(info->name));
 
diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index 8f5618b..dbbd0db 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -762,6 +762,9 @@ void libxl__spawn_stub_dm(libxl__egc *egc, libxl__stub_dm_spawn_state *sdss)
     dm_config->nics = guest_config->nics;
     dm_config->num_nics = guest_config->num_nics;
 
+    dm_config->c_info.run_hotplug_scripts =
+        guest_config->c_info.run_hotplug_scripts;
+
     ret = libxl__domain_create_info_setdefault(gc, &dm_config->c_info);
     if (ret) goto out;
     ret = libxl__domain_build_info_setdefault(gc, &dm_config->b_info);
diff --git a/tools/libxl/libxl_internal.c b/tools/libxl/libxl_internal.c
index fbff7d0..4775bb6 100644
--- a/tools/libxl/libxl_internal.c
+++ b/tools/libxl/libxl_internal.c
@@ -353,6 +353,25 @@ libxl_device_model_version libxl__device_model_version_running(libxl__gc *gc,
     return value;
 }
 
+int libxl__hotplug_settings(libxl__gc *gc, xs_transaction_t t)
+{
+    int rc = 0;
+    char *val;
+
+    val = libxl__xs_read(gc, t, DISABLE_UDEV_PATH);
+    if (!val && errno != ENOENT) {
+        LOGE(ERROR, "cannot read %s from xenstore", DISABLE_UDEV_PATH);
+        rc = ERROR_FAIL;
+        goto out;
+    }
+    if (!val) val = "0";
+
+    rc = !!atoi(val);
+
+out:
+    return rc;
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 6fee0d9..31584b5 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -90,6 +90,7 @@
 #define STUBDOM_CONSOLE_SERIAL 3
 #define STUBDOM_SPECIAL_CONSOLES 3
 #define TAP_DEVICE_SUFFIX "-emu"
+#define DISABLE_UDEV_PATH "libxl/disable_udev"
 
 #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
 
@@ -1463,6 +1464,8 @@ _hidden libxl__json_object *libxl__json_parse(libxl__gc *gc, const char *s);
 _hidden libxl_device_model_version
 libxl__device_model_version_running(libxl__gc *gc, uint32_t domid);
 
+/* Check how executes hotplug script currently */
+int libxl__hotplug_settings(libxl__gc *gc, xs_transaction_t t);
 
 /*
  * Calling context and GC for event-generating functions:
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index c3fbe77..9c83436 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -231,6 +231,7 @@ libxl_domain_create_info = Struct("domain_create_info",[
     ("xsdata",       libxl_key_value_list),
     ("platformdata", libxl_key_value_list),
     ("poolid",       uint32),
+    ("run_hotplug_scripts",libxl_defbool),
     ], dir=DIR_IN)
 
 MemKB = UInt(64, init_val = "LIBXL_MEMKB_DEFAULT")
diff --git a/tools/libxl/xl.c b/tools/libxl/xl.c
index d6f2b3e..f31e836 100644
--- a/tools/libxl/xl.c
+++ b/tools/libxl/xl.c
@@ -39,6 +39,7 @@ int dryrun_only;
 int force_execution;
 int autoballoon = 1;
 char *blkdev_start;
+int run_hotplug_scripts = 1;
 char *lockfile;
 char *default_vifscript = NULL;
 char *default_bridge = NULL;
@@ -70,6 +71,9 @@ static void parse_global_config(const char *configfile,
     if (!xlu_cfg_get_long (config, "autoballoon", &l, 0))
         autoballoon = l;
 
+    if (!xlu_cfg_get_long (config, "run_hotplug_scripts", &l, 0))
+        run_hotplug_scripts = l;
+
     if (!xlu_cfg_get_string (config, "lockfile", &buf, 0))
         lockfile = strdup(buf);
     else {
diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h
index b0ba357..0b2f848 100644
--- a/tools/libxl/xl.h
+++ b/tools/libxl/xl.h
@@ -140,6 +140,7 @@ int xl_child_pid(xlchildnum); /* returns 0 if child struct is not in use */
 
 /* global options */
 extern int autoballoon;
+extern int run_hotplug_scripts;
 extern int dryrun_only;
 extern char *lockfile;
 extern char *default_vifscript;
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 183dd99..5162b6f 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -595,6 +595,7 @@ static void parse_config_data(const char *config_source,
         }
     }
 
+    libxl_defbool_set(&c_info->run_hotplug_scripts, run_hotplug_scripts);
     c_info->type = LIBXL_DOMAIN_TYPE_PV;
     if (!xlu_cfg_get_string (config, "builder", &buf, 0) &&
         !strncmp(buf, "hvm", strlen(buf)))
-- 
1.7.7.5 (Apple Git-26)

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v9 11/17] libxl: rename _IOEMU nic type to VIF_IOEMU
  2012-07-13  9:44 [PATCH v9 00/15] execute hotplug scripts from libxl Roger Pau Monne
                   ` (9 preceding siblings ...)
  2012-07-13  9:44 ` [PATCH v9 10/17] libxl: add option to choose who executes hotplug scripts Roger Pau Monne
@ 2012-07-13  9:44 ` Roger Pau Monne
  2012-07-13  9:44 ` [PATCH v9 12/17] libxl: set correct nic type depending on the guest Roger Pau Monne
                   ` (5 subsequent siblings)
  16 siblings, 0 replies; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-13  9:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Roger Pau Monne

This change will avoid the confusion caused by the fact that IOEMU
means both PV and TAP network interfaces.

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/libxl/libxl.c         |    4 ++--
 tools/libxl/libxl_dm.c      |    8 ++++----
 tools/libxl/libxl_types.idl |    2 +-
 tools/libxl/xl_cmdimpl.c    |    4 ++--
 4 files changed, 9 insertions(+), 9 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index bfe3c6c..98adbb0 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2384,7 +2384,7 @@ int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic)
                                   libxl__xen_script_dir_path()) < 0 )
         return ERROR_FAIL;
     if (!nic->nictype)
-        nic->nictype = LIBXL_NIC_TYPE_IOEMU;
+        nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
     return 0;
 }
 
@@ -2680,7 +2680,7 @@ const char *libxl__device_nic_devname(libxl__gc *gc,
     switch (type) {
     case LIBXL_NIC_TYPE_VIF:
         return GCSPRINTF("vif%u.%d", domid, devid);
-    case LIBXL_NIC_TYPE_IOEMU:
+    case LIBXL_NIC_TYPE_VIF_IOEMU:
         return GCSPRINTF("vif%u.%d" TAP_DEVICE_SUFFIX, domid, devid);
     default:
         abort();
diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index dbbd0db..f21fb4f 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -215,12 +215,12 @@ static char ** libxl__build_device_model_args_old(libxl__gc *gc,
         free(s);
 
         for (i = 0; i < num_nics; i++) {
-            if (nics[i].nictype == LIBXL_NIC_TYPE_IOEMU) {
+            if (nics[i].nictype == LIBXL_NIC_TYPE_VIF_IOEMU) {
                 char *smac = libxl__sprintf(gc,
                                    LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nics[i].mac));
                 const char *ifname = libxl__device_nic_devname(gc,
                                                 domid, nics[i].devid,
-                                                LIBXL_NIC_TYPE_IOEMU);
+                                                LIBXL_NIC_TYPE_VIF_IOEMU);
                 flexarray_vappend(dm_args,
                                   "-net",
                                   GCSPRINTF(
@@ -469,12 +469,12 @@ static char ** libxl__build_device_model_args_new(libxl__gc *gc,
                                                          b_info->max_vcpus));
         }
         for (i = 0; i < num_nics; i++) {
-            if (nics[i].nictype == LIBXL_NIC_TYPE_IOEMU) {
+            if (nics[i].nictype == LIBXL_NIC_TYPE_VIF_IOEMU) {
                 char *smac = libxl__sprintf(gc,
                                 LIBXL_MAC_FMT, LIBXL_MAC_BYTES(nics[i].mac));
                 const char *ifname = libxl__device_nic_devname(gc,
                                                 guest_domid, nics[i].devid,
-                                                LIBXL_NIC_TYPE_IOEMU);
+                                                LIBXL_NIC_TYPE_VIF_IOEMU);
                 flexarray_append(dm_args, "-device");
                 flexarray_append(dm_args,
                    libxl__sprintf(gc, "%s,id=nic%d,netdev=net%d,mac=%s",
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 9c83436..1a6c4a2 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -60,7 +60,7 @@ libxl_disk_backend = Enumeration("disk_backend", [
     ])
 
 libxl_nic_type = Enumeration("nic_type", [
-    (1, "IOEMU"),
+    (1, "VIF_IOEMU"),
     (2, "VIF"),
     ])
 
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 5162b6f..1371458 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -979,7 +979,7 @@ static void parse_config_data(const char *config_source,
                     nic->bridge = strdup(p2 + 1);
                 } else if (!strcmp(p, "type")) {
                     if (!strcmp(p2 + 1, "ioemu"))
-                        nic->nictype = LIBXL_NIC_TYPE_IOEMU;
+                        nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
                     else
                         nic->nictype = LIBXL_NIC_TYPE_VIF;
                 } else if (!strcmp(p, "ip")) {
@@ -5196,7 +5196,7 @@ int main_networkattach(int argc, char **argv)
             if (!strcmp("vif", oparg)) {
                 nic.nictype = LIBXL_NIC_TYPE_VIF;
             } else if (!strcmp("ioemu", oparg)) {
-                nic.nictype = LIBXL_NIC_TYPE_IOEMU;
+                nic.nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
             } else {
                 fprintf(stderr, "Invalid parameter `type'.\n");
                 return 1;
-- 
1.7.7.5 (Apple Git-26)

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v9 12/17] libxl: set correct nic type depending on the guest
  2012-07-13  9:44 [PATCH v9 00/15] execute hotplug scripts from libxl Roger Pau Monne
                   ` (10 preceding siblings ...)
  2012-07-13  9:44 ` [PATCH v9 11/17] libxl: rename _IOEMU nic type to VIF_IOEMU Roger Pau Monne
@ 2012-07-13  9:44 ` Roger Pau Monne
  2012-07-19 16:29   ` Ian Jackson
  2012-07-13  9:44 ` [PATCH v9 13/17] libxl: use libxl__xs_path_cleanup on device_destroy Roger Pau Monne
                   ` (4 subsequent siblings)
  16 siblings, 1 reply; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-13  9:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Roger Pau Monne

Fix the use of nic type, which results in the following for each type
of domain:

 * HVM: let the user choose, if none specified use VIF_IOEMU.
 * HVM with stubdom: use VIF always.
 * PV: use VIF always.

Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Roger Pau Monne <roger.pau@citrix.com>
---
 tools/libxl/libxl.c          |   22 ++++++++++++++++++----
 tools/libxl/libxl_create.c   |    2 +-
 tools/libxl/libxl_dm.c       |    2 +-
 tools/libxl/libxl_internal.h |    3 ++-
 4 files changed, 22 insertions(+), 7 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 98adbb0..08146de 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2353,7 +2353,8 @@ out:
 
 /******************************************************************************/
 
-int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic)
+int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic,
+                                 uint32_t domid)
 {
     if (!nic->mtu)
         nic->mtu = 1492;
@@ -2383,8 +2384,21 @@ int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic)
     if ( !nic->script && asprintf(&nic->script, "%s/vif-bridge",
                                   libxl__xen_script_dir_path()) < 0 )
         return ERROR_FAIL;
-    if (!nic->nictype)
-        nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
+
+    switch (libxl__domain_type(gc, domid)) {
+    case LIBXL_DOMAIN_TYPE_HVM:
+        if (libxl_get_stubdom_id(CTX, domid))
+            nic->nictype = LIBXL_NIC_TYPE_VIF;
+        else if (!nic->nictype)
+            nic->nictype = LIBXL_NIC_TYPE_VIF_IOEMU;
+        break;
+    case LIBXL_DOMAIN_TYPE_PV:
+        nic->nictype = LIBXL_NIC_TYPE_VIF;
+        break;
+    default:
+        abort();
+    }
+
     return 0;
 }
 
@@ -2412,7 +2426,7 @@ void libxl__device_nic_add(libxl__egc *egc, uint32_t domid,
     char *dompath, **l;
     unsigned int nb, rc;
 
-    rc = libxl__device_nic_setdefault(gc, nic);
+    rc = libxl__device_nic_setdefault(gc, nic, domid);
     if (rc) goto out;
 
     front = flexarray_make(16, 1);
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index d3dc038..7db9457 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -938,7 +938,7 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__ao_devices *aodevs,
          * called libxl_device_nic_add at this point, but qemu needs
          * the nic information to be complete.
          */
-        libxl__device_nic_setdefault(gc, &d_config->nics[i]);
+        libxl__device_nic_setdefault(gc, &d_config->nics[i], domid);
     }
     switch (d_config->c_info.type) {
     case LIBXL_DOMAIN_TYPE_HVM:
diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index f21fb4f..cbe518f 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -875,7 +875,7 @@ static void spawn_stub_launch_dm(libxl__egc *egc,
          * called libxl_device_nic_add at this point, but qemu needs
          * the nic information to be complete.
          */
-        libxl__device_nic_setdefault(gc, &dm_config->nics[i]);
+        libxl__device_nic_setdefault(gc, &dm_config->nics[i], dm_domid);
     }
     ret = libxl_device_vfb_add(ctx, dm_domid, &dm_config->vfbs[0]);
     if (ret)
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 31584b5..b8318cb 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -890,7 +890,8 @@ _hidden int libxl__domain_build_info_setdefault(libxl__gc *gc,
                                         libxl_domain_build_info *b_info);
 _hidden int libxl__device_disk_setdefault(libxl__gc *gc,
                                           libxl_device_disk *disk);
-_hidden int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic);
+_hidden int libxl__device_nic_setdefault(libxl__gc *gc, libxl_device_nic *nic,
+                                         uint32_t domid);
 _hidden int libxl__device_vfb_setdefault(libxl__gc *gc, libxl_device_vfb *vfb);
 _hidden int libxl__device_vkb_setdefault(libxl__gc *gc, libxl_device_vkb *vkb);
 _hidden int libxl__device_pci_setdefault(libxl__gc *gc, libxl_device_pci *pci);
-- 
1.7.7.5 (Apple Git-26)

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v9 13/17] libxl: use libxl__xs_path_cleanup on device_destroy
  2012-07-13  9:44 [PATCH v9 00/15] execute hotplug scripts from libxl Roger Pau Monne
                   ` (11 preceding siblings ...)
  2012-07-13  9:44 ` [PATCH v9 12/17] libxl: set correct nic type depending on the guest Roger Pau Monne
@ 2012-07-13  9:44 ` Roger Pau Monne
  2012-07-13  9:44 ` [PATCH v9 14/17] libxl: call hotplug scripts for disk devices from libxl Roger Pau Monne
                   ` (3 subsequent siblings)
  16 siblings, 0 replies; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-13  9:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Roger Pau Monne

Since the hotplug script that was in charge of cleaning the backend is
no longer launched, we need to clean the backend by ourselves, so use
libxl__xs_path_cleanup instead of xs_rm.

Changes sinve v2:

 * Changed the goto construction to a do-while loop.

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/libxl/libxl_device.c |   18 ++++++++++++++----
 1 files changed, 14 insertions(+), 4 deletions(-)

diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 76f1a12..b8efef0 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -477,16 +477,26 @@ DEFINE_DEVICES_ADD(nic)
 
 int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
 {
-    libxl_ctx *ctx = libxl__gc_owner(gc);
     char *be_path = libxl__device_backend_path(gc, dev);
     char *fe_path = libxl__device_frontend_path(gc, dev);
+    xs_transaction_t t = 0;
+    int rc = 0;
 
-    xs_rm(ctx->xsh, XBT_NULL, be_path);
-    xs_rm(ctx->xsh, XBT_NULL, fe_path);
+    do {
+        t = xs_transaction_start(CTX->xsh);
+        libxl__xs_path_cleanup(gc, t, fe_path);
+        libxl__xs_path_cleanup(gc, t, be_path);
+        rc = !xs_transaction_end(CTX->xsh, t, 0);
+    } while (rc && errno == EAGAIN);
+    if (rc) {
+        LOGE(ERROR, "unable to finish transaction");
+        goto out;
+    }
 
     libxl__device_destroy_tapdisk(gc, be_path);
 
-    return 0;
+out:
+    return rc;
 }
 
 /* Callback for device destruction */
-- 
1.7.7.5 (Apple Git-26)

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v9 14/17] libxl: call hotplug scripts for disk devices from libxl
  2012-07-13  9:44 [PATCH v9 00/15] execute hotplug scripts from libxl Roger Pau Monne
                   ` (12 preceding siblings ...)
  2012-07-13  9:44 ` [PATCH v9 13/17] libxl: use libxl__xs_path_cleanup on device_destroy Roger Pau Monne
@ 2012-07-13  9:44 ` Roger Pau Monne
  2012-07-13  9:44 ` [PATCH v9 15/17] libxl: call hotplug scripts for nic " Roger Pau Monne
                   ` (2 subsequent siblings)
  16 siblings, 0 replies; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-13  9:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Roger Pau Monne

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                |  134 +++++++++++++++++++++++++++-
 tools/libxl/libxl_internal.h              |   19 ++++
 tools/libxl/libxl_linux.c                 |   97 +++++++++++++++++++++
 tools/libxl/libxl_netbsd.c                |    8 ++
 7 files changed, 272 insertions(+), 8 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 08146de..d0bbdce 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1811,6 +1811,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:
@@ -1826,6 +1831,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 b8efef0..fb9ca2e 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -410,6 +410,10 @@ void libxl__prepare_ao_device(libxl__ao *ao, libxl__ao_device *aodev)
     aodev->ao = ao;
     aodev->rc = 0;
     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);
+    libxl__ev_time_init(&aodev->ev);
 }
 
 void libxl__prepare_ao_devices(libxl__ao *ao, libxl__ao_devices *aodevs)
@@ -607,7 +611,16 @@ 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_xsentries_remove(libxl__egc *egc, 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)
 {
@@ -637,7 +650,7 @@ void libxl__wait_device_connection(libxl__egc *egc, libxl__ao_device *aodev)
 
 out:
     aodev->rc = rc;
-    device_xsentries_remove(egc, aodev);
+    device_hotplug_child_death_cb(egc, &aodev->child, 0, 0);
     return;
 }
 
@@ -692,7 +705,7 @@ retry_transaction:
 
 out:
     aodev->rc = rc;
-    device_xsentries_remove(egc, aodev);
+    device_hotplug_done(egc, aodev);
     return;
 }
 
@@ -725,9 +738,12 @@ static void device_backend_callback(libxl__egc *egc, libxl__ev_devstate *ds,
         goto out;
     }
 
+    device_hotplug(egc, aodev);
+    return;
+
 out:
     aodev->rc = rc;
-    device_xsentries_remove(egc, aodev);
+    device_hotplug_done(egc, aodev);
     return;
 }
 
@@ -737,7 +753,110 @@ static void device_backend_cleanup(libxl__gc *gc, libxl__ao_device *aodev)
     libxl__ev_devstate_cancel(gc, &aodev->backend_ds);
 }
 
-static void device_xsentries_remove(libxl__egc *egc, libxl__ao_device *aodev)
+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->ev, 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, ev);
+    STATE_AO_GC(aodev->ao);
+
+    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);
     char *be_path = libxl__device_backend_path(gc, aodev->dev);
@@ -745,6 +864,11 @@ static void device_xsentries_remove(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->ev);
+    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 b8318cb..b932dcb 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_XENCONSOLE_LIMIT 1048576
 #define LIBXL_XENCONSOLE_PROTOCOL "vt100"
@@ -1788,6 +1789,10 @@ struct libxl__ao_device {
     /* 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_time ev;
+    libxl__ev_child child;
 };
 
 /* Helper struct to simply the plug/unplug of multiple devices at the same
@@ -1844,6 +1849,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)

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v9 15/17] libxl: call hotplug scripts for nic devices from libxl
  2012-07-13  9:44 [PATCH v9 00/15] execute hotplug scripts from libxl Roger Pau Monne
                   ` (13 preceding siblings ...)
  2012-07-13  9:44 ` [PATCH v9 14/17] libxl: call hotplug scripts for disk devices from libxl Roger Pau Monne
@ 2012-07-13  9:44 ` Roger Pau Monne
  2012-07-13  9:44 ` [PATCH v9 16/17] libxl: convert libxl_device_vkb_add to an async operation Roger Pau Monne
  2012-07-13  9:44 ` [PATCH v9 17/17] libxl: convert libxl_device_vfb_add " Roger Pau Monne
  16 siblings, 0 replies; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-13  9:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Roger Pau Monne

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

Added another parameter to libxl__get_hotplug_script_info, that is
used to know the number of times hotplug scripts have been called for
that device. This is currently used by IOEMU nics on Linux.

Changes since v8:

 * Correctly detect errors from hotplug execution and cancel domain
   creation if an error is found.

Changes since v6:

 * Added an rc = 0 before exitting libxl__nic_type if successful.

Changes since v4:

 * Add num_exec to NetBSD dummy function.

 * Better comment in the prototype of libxl__get_hotplug_script_info.

 * Remove nasty use of goto.

 * Keep calling device_hotplug until libxl__get_hotplug_script_info
   returns <= 0. This is used by TAP nics which also have a VIF
   interface (PV_IOEMU).

Changes since v2:

 * Change libxl__nic_type to return the value in a parameter passed by
   the caller.

 * Rename vif_execute to num_exec, to represent the number of times
   hotplug scripts have been called for that device.

Changes since v1:

 * Move event code to libxl_device.c (as in previous patch).

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/libxl/libxl_device.c            |   60 +++++++++++++++++++--
 tools/libxl/libxl_internal.h          |   14 +++++-
 tools/libxl/libxl_linux.c             |   95 +++++++++++++++++++++++++++++++-
 tools/libxl/libxl_netbsd.c            |    3 +-
 5 files changed, 166 insertions(+), 12 deletions(-)

diff --git a/tools/hotplug/Linux/xen-backend.rules b/tools/hotplug/Linux/xen-backend.rules
index d55ff11..c591a3f 100644
--- a/tools/hotplug/Linux/xen-backend.rules
+++ b/tools/hotplug/Linux/xen-backend.rules
@@ -2,8 +2,8 @@ SUBSYSTEM=="xen-backend", KERNEL=="tap*", ENV{UDEV_CALL}="1", RUN+="/etc/xen/scr
 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=="vif-*", ENV{UDEV_CALL}="1", ACTION=="online", RUN+="/etc/xen/scripts/vif-setup online type_if=vif"
+SUBSYSTEM=="xen-backend", KERNEL=="vif-*", ENV{UDEV_CALL}="1", 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", ENV{UDEV_CALL}="1", RUN+="/etc/xen/scripts/xen-hotplug-cleanup"
 KERNEL=="evtchn", NAME="xen/%k"
@@ -13,4 +13,4 @@ KERNEL=="blktap-control", NAME="xen/blktap-2/control", MODE="0600"
 KERNEL=="gntdev", NAME="xen/%k", MODE="0600"
 KERNEL=="pci_iomul", NAME="xen/%k", MODE="0600"
 KERNEL=="tapdev[a-z]*", NAME="xen/blktap-2/tapdev%m", MODE="0600"
-SUBSYSTEM=="net", KERNEL=="vif*-emu", ACTION=="add", RUN+="/etc/xen/scripts/vif-setup $env{ACTION} type_if=tap"
+SUBSYSTEM=="net", KERNEL=="vif*-emu", ACTION=="add", ENV{UDEV_CALL}="1", RUN+="/etc/xen/scripts/vif-setup $env{ACTION} type_if=tap"
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index fb9ca2e..2f41b46 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -100,6 +100,31 @@ out:
     return numdevs;
 }
 
+int libxl__nic_type(libxl__gc *gc, libxl__device *dev, libxl_nic_type *nictype)
+{
+    char *snictype, *be_path;
+    int rc = 0;
+
+    be_path = libxl__device_backend_path(gc, dev);
+    snictype = libxl__xs_read(gc, XBT_NULL,
+                              GCSPRINTF("%s/%s", be_path, "type"));
+    if (!snictype) {
+        LOGE(ERROR, "unable to read nictype from %s", be_path);
+        rc = ERROR_FAIL;
+        goto out;
+    }
+    rc = libxl_nic_type_from_string(snictype, nictype);
+    if (rc) {
+        LOGE(ERROR, "unable to parse nictype from %s", be_path);
+        goto out;
+    }
+
+    rc = 0;
+
+out:
+    return rc;
+}
+
 int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t,
         libxl__device *device, char **bents, char **fents)
 {
@@ -622,6 +647,8 @@ static void device_hotplug_child_death_cb(libxl__egc *egc,
 
 static void device_hotplug_done(libxl__egc *egc, libxl__ao_device *aodev);
 
+static void device_hotplug_clean(libxl__gc *gc, libxl__ao_device *aodev);
+
 void libxl__wait_device_connection(libxl__egc *egc, libxl__ao_device *aodev)
 {
     STATE_AO_GC(aodev->ao);
@@ -765,7 +792,8 @@ static void device_hotplug(libxl__egc *egc, libxl__ao_device *aodev)
     /* 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);
+                                             aodev->action,
+                                             aodev->num_exec);
     switch (hotplug) {
     case 0:
         /* no hotplug script to execute */
@@ -842,6 +870,8 @@ static void device_hotplug_child_death_cb(libxl__egc *egc,
     char *be_path = libxl__device_backend_path(gc, aodev->dev);
     char *hotplug_error;
 
+    device_hotplug_clean(gc, aodev);
+
     if (status) {
         libxl_report_child_exitstatus(CTX, LIBXL__LOG_ERROR,
                                       aodev->what, pid, status);
@@ -851,8 +881,25 @@ static void device_hotplug_child_death_cb(libxl__egc *egc,
             LOG(ERROR, "reason of failure reported by hotplug script: %s",
                        hotplug_error);
         aodev->rc = ERROR_FAIL;
+        if (aodev->action == DEVICE_CONNECT)
+            /* 
+             * Only fail on device connection, on disconnection
+             * ignore error, and continue with the remove process
+             */
+             goto error;
     }
 
+    /* Increase num_exec and call hotplug scripts again if necessary
+     * If no more executions are needed, device_hotplug will call
+     * device_hotplug_done breaking the loop.
+     */
+    aodev->num_exec++;
+    device_hotplug(egc, aodev);
+
+    return;
+
+error:
+    assert(aodev->rc);
     device_hotplug_done(egc, aodev);
 }
 
@@ -864,9 +911,7 @@ 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->ev);
-    assert(!libxl__ev_child_inuse(&aodev->child));
+    device_hotplug_clean(gc, aodev);
 
     /* Clean xenstore if it's a disconnection */
     if (aodev->action == DEVICE_DISCONNECT) {
@@ -888,6 +933,13 @@ out:
     return;
 }
 
+static void device_hotplug_clean(libxl__gc *gc, libxl__ao_device *aodev)
+{
+    /* Clean events and check reentrancy */
+    libxl__ev_time_deregister(gc, &aodev->ev);
+    assert(!libxl__ev_child_inuse(&aodev->child));
+}
+
 static void devices_remove_callback(libxl__egc *egc, libxl__ao_devices *aodevs,
                                     int rc)
 {
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index b932dcb..60b5bf3 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -872,6 +872,8 @@ _hidden int libxl__parse_backend_path(libxl__gc *gc, const char *path,
                                       libxl__device *dev);
 _hidden int libxl__device_destroy(libxl__gc *gc, libxl__device *dev);
 _hidden int libxl__wait_for_backend(libxl__gc *gc, char *be_path, char *state);
+_hidden int libxl__nic_type(libxl__gc *gc, libxl__device *dev,
+                            libxl_nic_type *nictype);
 
 /*
  * For each aggregate type which can be used as an input we provide:
@@ -1791,6 +1793,7 @@ struct libxl__ao_device {
     libxl__ao_devices *aodevs;
     /* device hotplug execution */
     const char *what;
+    int num_exec;
     libxl__ev_time ev;
     libxl__ev_child child;
 };
@@ -1858,10 +1861,19 @@ _hidden void libxl__initiate_device_remove(libxl__egc *egc,
  * < 0: Error
  * 0: No need to execute hotplug script
  * 1: Execute hotplug script
+ *
+ * The last parameter, "num_exec" refeers to the number of times hotplug
+ * scripts have been called for this device.
+ *
+ * The main body of libxl will, for each device, keep calling
+ * libxl__get_hotplug_script_info, with incrementing values of
+ * num_exec, and executing the resulting script accordingly,
+ * until libxl__get_hotplug_script_info returns<=0.
  */
 _hidden int libxl__get_hotplug_script_info(libxl__gc *gc, libxl__device *dev,
                                            char ***args, char ***env,
-                                           libxl__device_action action);
+                                           libxl__device_action action,
+                                           int num_exec);
 
 /*----- local disk attach: attach a disk locally to run the bootloader -----*/
 
diff --git a/tools/libxl/libxl_linux.c b/tools/libxl/libxl_linux.c
index 97b3fd4..1c2b99a 100644
--- a/tools/libxl/libxl_linux.c
+++ b/tools/libxl/libxl_linux.c
@@ -87,6 +87,7 @@ static char **get_hotplug_env(libxl__gc *gc, libxl__device *dev)
     const char *type = libxl__device_kind_to_string(dev->backend_kind);
     char **env;
     int nr = 0;
+    libxl_nic_type nictype;
 
     script = libxl__xs_read(gc, XBT_NULL,
                             GCSPRINTF("%s/%s", be_path, "script"));
@@ -95,7 +96,7 @@ static char **get_hotplug_env(libxl__gc *gc, libxl__device *dev)
         return NULL;
     }
 
-    const int arraysize = 9;
+    const int arraysize = 13;
     GCNEW_ARRAY(env, arraysize);
     env[nr++] = "script";
     env[nr++] = script;
@@ -105,14 +106,90 @@ static char **get_hotplug_env(libxl__gc *gc, libxl__device *dev)
     env[nr++] = GCSPRINTF("backend/%s/%u/%d", type, dev->domid, dev->devid);
     env[nr++] = "XENBUS_BASE_PATH";
     env[nr++] = "backend";
+    if (dev->backend_kind == LIBXL__DEVICE_KIND_VIF) {
+        if (libxl__nic_type(gc, dev, &nictype)) {
+            LOG(ERROR, "unable to get nictype");
+            return NULL;
+        }
+        switch (nictype) {
+        case LIBXL_NIC_TYPE_VIF_IOEMU:
+            env[nr++] = "INTERFACE";
+            env[nr++] = libxl__strdup(gc, libxl__device_nic_devname(gc,
+                                                      dev->domid, dev->devid,
+                                                      LIBXL_NIC_TYPE_VIF_IOEMU));
+        case LIBXL_NIC_TYPE_VIF:
+            env[nr++] = "vif";
+            env[nr++] = libxl__strdup(gc, libxl__device_nic_devname(gc,
+                                                      dev->domid, dev->devid,
+                                                      LIBXL_NIC_TYPE_VIF));
+            break;
+        default:
+            return NULL;
+        }
+    }
+
     env[nr++] = NULL;
-    assert(nr == arraysize);
+    assert(nr <= arraysize);
 
     return env;
 }
 
 /* Hotplug scripts caller functions */
 
+static int libxl__hotplug_nic(libxl__gc *gc, libxl__device *dev,
+                               char ***args, char ***env,
+                               libxl__device_action action, int num_exec)
+{
+    char *be_path = libxl__device_backend_path(gc, dev);
+    char *script;
+    int nr = 0, rc = 0;
+    libxl_nic_type nictype;
+
+    script = libxl__xs_read(gc, XBT_NULL, GCSPRINTF("%s/%s", be_path,
+                                                             "script"));
+    if (!script) {
+        LOGE(ERROR, "unable to read script from %s", be_path);
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    rc = libxl__nic_type(gc, dev, &nictype);
+    if (rc) {
+        LOG(ERROR, "error when fetching nic type");
+        rc = ERROR_FAIL;
+        goto out;
+    }
+    if (nictype == LIBXL_NIC_TYPE_VIF && num_exec != 0) {
+        rc = 0;
+        goto out;
+    }
+
+    *env = get_hotplug_env(gc, dev);
+    if (!env) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    const int arraysize = 4;
+    GCNEW_ARRAY(*args, arraysize);
+    (*args)[nr++] = script;
+
+    if (nictype == LIBXL_NIC_TYPE_VIF_IOEMU && num_exec) {
+        (*args)[nr++] = action == DEVICE_CONNECT ? "add" : "remove";
+        (*args)[nr++] = libxl__strdup(gc, "type_if=tap");
+        (*args)[nr++] = NULL;
+    } else {
+        (*args)[nr++] = action == DEVICE_CONNECT ? "online" : "offline";
+        (*args)[nr++] = libxl__strdup(gc, "type_if=vif");
+        (*args)[nr++] = NULL;
+    }
+    assert(nr == arraysize);
+    rc = 1;
+
+out:
+    return rc;
+}
+
 static int libxl__hotplug_disk(libxl__gc *gc, libxl__device *dev,
                                char ***args, char ***env,
                                libxl__device_action action)
@@ -150,7 +227,8 @@ error:
 
 int libxl__get_hotplug_script_info(libxl__gc *gc, libxl__device *dev,
                                    char ***args, char ***env,
-                                   libxl__device_action action)
+                                   libxl__device_action action,
+                                   int num_exec)
 {
     char *disable_udev = libxl__xs_read(gc, XBT_NULL, DISABLE_UDEV_PATH);
     int rc;
@@ -163,8 +241,19 @@ int libxl__get_hotplug_script_info(libxl__gc *gc, libxl__device *dev,
 
     switch (dev->backend_kind) {
     case LIBXL__DEVICE_KIND_VBD:
+        if (num_exec != 0) {
+            rc = 0;
+            goto out;
+        }
         rc = libxl__hotplug_disk(gc, dev, args, env, action);
         break;
+    case LIBXL__DEVICE_KIND_VIF:
+        if (num_exec > 1) {
+            rc = 0;
+            goto out;
+        }
+        rc = libxl__hotplug_nic(gc, dev, args, env, action, num_exec);
+        break;
     default:
         /* No need to execute any hotplug scripts */
         rc = 0;
diff --git a/tools/libxl/libxl_netbsd.c b/tools/libxl/libxl_netbsd.c
index a2f8d3f..28cdf21 100644
--- a/tools/libxl/libxl_netbsd.c
+++ b/tools/libxl/libxl_netbsd.c
@@ -34,7 +34,8 @@ char *libxl__devid_to_localdev(libxl__gc *gc, int devid)
 /* Hotplug scripts caller functions */
 int libxl__get_hotplug_script_info(libxl__gc *gc, libxl__device *dev,
                                    char ***args, char ***env,
-                                   libxl__device_action action)
+                                   libxl__device_action action,
+                                   int num_exec)
 {
     return 0;
 }
-- 
1.7.7.5 (Apple Git-26)

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v9 16/17] libxl: convert libxl_device_vkb_add to an async operation
  2012-07-13  9:44 [PATCH v9 00/15] execute hotplug scripts from libxl Roger Pau Monne
                   ` (14 preceding siblings ...)
  2012-07-13  9:44 ` [PATCH v9 15/17] libxl: call hotplug scripts for nic " Roger Pau Monne
@ 2012-07-13  9:44 ` Roger Pau Monne
  2012-07-19 16:35   ` Ian Jackson
  2012-07-13  9:44 ` [PATCH v9 17/17] libxl: convert libxl_device_vfb_add " Roger Pau Monne
  16 siblings, 1 reply; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-13  9:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Roger Pau Monne

Split libxl_device_vkb_add into libxl__device_vkb_add (to be used
inside already running ao's), and make libxl_device_vkb_add a stub to
call libxl__device_vkb_add.

Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Roger Pau Monne <roger.pau@citrix.com>
---
 tools/libxl/libxl.c          |   14 ++++++++++----
 tools/libxl/libxl.h          |    3 ++-
 tools/libxl/libxl_create.c   |   19 +++++++++++--------
 tools/libxl/libxl_device.c   |    2 ++
 tools/libxl/libxl_dm.c       |    9 ++++-----
 tools/libxl/libxl_internal.h |    9 +++++++++
 6 files changed, 38 insertions(+), 18 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index d0bbdce..b07e4e5 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2811,9 +2811,10 @@ static int libxl__device_from_vkb(libxl__gc *gc, uint32_t domid,
     return 0;
 }
 
-int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb)
+void libxl__device_vkb_add(libxl__egc *egc, uint32_t domid,
+                           libxl_device_vkb *vkb, libxl__ao_device *aodev)
 {
-    GC_INIT(ctx);
+    STATE_AO_GC(aodev->ao);
     flexarray_t *front;
     flexarray_t *back;
     libxl__device device;
@@ -2858,8 +2859,9 @@ out_free:
     flexarray_free(back);
     flexarray_free(front);
 out:
-    GC_FREE;
-    return rc;
+    aodev->rc = rc;
+    aodev->callback(egc, aodev);
+    return;
 }
 
 /******************************************************************************/
@@ -3026,6 +3028,7 @@ DEFINE_DEVICE_REMOVE(vfb, destroy, 1)
 /* The following functions are defined:
  * libxl_device_disk_add
  * libxl_device_nic_add
+ * libxl_device_vkb_add
  */
 
 #define DEFINE_DEVICE_ADD(type)                                         \
@@ -3052,6 +3055,9 @@ DEFINE_DEVICE_ADD(disk)
 /* nic */
 DEFINE_DEVICE_ADD(nic)
 
+/* vkb */
+DEFINE_DEVICE_ADD(vkb)
+
 #undef DEFINE_DEVICE_ADD
 
 /******************************************************************************/
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index d548090..84d4efd 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -710,7 +710,8 @@ int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid,
                               libxl_device_nic *nic, libxl_nicinfo *nicinfo);
 
 /* Keyboard */
-int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb);
+int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb,
+                         const libxl_asyncop_how *ao_how);
 int libxl_device_vkb_remove(libxl_ctx *ctx, uint32_t domid,
                             libxl_device_vkb *vkb,
                             const libxl_asyncop_how *ao_how);
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index 7db9457..fdbcafc 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -904,10 +904,19 @@ static void domcreate_rebuild_done(libxl__egc *egc,
 
     store_libxl_entry(gc, domid, &d_config->b_info);
 
-    dcs->aodevs.size = d_config->num_disks;
+    if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM) {
+        assert(!d_config->vkbs && !d_config->num_vkbs);
+        d_config->vkbs = libxl__zalloc(NOGC, sizeof(*d_config->vkbs));
+        libxl_device_vkb_init(&d_config->vkbs[0]);
+        d_config->num_vkbs = 1;
+    }
+
+    dcs->aodevs.size = d_config->num_disks + d_config->num_vkbs;
     dcs->aodevs.callback = domcreate_launch_dm;
     libxl__prepare_ao_devices(ao, &dcs->aodevs);
     libxl__add_disks(egc, ao, domid, 0, d_config, &dcs->aodevs);
+    libxl__add_vkbs(egc, ao, domid, d_config->num_disks, d_config,
+                    &dcs->aodevs);
 
     return;
 
@@ -930,7 +939,7 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__ao_devices *aodevs,
     libxl_ctx *const ctx = CTX;
 
     if (ret) {
-        LOG(ERROR, "unable to add disk devices");
+        LOG(ERROR, "unable to add misc devices");
         goto error_out;
     }
     for (i = 0; i < d_config->num_nics; i++) {
@@ -944,7 +953,6 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__ao_devices *aodevs,
     case LIBXL_DOMAIN_TYPE_HVM:
     {
         libxl__device_console console;
-        libxl_device_vkb vkb;
 
         ret = init_console_info(&console, 0);
         if ( ret )
@@ -952,10 +960,6 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__ao_devices *aodevs,
         libxl__device_console_add(gc, domid, &console, state);
         libxl__device_console_dispose(&console);
 
-        libxl_device_vkb_init(&vkb);
-        libxl_device_vkb_add(ctx, domid, &vkb);
-        libxl_device_vkb_dispose(&vkb);
-
         dcs->dmss.dm.guest_domid = domid;
         if (libxl_defbool_val(d_config->b_info.device_model_stubdomain))
             libxl__spawn_stub_dm(egc, &dcs->dmss);
@@ -970,7 +974,6 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__ao_devices *aodevs,
 
         for (i = 0; i < d_config->num_vfbs; i++) {
             libxl_device_vfb_add(ctx, domid, &d_config->vfbs[i]);
-            libxl_device_vkb_add(ctx, domid, &d_config->vkbs[i]);
         }
 
         ret = init_console_info(&console, 0);
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 2f41b46..f6e5585 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -480,6 +480,7 @@ void libxl__ao_devices_callback(libxl__egc *egc, libxl__ao_device *aodev)
  * The following functions are defined:
  * libxl__add_disks
  * libxl__add_nics
+ * libxl__add_vkbs
  */
 
 #define DEFINE_DEVICES_ADD(type)                                               \
@@ -499,6 +500,7 @@ void libxl__ao_devices_callback(libxl__egc *egc, libxl__ao_device *aodev)
 
 DEFINE_DEVICES_ADD(disk)
 DEFINE_DEVICES_ADD(nic)
+DEFINE_DEVICES_ADD(vkb)
 
 #undef DEFINE_DEVICES_ADD
 
diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index cbe518f..a6ee080 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -833,10 +833,12 @@ retry_transaction:
         if (errno == EAGAIN)
             goto retry_transaction;
 
-    sdss->aodevs.size = dm_config->num_disks;
+    sdss->aodevs.size = dm_config->num_disks + dm_config->num_vkbs;
     sdss->aodevs.callback = spawn_stub_launch_dm;
     libxl__prepare_ao_devices(ao, &sdss->aodevs);
     libxl__add_disks(egc, ao, dm_domid, 0, dm_config, &sdss->aodevs);
+    libxl__add_vkbs(egc, ao, dm_domid, dm_config->num_disks, dm_config,
+                    &sdss->aodevs);
 
     free(args);
     return;
@@ -866,7 +868,7 @@ static void spawn_stub_launch_dm(libxl__egc *egc,
     uint32_t dm_domid = sdss->pvqemu.guest_domid;
 
     if (ret) {
-        LOG(ERROR, "error connecting disk devices");
+        LOG(ERROR, "error connecting misc devices");
         goto out;
      }
 
@@ -880,9 +882,6 @@ static void spawn_stub_launch_dm(libxl__egc *egc,
     ret = libxl_device_vfb_add(ctx, dm_domid, &dm_config->vfbs[0]);
     if (ret)
         goto out;
-    ret = libxl_device_vkb_add(ctx, dm_domid, &dm_config->vkbs[0]);
-    if (ret)
-        goto out;
 
     if (guest_config->b_info.u.hvm.serial)
         num_console++;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 60b5bf3..29d2fcd 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1827,6 +1827,11 @@ _hidden void libxl__device_nic_add(libxl__egc *egc, uint32_t domid,
                                    libxl_device_nic *nic,
                                    libxl__ao_device *aodev);
 
+/* AO operation to connect a vkb device */
+_hidden void libxl__device_vkb_add(libxl__egc *egc, uint32_t domid,
+                                   libxl_device_vkb *vkb,
+                                   libxl__ao_device *aodev);
+
 /* Waits for the passed device to reach state XenbusStateInitWait.
  * This is not really useful by itself, but is important when executing
  * hotplug scripts, since we need to be sure the device is in the correct
@@ -2242,6 +2247,10 @@ _hidden void libxl__add_nics(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
                              int start, libxl_domain_config *d_config,
                              libxl__ao_devices *aodevs);
 
+_hidden void libxl__add_vkbs(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
+                             int start, libxl_domain_config *d_config,
+                             libxl__ao_devices *aodevs);
+
 /*----- device model creation -----*/
 
 /* First layer; wraps libxl__spawn_spawn. */
-- 
1.7.7.5 (Apple Git-26)

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* [PATCH v9 17/17] libxl: convert libxl_device_vfb_add to an async operation
  2012-07-13  9:44 [PATCH v9 00/15] execute hotplug scripts from libxl Roger Pau Monne
                   ` (15 preceding siblings ...)
  2012-07-13  9:44 ` [PATCH v9 16/17] libxl: convert libxl_device_vkb_add to an async operation Roger Pau Monne
@ 2012-07-13  9:44 ` Roger Pau Monne
  2012-07-26 10:42   ` Ian Jackson
  16 siblings, 1 reply; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-13  9:44 UTC (permalink / raw)
  To: xen-devel; +Cc: Ian Jackson, Roger Pau Monne

Split libxl_device_vfb_add into libxl__device_vfb_add (to be used
inside already running ao's), and make libxl_device_vfb_add a stub
to call libxl__device_vfb_add.

Cc: Ian Jackson <ian.jackson@eu.citrix.com>
Signed-off-by: Roger Pau Monne <roger.pau@citrix.com>
---
 tools/libxl/libxl.c          |   14 ++++++++++----
 tools/libxl/libxl.h          |    3 ++-
 tools/libxl/libxl_create.c   |   10 ++++------
 tools/libxl/libxl_device.c   |    2 ++
 tools/libxl/libxl_dm.c       |    9 +++++----
 tools/libxl/libxl_internal.h |    9 +++++++++
 6 files changed, 32 insertions(+), 15 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index b07e4e5..fc4989c 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2897,9 +2897,10 @@ static int libxl__device_from_vfb(libxl__gc *gc, uint32_t domid,
     return 0;
 }
 
-int libxl_device_vfb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb)
+void libxl__device_vfb_add(libxl__egc *egc, uint32_t domid,
+                           libxl_device_vfb *vfb, libxl__ao_device *aodev)
 {
-    GC_INIT(ctx);
+    STATE_AO_GC(aodev->ao);
     flexarray_t *front;
     flexarray_t *back;
     libxl__device device;
@@ -2957,8 +2958,9 @@ out_free:
     flexarray_free(front);
     flexarray_free(back);
 out:
-    GC_FREE;
-    return rc;
+    aodev->rc = rc;
+    aodev->callback(egc, aodev);
+    return;
 }
 
 /******************************************************************************/
@@ -3029,6 +3031,7 @@ DEFINE_DEVICE_REMOVE(vfb, destroy, 1)
  * libxl_device_disk_add
  * libxl_device_nic_add
  * libxl_device_vkb_add
+ * libxl_device_vfb_add
  */
 
 #define DEFINE_DEVICE_ADD(type)                                         \
@@ -3058,6 +3061,9 @@ DEFINE_DEVICE_ADD(nic)
 /* vkb */
 DEFINE_DEVICE_ADD(vkb)
 
+/* vfb */
+DEFINE_DEVICE_ADD(vfb)
+
 #undef DEFINE_DEVICE_ADD
 
 /******************************************************************************/
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 84d4efd..414475e 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -720,7 +720,8 @@ int libxl_device_vkb_destroy(libxl_ctx *ctx, uint32_t domid,
                              const libxl_asyncop_how *ao_how);
 
 /* Framebuffer */
-int libxl_device_vfb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb);
+int libxl_device_vfb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb,
+                         const libxl_asyncop_how *ao_how);
 int libxl_device_vfb_remove(libxl_ctx *ctx, uint32_t domid,
                             libxl_device_vfb *vfb,
                             const libxl_asyncop_how *ao_how);
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index fdbcafc..8b5ea4c 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -911,12 +911,15 @@ static void domcreate_rebuild_done(libxl__egc *egc,
         d_config->num_vkbs = 1;
     }
 
-    dcs->aodevs.size = d_config->num_disks + d_config->num_vkbs;
+    dcs->aodevs.size = d_config->num_disks + d_config->num_vkbs +
+                       d_config->num_vfbs;
     dcs->aodevs.callback = domcreate_launch_dm;
     libxl__prepare_ao_devices(ao, &dcs->aodevs);
     libxl__add_disks(egc, ao, domid, 0, d_config, &dcs->aodevs);
     libxl__add_vkbs(egc, ao, domid, d_config->num_disks, d_config,
                     &dcs->aodevs);
+    libxl__add_vfbs(egc, ao, domid, d_config->num_disks + d_config->num_vkbs,
+                    d_config, &dcs->aodevs);
 
     return;
 
@@ -936,7 +939,6 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__ao_devices *aodevs,
     const uint32_t domid = dcs->guest_domid;
     libxl_domain_config *const d_config = dcs->guest_config;
     libxl__domain_build_state *const state = &dcs->build_state;
-    libxl_ctx *const ctx = CTX;
 
     if (ret) {
         LOG(ERROR, "unable to add misc devices");
@@ -972,10 +974,6 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__ao_devices *aodevs,
         int need_qemu = 0;
         libxl__device_console console;
 
-        for (i = 0; i < d_config->num_vfbs; i++) {
-            libxl_device_vfb_add(ctx, domid, &d_config->vfbs[i]);
-        }
-
         ret = init_console_info(&console, 0);
         if ( ret )
             goto error_out;
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index f6e5585..c550ea5 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -481,6 +481,7 @@ void libxl__ao_devices_callback(libxl__egc *egc, libxl__ao_device *aodev)
  * libxl__add_disks
  * libxl__add_nics
  * libxl__add_vkbs
+ * libxl__add_vfbs
  */
 
 #define DEFINE_DEVICES_ADD(type)                                               \
@@ -501,6 +502,7 @@ void libxl__ao_devices_callback(libxl__egc *egc, libxl__ao_device *aodev)
 DEFINE_DEVICES_ADD(disk)
 DEFINE_DEVICES_ADD(nic)
 DEFINE_DEVICES_ADD(vkb)
+DEFINE_DEVICES_ADD(vfb)
 
 #undef DEFINE_DEVICES_ADD
 
diff --git a/tools/libxl/libxl_dm.c b/tools/libxl/libxl_dm.c
index a6ee080..cc35380 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -833,12 +833,16 @@ retry_transaction:
         if (errno == EAGAIN)
             goto retry_transaction;
 
-    sdss->aodevs.size = dm_config->num_disks + dm_config->num_vkbs;
+    sdss->aodevs.size = dm_config->num_disks + dm_config->num_vkbs +
+                        dm_config->num_vfbs;
     sdss->aodevs.callback = spawn_stub_launch_dm;
     libxl__prepare_ao_devices(ao, &sdss->aodevs);
     libxl__add_disks(egc, ao, dm_domid, 0, dm_config, &sdss->aodevs);
     libxl__add_vkbs(egc, ao, dm_domid, dm_config->num_disks, dm_config,
                     &sdss->aodevs);
+    libxl__add_vfbs(egc, ao, dm_domid,
+                    dm_config->num_disks + dm_config->num_vfbs, dm_config,
+                    &sdss->aodevs);
 
     free(args);
     return;
@@ -879,9 +883,6 @@ static void spawn_stub_launch_dm(libxl__egc *egc,
          */
         libxl__device_nic_setdefault(gc, &dm_config->nics[i], dm_domid);
     }
-    ret = libxl_device_vfb_add(ctx, dm_domid, &dm_config->vfbs[0]);
-    if (ret)
-        goto out;
 
     if (guest_config->b_info.u.hvm.serial)
         num_console++;
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 29d2fcd..d34b7ff 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1832,6 +1832,11 @@ _hidden void libxl__device_vkb_add(libxl__egc *egc, uint32_t domid,
                                    libxl_device_vkb *vkb,
                                    libxl__ao_device *aodev);
 
+/* AO operation to connect a vfb device */
+_hidden void libxl__device_vfb_add(libxl__egc *egc, uint32_t domid,
+                                   libxl_device_vfb *vfb,
+                                   libxl__ao_device *aodev);
+
 /* Waits for the passed device to reach state XenbusStateInitWait.
  * This is not really useful by itself, but is important when executing
  * hotplug scripts, since we need to be sure the device is in the correct
@@ -2251,6 +2256,10 @@ _hidden void libxl__add_vkbs(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
                              int start, libxl_domain_config *d_config,
                              libxl__ao_devices *aodevs);
 
+_hidden void libxl__add_vfbs(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
+                             int start, libxl_domain_config *d_config,
+                             libxl__ao_devices *aodevs);
+
 /*----- device model creation -----*/
 
 /* First layer; wraps libxl__spawn_spawn. */
-- 
1.7.7.5 (Apple Git-26)

^ permalink raw reply related	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 05/17] libxl: refactor disk addition to take a helper
  2012-07-13  9:44 ` [PATCH v9 05/17] libxl: refactor disk addition to take a helper Roger Pau Monne
@ 2012-07-17 16:46   ` Ian Jackson
  2012-07-20 10:38     ` Roger Pau Monne
  0 siblings, 1 reply; 40+ messages in thread
From: Ian Jackson @ 2012-07-17 16:46 UTC (permalink / raw)
  To: Roger Pau Monne; +Cc: xen-devel

Roger Pau Monne writes ("[PATCH v9 05/17] libxl: refactor disk addition to take a helper"):
> Change libxl__device_disk_add to no longer take a xs transaction and
> instead pass a helper for the local attach case that's used to get the
> free vdev.
...> 
> This function contains some non-functional changes due to an
> indentation change.

> +/* Specific function called directly only by local disk attach,
> + * all other users should instead use the regular
> + * libxl__device_disk_add wrapper
> + */
> +static int device_disk_add(libxl__gc *gc, uint32_t domid,
> +                           libxl_device_disk *disk,
> +                           char *(*fn)(libxl__gc *, const char *,
> +                                              xs_transaction_t),
> +                           const char *blkdev_start)

(I'm going to be quoting a diff -b.)

A better comment would be one which described what `fn' does.  Ie,
rather than saying `this is internal to local attach', describe its
semantics.

Maybe also `fn' could have a better name.  `get_vdev' ?

And the context pointer should be a void*, not a const char*.
`void *get_vdev_user' or something.

...
> +        if (fn) {
> +            assert(blkdev_start);
> +            disk->vdev = fn(gc, blkdev_start, t);
> +            if (disk->vdev == NULL) {
> +                LOG(ERROR, "libxl__alloc_vdev failed");

Surely this logging is (a) not necessarily true since the caller's fn
may have nothing to do with libxl__alloc_vdev (b) should be done by fn
anyway, since fn probably knows what is going on.

> +        if (front)
> +            flexarray_free(front);
>          front = flexarray_make(16, 1);

Urgh, this is a bit unpleasant, isn't it.  I can't see a better way to
do it though.

Thanks,
Ian.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 01/17] libxl: change ao_device_remove to ao_device
  2012-07-13  9:44 ` [PATCH v9 01/17] libxl: change ao_device_remove to ao_device Roger Pau Monne
@ 2012-07-18 16:29   ` Ian Jackson
  2012-07-19 15:15     ` Roger Pau Monne
  0 siblings, 1 reply; 40+ messages in thread
From: Ian Jackson @ 2012-07-18 16:29 UTC (permalink / raw)
  To: Roger Pau Monne; +Cc: xen-devel

Roger Pau Monne writes ("[PATCH v9 01/17] libxl: change ao_device_remove to ao_device"):
> Introduce a new structure to track state of device backends, that will
> be used in following patches on this series.
> 
> This structure if used for both device creation and device
> destruction and removes libxl__ao_device_remove.
> 
> Changes since v8:
> 
>  * Don't wait for QDISK, VKBD or VFB to disconnect, since Qemu doesn't
>    honour the disconnection protocol.

Following discussion in front of a whiteboard (thanks also to Ian C
and Stefano), we have concluded that this needs to be done
differently.  Here is the comment I promised Roger I would write

Ian.

Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>


/*
 * Algorithm for handling device removal (including domain
 * destruction).  This is somewhat subtle because we may already have
 * killed the domain and caused the death of qemu.
 *
 * In current versions of qemu there is no mechanism for ensuring that
 * the resources used by its devices (both emulated and any PV devices
 * provided by qemu) are freed (eg, fds closed) before it shuts down,
 * and no confirmation from a terminating qemu back to the toolstack.
 *
 * This will need to be fixed in Xen 4.3.  In the meantime (Xen 4.2)
 * we implement a bodge.
 *
 *      WE WANT TO UNPLUG         WE WANT TO SHUT DOWN OR DESTROY
 *                    |                           |
 *                    |             LIBXL SENDS SIGHUP TO QEMU
 *                    |      .....................|........................
 *                    |      : XEN 4.3+ PLANNED   |                       :
 *                    |      :      QEMU TEARS DOWN ALL DEVICES           :
 *                    |      :      FREES RESOURCES (closing fds)         :
 *                    |      :      SETS PV BACKENDS TO STATE 5,          :
 *                    |      :       waits for PV frontends to shut down  :
 *                    |      :       SETS PV BACKENDS TO STATE 6          :
 *                    |      :                    |                       :
 *                    |      :      QEMU NOTIFIES TOOLSTACK (via          :
 *                    |      :       xenstore) that it is exiting         :
 *                    |      :      QEMU EXITS (parent may be init)       :
 *                    |      :                    |                       :
 *                    |      :        TOOLSTACK WAITS FOR QEMU            :
 *                    |      :        notices qemu has finished           :
 *                    |      :....................|.......................:
 *                    |      .--------------------'
 *                    V      V
 *                  for each device
 *                 we want to unplug/remove
 *       ..................|...........................................
 *       :                 V                       XEN 4.2 RACY BODGE :
 *       :      device is provided by    qemu                         :
 *       :            |            `-----------.                      :
 *       :   something|                        V                      :
 *       :    else, eg|             domain (that is domain for which  :
 *       :     blkback|              this PV device is the backend,   :
 *       :            |              which might be the stub dm)      :
 *       :            |                is still alive?                :
 *       :            |                  |        |                   :
 *       :            |                  |alive   |dead               :
 *       :            |<-----------------'        |                   :
 *       :            |    hopefully qemu is      |                   :
 *       :            |       still running       |                   :
 *       :............|.................          |                   :
 *             ,----->|                :     we may be racing         :
 *             |    backend state?     :      with qemu's death       :
 *             ^      |         |      :          |                   :
 *     xenstore|      |other    |6     :      WAIT 2.0s               :
 *     conflict|      |         |      :       TIMEOUT                :
 *             |   WRITE B.E.   |      :          |                   :
 *             |    STATE:=5    |      :     hopefully qemu has       :
 *             `---'  |         |      :      gone by now and         :
 *                    |ok       |      :      freed its resources     :
 *                    |         |      :          |                   :
 *              WAIT FOR        |      :     SET B.E.                 :
 *              STATE==6        |      :      STATE:=6                :
 *              /     |         |      :..........|...................:
 *      timeout/    ok|         |                 |
 *            /       |         |                 |
 *           |    RUN HOTPLUG <-'<----------------'
 *           |      SCRIPT
 *           |        |
 *           `---> NUKE
 *                  BACKEND
 *                    |
 *                   DONE.
 */

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 07/17] libxl: rename vifs to nics
  2012-07-13  9:44 ` [PATCH v9 07/17] libxl: rename vifs to nics Roger Pau Monne
@ 2012-07-19 15:12   ` Ian Jackson
  0 siblings, 0 replies; 40+ messages in thread
From: Ian Jackson @ 2012-07-19 15:12 UTC (permalink / raw)
  To: Roger Pau Monne; +Cc: xen-devel

Roger Pau Monne writes ("[PATCH v9 07/17] libxl: rename vifs to nics"):
> This change renames functions and struct values that used to contain
> vifs in their names to nics, that provides a more clear name to
> define network interfaces without referring to the backend that is
> behind them.
> 
> This is not a functional change.
> 
> Cc: Ian Jackson <ian.jackson@eu.citrix.com>
> Signed-off-by: Roger Pau Monne <roger.pau@citrix.com>

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 01/17] libxl: change ao_device_remove to ao_device
  2012-07-18 16:29   ` Ian Jackson
@ 2012-07-19 15:15     ` Roger Pau Monne
  0 siblings, 0 replies; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-19 15:15 UTC (permalink / raw)
  To: Ian Jackson; +Cc: xen-devel

Ian Jackson wrote:
> Roger Pau Monne writes ("[PATCH v9 01/17] libxl: change ao_device_remove to ao_device"):
>> Introduce a new structure to track state of device backends, that will
>> be used in following patches on this series.
>>
>> This structure if used for both device creation and device
>> destruction and removes libxl__ao_device_remove.
>>
>> Changes since v8:
>>
>>  * Don't wait for QDISK, VKBD or VFB to disconnect, since Qemu doesn't
>>    honour the disconnection protocol.
> 
> Following discussion in front of a whiteboard (thanks also to Ian C
> and Stefano), we have concluded that this needs to be done
> differently.  Here is the comment I promised Roger I would write
> 
> Ian.
> 
> Signed-off-by: Ian Jackson <ian.jackson@eu.citrix.com>
> 
> 
> /*
>  * Algorithm for handling device removal (including domain
>  * destruction).  This is somewhat subtle because we may already have
>  * killed the domain and caused the death of qemu.
>  *
>  * In current versions of qemu there is no mechanism for ensuring that
>  * the resources used by its devices (both emulated and any PV devices
>  * provided by qemu) are freed (eg, fds closed) before it shuts down,
>  * and no confirmation from a terminating qemu back to the toolstack.
>  *
>  * This will need to be fixed in Xen 4.3.  In the meantime (Xen 4.2)
>  * we implement a bodge.
>  *
>  *      WE WANT TO UNPLUG         WE WANT TO SHUT DOWN OR DESTROY
>  *                    |                           |
>  *                    |             LIBXL SENDS SIGHUP TO QEMU
>  *                    |      .....................|........................
>  *                    |      : XEN 4.3+ PLANNED   |                       :
>  *                    |      :      QEMU TEARS DOWN ALL DEVICES           :
>  *                    |      :      FREES RESOURCES (closing fds)         :
>  *                    |      :      SETS PV BACKENDS TO STATE 5,          :
>  *                    |      :       waits for PV frontends to shut down  :
>  *                    |      :       SETS PV BACKENDS TO STATE 6          :
>  *                    |      :                    |                       :
>  *                    |      :      QEMU NOTIFIES TOOLSTACK (via          :
>  *                    |      :       xenstore) that it is exiting         :
>  *                    |      :      QEMU EXITS (parent may be init)       :
>  *                    |      :                    |                       :
>  *                    |      :        TOOLSTACK WAITS FOR QEMU            :
>  *                    |      :        notices qemu has finished           :
>  *                    |      :....................|.......................:
>  *                    |      .--------------------'
>  *                    V      V
>  *                  for each device
>  *                 we want to unplug/remove
>  *       ..................|...........................................
>  *       :                 V                       XEN 4.2 RACY BODGE :
>  *       :      device is provided by    qemu                         :
>  *       :            |            `-----------.                      :
>  *       :   something|                        V                      :
>  *       :    else, eg|             domain (that is domain for which  :
>  *       :     blkback|              this PV device is the backend,   :
>  *       :            |              which might be the stub dm)      :
>  *       :            |                is still alive?                :
>  *       :            |                  |        |                   :
>  *       :            |                  |alive   |dead               :
>  *       :            |<-----------------'        |                   :
>  *       :            |    hopefully qemu is      |                   :
>  *       :            |       still running       |                   :
>  *       :............|.................          |                   :
>  *             ,----->|                :     we may be racing         :
>  *             |    backend state?     :      with qemu's death       :
>  *             ^      |         |      :          |                   :
>  *     xenstore|      |other    |6     :      WAIT 2.0s               :
>  *     conflict|      |         |      :       TIMEOUT                :
>  *             |   WRITE B.E.   |      :          |                   :
>  *             |    STATE:=5    |      :     hopefully qemu has       :
>  *             `---'  |         |      :      gone by now and         :
>  *                    |ok       |      :      freed its resources     :
>  *                    |         |      :          |                   :
>  *              WAIT FOR        |      :     SET B.E.                 :
>  *              STATE==6        |      :      STATE:=6                :
>  *              /     |         |      :..........|...................:
>  *      timeout/    ok|         |                 |
>  *            /       |         |                 |
>  *           |    RUN HOTPLUG <-'<----------------'
>  *           |      SCRIPT
>  *           |        |
>  *           `---> NUKE
>  *                  BACKEND
>  *                    |
>  *                   DONE.
>  */

This is the diagram comment I'm planning to add on top of the callbacks
in libxl_device.c, it contains the flow of functions used for device
plug/unplug:

/*
 * This is a general flow that describes the device plug/unplug process
 * Some functions are ommited (like _cleanup) to simplify the scheme.
 *
 *   +----------------------+
 * +->initiate_device_remove+
 * | +----------------------+---------+
 * |                                  |
 * | +---------------+ NO +-----------v-----------+
 * | |wait state == 6+----+Qemu bk && domu running|
 * | +----------+---++    +-----------+-----------+
 * |            |   |                 |YES
 * |         T/O|   |OK               |T/O 2s
 * |            |   |         +-------v-----------+
 * |            |   |         |device_qemu_timeout|
 * |            |   |         |      set state = 6|
 * |            |   |         +-------+-----------+
 * |            |   |                 |
 * |            |   |     +-----------v-----------+
+---------------+T/O
 * |            |   +----->device_backend_callback<--------+wait state
== 2+--+
 * |            |         +-----------+-----------+
OK+-------------^-+  |
 * |OK       +--v-------+             |
NO|    |
 * |force = 1|disconnect|          +--v-----------+
+-----+-+  |
 * +---------+&& !force |  +-------+device_hotplug<--+-------------+Qemu
bk|  |
 *           +---+------+  |       +--------------+  |
YES+-----^-+  |
 *             NO|         |                         |
 |    |
 *               |         |                         |
 |    |
 * +-------------+         |
|+------------------+---+|
 * | +---------------------v-+       +------------+
||wait_device_connection||
 * |++get_hotplug_script_info+------->exec_hotplug|
|+----------------------+|
 * ||+-----------------------+OK     +---+------+-+  |
      |
 * ||                                 T/O|      |    |
      |
 * ||               +--------------------+      |    |
      |
 * ||+--------------v---+  +--------------------v-+  |
      |
 * |||hotplug_timeout_cb|  |hotplug_child_death_cb+--+
      |
 * |||       kill script|  |            num_exec++|OK
      |
 * ||+------------------+  +--------------------+-+
      |
 * ||                                      error|
      |
 * ||                                           |
      |
 * ||                         +-----------------v-+
      |
 *
+>------------------------->device_hotplug_done<---------------------------+
 *   error || no script left  +--------+----------+
 *                                     |
 *                         +-----------v--------+    +-----------------+
 *                         |action == disconnect+---->rm back/front end|
 *                         +-------------------++YES ++----------------+
 *                                           NO|      |
 *                                            +v------v+
 *                                            |callback|
 *                                            +--------+
 */

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 08/17] libxl: convert libxl_device_disk_add to an async op
  2012-07-13  9:44 ` [PATCH v9 08/17] libxl: convert libxl_device_disk_add to an async op Roger Pau Monne
@ 2012-07-19 15:58   ` Ian Jackson
  2012-07-19 16:14     ` Roger Pau Monne
  2012-07-20  9:41   ` Ian Campbell
  1 sibling, 1 reply; 40+ messages in thread
From: Ian Jackson @ 2012-07-19 15:58 UTC (permalink / raw)
  To: Roger Pau Monne; +Cc: xen-devel

Roger Pau Monne writes ("[PATCH v9 08/17] libxl: convert libxl_device_disk_add to an async op"):
> This patch converts libxl_device_disk_add to an ao operation that
> waits for device backend to reach state XenbusStateInitWait and then
> marks the operation as completed. This is not really useful now, but
> will be used by later patches that will launch hotplug scripts after
> we reached the desired xenbus state.

This looks pretty good.  I have just a couple of questions:

> +/* Waits for the passed device to reach state XenbusStateInitWait.
> + * This is not really useful by itself, but is important when executing
> + * hotplug scripts, since we need to be sure the device is in the correct
> + * state before executing them.
> + *
> + * Once finished, aodev->callback will be executed.
> + */
> +_hidden void libxl__wait_device_connection(libxl__egc*,
> +                                           libxl__ao_device *aodev);

This comment seems to be wrong ?  We set the callback
to device_backend_callback but perhaps that calls aodev->callback ?

It's hard for me to see the context without applying all of these
patches; could you perhaps provide a public git ref too next time ?

> @@ -1808,6 +1829,8 @@ struct libxl__ao_devices {
>   * The libxl__ao_device passed to this function should be
>   * prepared using libxl__prepare_ao_device prior to calling
>   * this function.
> + *
> + * Once finished, aodev->callback will be executed.
>   */
>  _hidden void libxl__initiate_device_remove(libxl__egc *egc,
>                                             libxl__ao_device *aodev);
> @@ -2162,6 +2185,19 @@ _hidden void libxl__destroy_domid(libxl__egc *egc,

Is this hunk in the wrong patch ?

Ian.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 08/17] libxl: convert libxl_device_disk_add to an async op
  2012-07-19 15:58   ` Ian Jackson
@ 2012-07-19 16:14     ` Roger Pau Monne
  2012-07-20 10:43       ` Ian Jackson
  0 siblings, 1 reply; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-19 16:14 UTC (permalink / raw)
  To: Ian Jackson; +Cc: xen-devel

Ian Jackson wrote:
> Roger Pau Monne writes ("[PATCH v9 08/17] libxl: convert libxl_device_disk_add to an async op"):
>> This patch converts libxl_device_disk_add to an ao operation that
>> waits for device backend to reach state XenbusStateInitWait and then
>> marks the operation as completed. This is not really useful now, but
>> will be used by later patches that will launch hotplug scripts after
>> we reached the desired xenbus state.
> 
> This looks pretty good.  I have just a couple of questions:
> 
>> +/* Waits for the passed device to reach state XenbusStateInitWait.
>> + * This is not really useful by itself, but is important when executing
>> + * hotplug scripts, since we need to be sure the device is in the correct
>> + * state before executing them.
>> + *
>> + * Once finished, aodev->callback will be executed.
>> + */
>> +_hidden void libxl__wait_device_connection(libxl__egc*,
>> +                                           libxl__ao_device *aodev);
> 
> This comment seems to be wrong ?  We set the callback
> to device_backend_callback but perhaps that calls aodev->callback ?

Yes, device_backend_callback is the callback for the devstate event, but
not the callback for the global aodev operation, which is stored in
aodev->callback. I think the caller doesn't need to know that internally
we set another callback, for the devstate event, since what matters is
that aodev->callback will be called when the operation is finished.

> It's hard for me to see the context without applying all of these
> patches; could you perhaps provide a public git ref too next time ?
> 
>> @@ -1808,6 +1829,8 @@ struct libxl__ao_devices {
>>   * The libxl__ao_device passed to this function should be
>>   * prepared using libxl__prepare_ao_device prior to calling
>>   * this function.
>> + *
>> + * Once finished, aodev->callback will be executed.
>>   */
>>  _hidden void libxl__initiate_device_remove(libxl__egc *egc,
>>                                             libxl__ao_device *aodev);
>> @@ -2162,6 +2185,19 @@ _hidden void libxl__destroy_domid(libxl__egc *egc,
> 
> Is this hunk in the wrong patch ?

Yes, it is.

> Ian.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 06/17] libxl: convert libxl__device_disk_local_attach to an async op
  2012-07-13  9:44 ` [PATCH v9 06/17] libxl: convert libxl__device_disk_local_attach to an async op Roger Pau Monne
@ 2012-07-19 16:16   ` Ian Jackson
  2012-07-20  9:48     ` Roger Pau Monne
  0 siblings, 1 reply; 40+ messages in thread
From: Ian Jackson @ 2012-07-19 16:16 UTC (permalink / raw)
  To: Roger Pau Monne; +Cc: Stefano Stabellini, xen-devel

Roger Pau Monne writes ("[PATCH v9 06/17] libxl: convert libxl__device_disk_local_attach to an async op"):
> This will be needed in future patches, when libxl__device_disk_add
> becomes async also. Create a new status structure that defines the
> local attach of a disk device and use it in
> libxl__device_disk_local_attach.

Thanks.


> +/*----- local disk attach: attach a disk locally to run the bootloader -----*/
> +
> +typedef struct libxl__disk_local_state libxl__disk_local_state;
> +typedef void libxl__disk_local_state_callback(libxl__egc*,
> +                                              libxl__disk_local_state*,
> +                                              int rc);
> +

> +/* A libxl__disk_local_state may be in the following states:
> + * Undefined, Idle, Attaching, Attached, Detaching, Detached.

What is the difference between Detached and Idle ?

> + */
> +struct libxl__disk_local_state {
> +    /* filled by the user */
> +    libxl__ao *ao;
> +    const libxl_device_disk *in_disk;
> +    libxl_device_disk disk;
> +    const char *blkdev_start;
> +    libxl__disk_local_state_callback *callback;
> +    /* filled by libxl__device_disk_local_initiate_attach */
> +    char *diskpath;
> +    /* private for implementation of local detach */
> +    libxl__ao_device aodev;
> +};
> +
> +/* Initializes the state of a libxl__disk_local_state to init,
                                                            Idle
> + * can be called multiple times.
> + * State Undefined -> Idle
> + */
> +_hidden void libxl__device_disk_local_init(libxl__disk_local_state *dls,
> +                                           libxl__ao *ao,
> +                                           libxl_device_disk *disk,
> +                                           const char *blkdev_start,
> +                                           libxl__disk_local_state_callback
> +                                           *callback);

I don't think an _init function should take an ao and a bunch of
parameters to fill in like that.  Mostly elsewhere init functions just
make sure that attempts to free are safe no-ops.  IMO callers should
fill in themselves the fields which the doc comment says they should
fill in themselves.

> +/* Make a disk available in this (the control) domain. Always calls
> + * dls->callback when finished.
> + * State Idle -> Attached
> + */

Surely state Idle -> Attaching.

> +_hidden void libxl__device_disk_local_initiate_attach(libxl__egc *egc,
> +                                                libxl__disk_local_state *dls);

You need to say what the state is on entry to the callback.  The
sensible thing would be:
   /* State on entry to the callback is:
    *    Attached if rc==0
    *    Idle if rc!=0
    */
but I infer from your user in libxl_bootloader.c that if rc!=0 the dls
is left in some kind of half-attached error state which isn't
documented above.

> +/* Disconnects a disk device form the control domain. If the passed
> + * dls is not attached (or has already been detached),
> + * libxl__device_disk_local_initiate_detach will just call the callback
> + * directly.
> + * State Idle/Attached -> Idle
> + */
> +_hidden void libxl__device_disk_local_initiate_detach(libxl__egc *egc,
> +                                                libxl__disk_local_state *dls);
> +

You mean state Idle/Attached -> Detaching, and
    /* State on entry to the callback is Idle. */
    
Ian.


> diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
...
> @@ -2191,6 +2202,7 @@ char * libxl__device_disk_local_attach(libxl__gc *gc,
>              default:
>                  LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
>                             "unrecognized disk format: %d", disk->format);
> +                rc = ERROR_FAIL;
>                  break;

Why `break' and not `goto out' ?  (Here and later.)

Perhaps this would be clear from context.

> +void libxl__device_disk_local_initiate_detach(libxl__egc *egc,
> +                                     libxl__disk_local_state *dls)
...
>      switch (disk->backend) {
>          case LIBXL_DISK_BACKEND_QDISK:
>              if (disk->vdev != NULL) {
> -                libxl_device_disk_remove(gc->owner, LIBXL_TOOLSTACK_DOMID,
...
> +                return;
>              }
> -            break;
>          default:

This deserves:
  +            /* disk->vdev == NULL; fall through */
           default:
or something.  Particularly since the next comment is then not true,
or at least not applicable:

>              /*
>               * Nothing to do for PHYSTYPE_PHY.
>               * For other device types assume that the blktap2 process is
>               * needed by the soon to be started domain and do nothing.
>               */
> -            break;
> +            dls->callback(egc, dls, rc);



> -    if (bl->diskpath) {
> -        libxl__device_disk_local_detach(gc, &bl->localdisk);
> -        free(bl->diskpath);
> -        bl->diskpath = 0;
> -    }
>      libxl__domaindeathcheck_stop(gc,&bl->deathcheck);
>      libxl__datacopier_kill(&bl->keystrokes);
>      libxl__datacopier_kill(&bl->display);
> @@ -249,10 +245,35 @@ static void bootloader_setpaths(libxl__gc *gc, libxl__bootloader_state *bl)
>      bl->outputpath = GCSPRINTF(XEN_RUN_DIR "/bootloader.%"PRIu32".out", domid);
>  }
> 
> +/* Callbacks */
> +
> +static void bootloader_finished_cb(libxl__egc *egc,
> +                                   libxl__disk_local_state *dls,
> +                                   int rc);
> +
>  static void bootloader_callback(libxl__egc *egc, libxl__bootloader_state *bl,
>                                  int rc)
>  {
>      bootloader_cleanup(egc, bl);
> +
> +    bl->dls.callback = bootloader_finished_cb;
> +    libxl__device_disk_local_initiate_detach(egc, &bl->dls);
> +}

This detaches the disk while we're still using it, AFAICT.
The dls needs to survive completion of the bootloader.

> +static void bootloader_finished_cb(libxl__egc *egc,
> +                                   libxl__disk_local_state *dls,
> +                                   int rc)
> +{
> +    STATE_AO_GC(dls->ao);
> +    libxl__bootloader_state *bl = CONTAINER_OF(dls, *bl, dls);
> +
> +    free(bl->dls.diskpath);
> +    bl->dls.diskpath = 0;

Surely that isn't right ?  We should let the local detach machinery
free this.  The doc comment in the dls struct definition doesn't say
we're to mess with it like this.

> +static void bootloader_disk_attached_cb(libxl__egc *egc,
> +                                        libxl__disk_local_state *dls,
> +                                        int rc)
> +{
> +    STATE_AO_GC(dls->ao);
> +    libxl__bootloader_state *bl = CONTAINER_OF(dls, *bl, dls);
> +    const libxl_domain_build_info *info = bl->info;
> +    const char *bootloader;
> +
> +    if (rc) {
> +        LOG(ERROR, "failed to attach local disk for bootloader execution");
> +        dls->callback = bootloader_disk_failed_cb;
> +        libxl__device_disk_local_initiate_detach(egc, dls);
> +        return;

So in line with my comments about the possible states of a dls, I
think this recovery should be done by the local attach machinery, not
left to the caller like this.

If you do want to insist that if the attach callback is given an error
you need to give a name to the implied Error state of the dls.

If you do as I suggest you can do away with the separate
bootloader_disk_failed_cb; it becomes buried in the attach/detach
machinery which probably doesn't even need a new function for it.


Thanks,
Ian.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 12/17] libxl: set correct nic type depending on the guest
  2012-07-13  9:44 ` [PATCH v9 12/17] libxl: set correct nic type depending on the guest Roger Pau Monne
@ 2012-07-19 16:29   ` Ian Jackson
  0 siblings, 0 replies; 40+ messages in thread
From: Ian Jackson @ 2012-07-19 16:29 UTC (permalink / raw)
  To: Roger Pau Monne; +Cc: xen-devel

Roger Pau Monne writes ("[PATCH v9 12/17] libxl: set correct nic type depending on the guest"):
> Fix the use of nic type, which results in the following for each type
> of domain:
> 
>  * HVM: let the user choose, if none specified use VIF_IOEMU.
>  * HVM with stubdom: use VIF always.

I don't think this is right.  The interface type as specified by
libxl's caller should be the type seen by the guest, not related to
the internal implementation (eg, stubdom or not).

Ian.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 16/17] libxl: convert libxl_device_vkb_add to an async operation
  2012-07-13  9:44 ` [PATCH v9 16/17] libxl: convert libxl_device_vkb_add to an async operation Roger Pau Monne
@ 2012-07-19 16:35   ` Ian Jackson
  2012-07-19 16:41     ` Roger Pau Monne
  0 siblings, 1 reply; 40+ messages in thread
From: Ian Jackson @ 2012-07-19 16:35 UTC (permalink / raw)
  To: Roger Pau Monne; +Cc: xen-devel

Roger Pau Monne writes ("[PATCH v9 16/17] libxl: convert libxl_device_vkb_add to an async operation"):
> Split libxl_device_vkb_add into libxl__device_vkb_add (to be used
> inside already running ao's), and make libxl_device_vkb_add a stub to
> call libxl__device_vkb_add.
...
> -    dcs->aodevs.size = d_config->num_disks;
> +    if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM) {
> +        assert(!d_config->vkbs && !d_config->num_vkbs);

This is rather unfriendly - doesn't it amount to aborting on an
invalid domain configuration.  And I'm not sure I understand the
logic, which is new in your patch.

Ian.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 16/17] libxl: convert libxl_device_vkb_add to an async operation
  2012-07-19 16:35   ` Ian Jackson
@ 2012-07-19 16:41     ` Roger Pau Monne
  2012-07-20 10:49       ` Ian Jackson
  0 siblings, 1 reply; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-19 16:41 UTC (permalink / raw)
  To: Ian Jackson; +Cc: xen-devel

Ian Jackson wrote:
> Roger Pau Monne writes ("[PATCH v9 16/17] libxl: convert libxl_device_vkb_add to an async operation"):
>> Split libxl_device_vkb_add into libxl__device_vkb_add (to be used
>> inside already running ao's), and make libxl_device_vkb_add a stub to
>> call libxl__device_vkb_add.
> ...
>> -    dcs->aodevs.size = d_config->num_disks;
>> +    if (d_config->c_info.type == LIBXL_DOMAIN_TYPE_HVM) {
>> +        assert(!d_config->vkbs && !d_config->num_vkbs);
> 
> This is rather unfriendly - doesn't it amount to aborting on an
> invalid domain configuration.  And I'm not sure I understand the
> logic, which is new in your patch.

This was part of the previous code, but this was done inside of a switch
instead of an if. Since it's not possible to specify vkb devices in the
config file (at least xl.cfg(5) doesn't mention anything about vkbs),
I'm quite sure d_config->vkbs == NULL and d_config->num_vkbs == 0 always
or something has gone extremely wrong, just added the abort to be sure.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 08/17] libxl: convert libxl_device_disk_add to an async op
  2012-07-13  9:44 ` [PATCH v9 08/17] libxl: convert libxl_device_disk_add to an async op Roger Pau Monne
  2012-07-19 15:58   ` Ian Jackson
@ 2012-07-20  9:41   ` Ian Campbell
  2012-07-20 10:54     ` Roger Pau Monne
  1 sibling, 1 reply; 40+ messages in thread
From: Ian Campbell @ 2012-07-20  9:41 UTC (permalink / raw)
  To: Roger Pau Monne; +Cc: Ian Jackson, xen-devel

On Fri, 2012-07-13 at 10:44 +0100, Roger Pau Monne wrote:
> diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
> index c730ac5..f3161d5 100644
> --- a/tools/libxl/libxl.h
> +++ b/tools/libxl/libxl.h
> @@ -675,7 +675,9 @@ void libxl_vcpuinfo_list_free(libxl_vcpuinfo *,
> int nr_vcpus);
>   */
> 
>  /* Disks */
> -int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid,
> libxl_device_disk *disk);
> +int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid,
> +                          libxl_device_disk *disk,
> +                          const libxl_asyncop_how *ao_how);
>  int libxl_device_disk_remove(libxl_ctx *ctx, uint32_t domid,
>                               libxl_device_disk *disk,
>                               const libxl_asyncop_how *ao_how); 

This means you need:
        diff -r 95cb75013da5 tools/ocaml/libs/xl/xenlight_stubs.c
        --- a/tools/ocaml/libs/xl/xenlight_stubs.c	Fri Jul 20 10:34:50 2012 +0100
        +++ b/tools/ocaml/libs/xl/xenlight_stubs.c	Fri Jul 20 10:40:45 2012 +0100
        @@ -247,7 +247,7 @@ value stub_xl_device_disk_add(value info
         	device_disk_val(&gc, &lg, &c_info, info);
         
         	INIT_CTX();
        -	ret = libxl_device_disk_add(ctx, Int_val(domid), &c_info);
        +	ret = libxl_device_disk_add(ctx, Int_val(domid), &c_info, 0);
         	if (ret != 0)
         		failwith_xl("disk_add", &lg);
         	FREE_CTX();
        
I also got:
        xenlight_stubs.c: In function ‘stub_xl_device_nic_add’:
        xenlight_stubs.c:284: error: too few arguments to function ‘libxl_device_nic_add’
        xenlight_stubs.c: In function ‘stub_xl_device_vkb_add’:
        xenlight_stubs.c:318: error: too few arguments to function ‘libxl_device_vkb_add’
        xenlight_stubs.c: In function ‘stub_xl_device_vkb_destroy’:
        xenlight_stubs.c:354: error: too few arguments to function ‘libxl_device_vkb_destroy’
        xenlight_stubs.c: In function ‘stub_xl_device_vfb_add’:
        xenlight_stubs.c:372: error: too few arguments to function ‘libxl_device_vfb_add’
        xenlight_stubs.c: In function ‘stub_xl_device_vfb_destroy’:
        xenlight_stubs.c:408: error: too few arguments to function ‘libxl_device_vfb_destroy’
but I presume you can find the right patches for those without me
sending them one by one.


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 06/17] libxl: convert libxl__device_disk_local_attach to an async op
  2012-07-19 16:16   ` Ian Jackson
@ 2012-07-20  9:48     ` Roger Pau Monne
  2012-07-20 11:27       ` Ian Jackson
  0 siblings, 1 reply; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-20  9:48 UTC (permalink / raw)
  To: Ian Jackson; +Cc: Stefano Stabellini, xen-devel

Ian Jackson wrote:
> Roger Pau Monne writes ("[PATCH v9 06/17] libxl: convert libxl__device_disk_local_attach to an async op"):
>> This will be needed in future patches, when libxl__device_disk_add
>> becomes async also. Create a new status structure that defines the
>> local attach of a disk device and use it in
>> libxl__device_disk_local_attach.
> 
> Thanks.
> 
> 
>> +/*----- local disk attach: attach a disk locally to run the bootloader -----*/
>> +
>> +typedef struct libxl__disk_local_state libxl__disk_local_state;
>> +typedef void libxl__disk_local_state_callback(libxl__egc*,
>> +                                              libxl__disk_local_state*,
>> +                                              int rc);
>> +
> 
>> +/* A libxl__disk_local_state may be in the following states:
>> + * Undefined, Idle, Attaching, Attached, Detaching, Detached.
> 
> What is the difference between Detached and Idle ?

None, I've removed the "Detached" state.

>> + */
>> +struct libxl__disk_local_state {
>> +    /* filled by the user */
>> +    libxl__ao *ao;
>> +    const libxl_device_disk *in_disk;
>> +    libxl_device_disk disk;
>> +    const char *blkdev_start;
>> +    libxl__disk_local_state_callback *callback;
>> +    /* filled by libxl__device_disk_local_initiate_attach */
>> +    char *diskpath;
>> +    /* private for implementation of local detach */
>> +    libxl__ao_device aodev;
>> +};
>> +
>> +/* Initializes the state of a libxl__disk_local_state to init,
>                                                             Idle
>> + * can be called multiple times.
>> + * State Undefined -> Idle
>> + */
>> +_hidden void libxl__device_disk_local_init(libxl__disk_local_state *dls,
>> +                                           libxl__ao *ao,
>> +                                           libxl_device_disk *disk,
>> +                                           const char *blkdev_start,
>> +                                           libxl__disk_local_state_callback
>> +                                           *callback);
> 
> I don't think an _init function should take an ao and a bunch of
> parameters to fill in like that.  Mostly elsewhere init functions just
> make sure that attempts to free are safe no-ops.  IMO callers should
> fill in themselves the fields which the doc comment says they should
> fill in themselves.

Ok, I've removed the libxl__device_disk_local_init function and filled
the struct in the caller's function.

>> +/* Make a disk available in this (the control) domain. Always calls
>> + * dls->callback when finished.
>> + * State Idle -> Attached
>> + */
> 
> Surely state Idle -> Attaching.

Fixed

>> +_hidden void libxl__device_disk_local_initiate_attach(libxl__egc *egc,
>> +                                                libxl__disk_local_state *dls);
> 
> You need to say what the state is on entry to the callback.  The
> sensible thing would be:
>    /* State on entry to the callback is:
>     *    Attached if rc==0
>     *    Idle if rc!=0
>     */
> but I infer from your user in libxl_bootloader.c that if rc!=0 the dls
> is left in some kind of half-attached error state which isn't
> documented above.

Yes, this is what the previous code did (I'm not saying it is good or bad).

>> +/* Disconnects a disk device form the control domain. If the passed
>> + * dls is not attached (or has already been detached),
>> + * libxl__device_disk_local_initiate_detach will just call the callback
>> + * directly.
>> + * State Idle/Attached -> Idle
>> + */
>> +_hidden void libxl__device_disk_local_initiate_detach(libxl__egc *egc,
>> +                                                libxl__disk_local_state *dls);
>> +
> 
> You mean state Idle/Attached -> Detaching, and
>     /* State on entry to the callback is Idle. */
>     

Fixed.

> 
> 
>> diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
> ...
>> @@ -2191,6 +2202,7 @@ char * libxl__device_disk_local_attach(libxl__gc *gc,
>>              default:
>>                  LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
>>                             "unrecognized disk format: %d", disk->format);
>> +                rc = ERROR_FAIL;
>>                  break;
> 
> Why `break' and not `goto out' ?  (Here and later.)
> 
> Perhaps this would be clear from context.

This is part of the original code, and I don't think it's a good idea to
add more patches to my series, if we want to get them in for 4.2.

>> +void libxl__device_disk_local_initiate_detach(libxl__egc *egc,
>> +                                     libxl__disk_local_state *dls)
> ...
>>      switch (disk->backend) {
>>          case LIBXL_DISK_BACKEND_QDISK:
>>              if (disk->vdev != NULL) {
>> -                libxl_device_disk_remove(gc->owner, LIBXL_TOOLSTACK_DOMID,
> ...
>> +                return;
>>              }
>> -            break;
>>          default:
> 
> This deserves:
>   +            /* disk->vdev == NULL; fall through */
>            default:
> or something.  Particularly since the next comment is then not true,
> or at least not applicable:

Done.

>>              /*
>>               * Nothing to do for PHYSTYPE_PHY.
>>               * For other device types assume that the blktap2 process is
>>               * needed by the soon to be started domain and do nothing.
>>               */
>> -            break;
>> +            dls->callback(egc, dls, rc);
> 
> 
> 
>> -    if (bl->diskpath) {
>> -        libxl__device_disk_local_detach(gc, &bl->localdisk);
>> -        free(bl->diskpath);
>> -        bl->diskpath = 0;
>> -    }
>>      libxl__domaindeathcheck_stop(gc,&bl->deathcheck);
>>      libxl__datacopier_kill(&bl->keystrokes);
>>      libxl__datacopier_kill(&bl->display);
>> @@ -249,10 +245,35 @@ static void bootloader_setpaths(libxl__gc *gc, libxl__bootloader_state *bl)
>>      bl->outputpath = GCSPRINTF(XEN_RUN_DIR "/bootloader.%"PRIu32".out", domid);
>>  }
>>
>> +/* Callbacks */
>> +
>> +static void bootloader_finished_cb(libxl__egc *egc,
>> +                                   libxl__disk_local_state *dls,
>> +                                   int rc);
>> +
>>  static void bootloader_callback(libxl__egc *egc, libxl__bootloader_state *bl,
>>                                  int rc)
>>  {
>>      bootloader_cleanup(egc, bl);
>> +
>> +    bl->dls.callback = bootloader_finished_cb;
>> +    libxl__device_disk_local_initiate_detach(egc, &bl->dls);
>> +}
> 
> This detaches the disk while we're still using it, AFAICT.
> The dls needs to survive completion of the bootloader.

This is done in the same part of code as it was previously done (in the
past the call was inside bootloader_cleanup, which was the first
function bootloader_callback calls).

Since bootloader_callback is called after bootloader_finished, and that
gets caller when the bootloader process dies, I'm quite sure the
bootloader has already finished at this point.

>> +static void bootloader_finished_cb(libxl__egc *egc,
>> +                                   libxl__disk_local_state *dls,
>> +                                   int rc)
>> +{
>> +    STATE_AO_GC(dls->ao);
>> +    libxl__bootloader_state *bl = CONTAINER_OF(dls, *bl, dls);
>> +
>> +    free(bl->dls.diskpath);
>> +    bl->dls.diskpath = 0;
> 
> Surely that isn't right ?  We should let the local detach machinery
> free this.  The doc comment in the dls struct definition doesn't say
> we're to mess with it like this.

I've changed that so the free is done inside the callback of
libxl__device_disk_local_initiate_detach.

>> +static void bootloader_disk_attached_cb(libxl__egc *egc,
>> +                                        libxl__disk_local_state *dls,
>> +                                        int rc)
>> +{
>> +    STATE_AO_GC(dls->ao);
>> +    libxl__bootloader_state *bl = CONTAINER_OF(dls, *bl, dls);
>> +    const libxl_domain_build_info *info = bl->info;
>> +    const char *bootloader;
>> +
>> +    if (rc) {
>> +        LOG(ERROR, "failed to attach local disk for bootloader execution");
>> +        dls->callback = bootloader_disk_failed_cb;
>> +        libxl__device_disk_local_initiate_detach(egc, dls);
>> +        return;
> 
> So in line with my comments about the possible states of a dls, I
> think this recovery should be done by the local attach machinery, not
> left to the caller like this.

Ok, I agree this is not optimal, but I would also argue that it has the
same behaviour as the previous code. I will fix this by calling the
detach function in the attach callback if the attach failed.

> If you do want to insist that if the attach callback is given an error
> you need to give a name to the implied Error state of the dls.
> 
> If you do as I suggest you can do away with the separate
> bootloader_disk_failed_cb; it becomes buried in the attach/detach
> machinery which probably doesn't even need a new function for it.
> 
> 
> Thanks,
> Ian.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 05/17] libxl: refactor disk addition to take a helper
  2012-07-17 16:46   ` Ian Jackson
@ 2012-07-20 10:38     ` Roger Pau Monne
  0 siblings, 0 replies; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-20 10:38 UTC (permalink / raw)
  To: Ian Jackson; +Cc: xen-devel

Ian Jackson wrote:
> Roger Pau Monne writes ("[PATCH v9 05/17] libxl: refactor disk addition to take a helper"):
>> Change libxl__device_disk_add to no longer take a xs transaction and
>> instead pass a helper for the local attach case that's used to get the
>> free vdev.
> ...> 
>> This function contains some non-functional changes due to an
>> indentation change.
> 
>> +/* Specific function called directly only by local disk attach,
>> + * all other users should instead use the regular
>> + * libxl__device_disk_add wrapper
>> + */
>> +static int device_disk_add(libxl__gc *gc, uint32_t domid,
>> +                           libxl_device_disk *disk,
>> +                           char *(*fn)(libxl__gc *, const char *,
>> +                                              xs_transaction_t),
>> +                           const char *blkdev_start)
> 
> (I'm going to be quoting a diff -b.)
> 
> A better comment would be one which described what `fn' does.  Ie,
> rather than saying `this is internal to local attach', describe its
> semantics.
> 
> Maybe also `fn' could have a better name.  `get_vdev' ?
> 
> And the context pointer should be a void*, not a const char*.
> `void *get_vdev_user' or something.
> 
> ...
>> +        if (fn) {
>> +            assert(blkdev_start);
>> +            disk->vdev = fn(gc, blkdev_start, t);
>> +            if (disk->vdev == NULL) {
>> +                LOG(ERROR, "libxl__alloc_vdev failed");
> 
> Surely this logging is (a) not necessarily true since the caller's fn
> may have nothing to do with libxl__alloc_vdev (b) should be done by fn
> anyway, since fn probably knows what is going on.

I've fixed all the above, thanks for the review.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 08/17] libxl: convert libxl_device_disk_add to an async op
  2012-07-19 16:14     ` Roger Pau Monne
@ 2012-07-20 10:43       ` Ian Jackson
  0 siblings, 0 replies; 40+ messages in thread
From: Ian Jackson @ 2012-07-20 10:43 UTC (permalink / raw)
  To: Roger Pau Monne; +Cc: xen-devel

Roger Pau Monne writes ("Re: [PATCH v9 08/17] libxl: convert libxl_device_disk_add to an async op"):
> Ian Jackson wrote:
> > This comment seems to be wrong ?  We set the callback
> > to device_backend_callback but perhaps that calls aodev->callback ?
> 
> Yes, device_backend_callback is the callback for the devstate event, but
> not the callback for the global aodev operation, which is stored in
> aodev->callback. I think the caller doesn't need to know that internally
> we set another callback, for the devstate event, since what matters is
> that aodev->callback will be called when the operation is finished.

Right, OK.

> >> @@ -1808,6 +1829,8 @@ struct libxl__ao_devices {
> >>   * The libxl__ao_device passed to this function should be
> >>   * prepared using libxl__prepare_ao_device prior to calling
> >>   * this function.
> >> + *
> >> + * Once finished, aodev->callback will be executed.
> >>   */
> >>  _hidden void libxl__initiate_device_remove(libxl__egc *egc,
> >>                                             libxl__ao_device *aodev);
> >> @@ -2162,6 +2185,19 @@ _hidden void libxl__destroy_domid(libxl__egc *egc,
> > 
> > Is this hunk in the wrong patch ?
> 
> Yes, it is.

Right, apart from that last thing, then:

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 16/17] libxl: convert libxl_device_vkb_add to an async operation
  2012-07-19 16:41     ` Roger Pau Monne
@ 2012-07-20 10:49       ` Ian Jackson
  2012-07-20 11:00         ` Roger Pau Monne
  0 siblings, 1 reply; 40+ messages in thread
From: Ian Jackson @ 2012-07-20 10:49 UTC (permalink / raw)
  To: Roger Pau Monne; +Cc: xen-devel

Roger Pau Monne writes ("Re: [PATCH v9 16/17] libxl: convert libxl_device_vkb_add to an async operation"):
> Ian Jackson wrote:
...
> > This is rather unfriendly - doesn't it amount to aborting on an
> > invalid domain configuration.  And I'm not sure I understand the
> > logic, which is new in your patch.
> 
> This was part of the previous code, but this was done inside of a switch
> instead of an if. Since it's not possible to specify vkb devices in the
> config file (at least xl.cfg(5) doesn't mention anything about vkbs),
> I'm quite sure d_config->vkbs == NULL and d_config->num_vkbs == 0 always
> or something has gone extremely wrong, just added the abort to be sure.

People who write other code which calls libxl might try to pass vkbds,
but then the code would crash.  And if they didn't test it with HVM
domains, they wouldn't notice that their code had a crash bug.

I think it should cause the creation to fail with ERROR_INVAL.

Ian.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 08/17] libxl: convert libxl_device_disk_add to an async op
  2012-07-20  9:41   ` Ian Campbell
@ 2012-07-20 10:54     ` Roger Pau Monne
  2012-07-20 11:28       ` Ian Jackson
  0 siblings, 1 reply; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-20 10:54 UTC (permalink / raw)
  To: Ian Campbell; +Cc: Ian Jackson, xen-devel

Ian Campbell wrote:
> On Fri, 2012-07-13 at 10:44 +0100, Roger Pau Monne wrote:
>> diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
>> index c730ac5..f3161d5 100644
>> --- a/tools/libxl/libxl.h
>> +++ b/tools/libxl/libxl.h
>> @@ -675,7 +675,9 @@ void libxl_vcpuinfo_list_free(libxl_vcpuinfo *,
>> int nr_vcpus);
>>   */
>>
>>  /* Disks */
>> -int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid,
>> libxl_device_disk *disk);
>> +int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid,
>> +                          libxl_device_disk *disk,
>> +                          const libxl_asyncop_how *ao_how);
>>  int libxl_device_disk_remove(libxl_ctx *ctx, uint32_t domid,
>>                               libxl_device_disk *disk,
>>                               const libxl_asyncop_how *ao_how); 
> 
> This means you need:
>         diff -r 95cb75013da5 tools/ocaml/libs/xl/xenlight_stubs.c
>         --- a/tools/ocaml/libs/xl/xenlight_stubs.c	Fri Jul 20 10:34:50 2012 +0100
>         +++ b/tools/ocaml/libs/xl/xenlight_stubs.c	Fri Jul 20 10:40:45 2012 +0100
>         @@ -247,7 +247,7 @@ value stub_xl_device_disk_add(value info
>          	device_disk_val(&gc, &lg, &c_info, info);
>          
>          	INIT_CTX();
>         -	ret = libxl_device_disk_add(ctx, Int_val(domid), &c_info);
>         +	ret = libxl_device_disk_add(ctx, Int_val(domid), &c_info, 0);
>          	if (ret != 0)
>          		failwith_xl("disk_add", &lg);
>          	FREE_CTX();
>         
> I also got:
>         xenlight_stubs.c: In function ‘stub_xl_device_nic_add’:
>         xenlight_stubs.c:284: error: too few arguments to function ‘libxl_device_nic_add’
>         xenlight_stubs.c: In function ‘stub_xl_device_vkb_add’:
>         xenlight_stubs.c:318: error: too few arguments to function ‘libxl_device_vkb_add’
>         xenlight_stubs.c: In function ‘stub_xl_device_vkb_destroy’:
>         xenlight_stubs.c:354: error: too few arguments to function ‘libxl_device_vkb_destroy’
>         xenlight_stubs.c: In function ‘stub_xl_device_vfb_add’:
>         xenlight_stubs.c:372: error: too few arguments to function ‘libxl_device_vfb_add’
>         xenlight_stubs.c: In function ‘stub_xl_device_vfb_destroy’:
>         xenlight_stubs.c:408: error: too few arguments to function ‘libxl_device_vfb_destroy’
> but I presume you can find the right patches for those without me
> sending them one by one.
> 

Thanks, I didn't have any idea we had those bindings. I've gonna check
each patch to be sure I'm not breaking anything once I can get ocaml
working...

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 16/17] libxl: convert libxl_device_vkb_add to an async operation
  2012-07-20 10:49       ` Ian Jackson
@ 2012-07-20 11:00         ` Roger Pau Monne
  0 siblings, 0 replies; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-20 11:00 UTC (permalink / raw)
  To: Ian Jackson; +Cc: xen-devel

Ian Jackson wrote:
> Roger Pau Monne writes ("Re: [PATCH v9 16/17] libxl: convert libxl_device_vkb_add to an async operation"):
>> Ian Jackson wrote:
> ...
>>> This is rather unfriendly - doesn't it amount to aborting on an
>>> invalid domain configuration.  And I'm not sure I understand the
>>> logic, which is new in your patch.
>> This was part of the previous code, but this was done inside of a switch
>> instead of an if. Since it's not possible to specify vkb devices in the
>> config file (at least xl.cfg(5) doesn't mention anything about vkbs),
>> I'm quite sure d_config->vkbs == NULL and d_config->num_vkbs == 0 always
>> or something has gone extremely wrong, just added the abort to be sure.
> 
> People who write other code which calls libxl might try to pass vkbds,
> but then the code would crash.  And if they didn't test it with HVM
> domains, they wouldn't notice that their code had a crash bug.
> 
> I think it should cause the creation to fail with ERROR_INVAL.

I've been thinking about this and I think that maybe we should only
perform this piece of code if num_vkbs is 0, so we make sure there's at
least one vkb device, but not fail if num_vkbs > 0.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 06/17] libxl: convert libxl__device_disk_local_attach to an async op
  2012-07-20  9:48     ` Roger Pau Monne
@ 2012-07-20 11:27       ` Ian Jackson
  2012-07-20 12:52         ` Roger Pau Monne
  2012-07-20 17:45         ` Ian Jackson
  0 siblings, 2 replies; 40+ messages in thread
From: Ian Jackson @ 2012-07-20 11:27 UTC (permalink / raw)
  To: Roger Pau Monne; +Cc: Stefano Stabellini, xen-devel

Roger Pau Monne writes ("Re: [PATCH v9 06/17] libxl: convert libxl__device_disk_local_attach to an async op"):
> [stuff]

Thanks.

> Ian Jackson wrote:
> >> diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
> > ...
> >> @@ -2191,6 +2202,7 @@ char * libxl__device_disk_local_attach(libxl__gc *gc,
> >>              default:
> >>                  LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
> >>                             "unrecognized disk format: %d", disk->format);
> >> +                rc = ERROR_FAIL;
> >>                  break;
> > 
> > Why `break' and not `goto out' ?  (Here and later.)
> > 
> > Perhaps this would be clear from context.
> 
> This is part of the original code, and I don't think it's a good idea to
> add more patches to my series, if we want to get them in for 4.2.

Perhaps this would have been clearer in context.  Can I have a git
branch to look at next time pretty please ? :-)  (I see you're working
on that, great, thanks.)


> >>  static void bootloader_callback(libxl__egc *egc, libxl__bootloader_state *bl,
> >>                                  int rc)
> >>  {
> >>      bootloader_cleanup(egc, bl);
> >> +
> >> +    bl->dls.callback = bootloader_finished_cb;
> >> +    libxl__device_disk_local_initiate_detach(egc, &bl->dls);
> >> +}
> > 
> > This detaches the disk while we're still using it, AFAICT.
> > The dls needs to survive completion of the bootloader.
> 
> This is done in the same part of code as it was previously done (in the
> past the call was inside bootloader_cleanup, which was the first
> function bootloader_callback calls).
> 
> Since bootloader_callback is called after bootloader_finished, and that
> gets caller when the bootloader process dies, I'm quite sure the
> bootloader has already finished at this point.

I was going to say that the disk needs to stay mounted until after
domain building, because the image file is mmapped, but actually I
have double-checked the code and the file we mmap is actually a copy
made by the bootloader, and does not refer to the attached local disk.

So I was confused, sorry.


> >> +static void bootloader_finished_cb(libxl__egc *egc,
> >> +                                   libxl__disk_local_state *dls,
> >> +                                   int rc)
> >> +{
> >> +    STATE_AO_GC(dls->ao);
> >> +    libxl__bootloader_state *bl = CONTAINER_OF(dls, *bl, dls);
> >> +
> >> +    free(bl->dls.diskpath);
> >> +    bl->dls.diskpath = 0;
> > 
> > Surely that isn't right ?  We should let the local detach machinery
> > free this.  The doc comment in the dls struct definition doesn't say
> > we're to mess with it like this.
> 
> I've changed that so the free is done inside the callback of
> libxl__device_disk_local_initiate_detach.

Is the diskpath not from the gc ?  If it isn't then the memory
lifetime and ownership needs to be documented by the variable
definition (ie, the struct member definition).


> >> +static void bootloader_disk_attached_cb(libxl__egc *egc,
> >> +                                        libxl__disk_local_state *dls,
> >> +                                        int rc)
> >> +{
> >> +    STATE_AO_GC(dls->ao);
> >> +    libxl__bootloader_state *bl = CONTAINER_OF(dls, *bl, dls);
> >> +    const libxl_domain_build_info *info = bl->info;
> >> +    const char *bootloader;
> >> +
> >> +    if (rc) {
> >> +        LOG(ERROR, "failed to attach local disk for bootloader execution");
> >> +        dls->callback = bootloader_disk_failed_cb;
> >> +        libxl__device_disk_local_initiate_detach(egc, dls);
> >> +        return;
> > 
> > So in line with my comments about the possible states of a dls, I
> > think this recovery should be done by the local attach machinery, not
> > left to the caller like this.
> 
> Ok, I agree this is not optimal, but I would also argue that it has the
> same behaviour as the previous code. I will fix this by calling the
> detach function in the attach callback if the attach failed.

I'm not sure what you mean by "I will fix this by ...", because AFAICT
you are already calling "the detach function"
(libxl__device_disk_local_initiate_detach) in "the attach callback"
(bootloader_disk_attached_cb).

Anyway, I don't really mind whether the disk local attach exposes this
Error state but if you do expose it you should document it.


Ian.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 08/17] libxl: convert libxl_device_disk_add to an async op
  2012-07-20 10:54     ` Roger Pau Monne
@ 2012-07-20 11:28       ` Ian Jackson
  0 siblings, 0 replies; 40+ messages in thread
From: Ian Jackson @ 2012-07-20 11:28 UTC (permalink / raw)
  To: Roger Pau Monne; +Cc: Ian Campbell, xen-devel

Roger Pau Monne writes ("Re: [Xen-devel] [PATCH v9 08/17] libxl: convert libxl_device_disk_add to an async op"):
> Thanks, I didn't have any idea we had those bindings. I've gonna check
> each patch to be sure I'm not breaking anything once I can get ocaml
> working...

I will in any case notice if you break the build, before anything gets
committed to xen-unstable.

Ian.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 06/17] libxl: convert libxl__device_disk_local_attach to an async op
  2012-07-20 11:27       ` Ian Jackson
@ 2012-07-20 12:52         ` Roger Pau Monne
  2012-07-20 17:45         ` Ian Jackson
  1 sibling, 0 replies; 40+ messages in thread
From: Roger Pau Monne @ 2012-07-20 12:52 UTC (permalink / raw)
  To: Ian Jackson; +Cc: Stefano Stabellini, xen-devel

Ian Jackson wrote:
>> Ian Jackson wrote:
>>>> diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
>>> ...
>>>> @@ -2191,6 +2202,7 @@ char * libxl__device_disk_local_attach(libxl__gc *gc,
>>>>              default:
>>>>                  LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
>>>>                             "unrecognized disk format: %d", disk->format);
>>>> +                rc = ERROR_FAIL;
>>>>                  break;
>>> Why `break' and not `goto out' ?  (Here and later.)
>>>
>>> Perhaps this would be clear from context.
>> This is part of the original code, and I don't think it's a good idea to
>> add more patches to my series, if we want to get them in for 4.2.
> 
> Perhaps this would have been clearer in context.  Can I have a git
> branch to look at next time pretty please ? :-)  (I see you're working
> on that, great, thanks.)

Yes, I will try to send a pull request later.

>>>> +static void bootloader_finished_cb(libxl__egc *egc,
>>>> +                                   libxl__disk_local_state *dls,
>>>> +                                   int rc)
>>>> +{
>>>> +    STATE_AO_GC(dls->ao);
>>>> +    libxl__bootloader_state *bl = CONTAINER_OF(dls, *bl, dls);
>>>> +
>>>> +    free(bl->dls.diskpath);
>>>> +    bl->dls.diskpath = 0;
>>> Surely that isn't right ?  We should let the local detach machinery
>>> free this.  The doc comment in the dls struct definition doesn't say
>>> we're to mess with it like this.
>> I've changed that so the free is done inside the callback of
>> libxl__device_disk_local_initiate_detach.
> 
> Is the diskpath not from the gc ?  If it isn't then the memory
> lifetime and ownership needs to be documented by the variable
> definition (ie, the struct member definition).

No, and frankly I can't find any reason why it shouldn't be allocated
from the gc. The local attach/detach functions are internal to libxl,
and if the resulting diskpath has to survive the gc I would say this is
a problem of the caller.

>>>> +static void bootloader_disk_attached_cb(libxl__egc *egc,
>>>> +                                        libxl__disk_local_state *dls,
>>>> +                                        int rc)
>>>> +{
>>>> +    STATE_AO_GC(dls->ao);
>>>> +    libxl__bootloader_state *bl = CONTAINER_OF(dls, *bl, dls);
>>>> +    const libxl_domain_build_info *info = bl->info;
>>>> +    const char *bootloader;
>>>> +
>>>> +    if (rc) {
>>>> +        LOG(ERROR, "failed to attach local disk for bootloader execution");
>>>> +        dls->callback = bootloader_disk_failed_cb;
>>>> +        libxl__device_disk_local_initiate_detach(egc, dls);
>>>> +        return;
>>> So in line with my comments about the possible states of a dls, I
>>> think this recovery should be done by the local attach machinery, not
>>> left to the caller like this.
>> Ok, I agree this is not optimal, but I would also argue that it has the
>> same behaviour as the previous code. I will fix this by calling the
>> detach function in the attach callback if the attach failed.
> 
> I'm not sure what you mean by "I will fix this by ...", because AFAICT
> you are already calling "the detach function"
> (libxl__device_disk_local_initiate_detach) in "the attach callback"
> (bootloader_disk_attached_cb).

Yes, but this is in the attach callback provided by the user, which
means we call the user callback with an unknown disk state.

Now I've fixed this and I'm calling detach internally, so the user
doesn't have to deal with this. If the local attach fails, the
bootloader just has to exit.

> Anyway, I don't really mind whether the disk local attach exposes this
> Error state but if you do expose it you should document it.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 06/17] libxl: convert libxl__device_disk_local_attach to an async op
  2012-07-20 11:27       ` Ian Jackson
  2012-07-20 12:52         ` Roger Pau Monne
@ 2012-07-20 17:45         ` Ian Jackson
  1 sibling, 0 replies; 40+ messages in thread
From: Ian Jackson @ 2012-07-20 17:45 UTC (permalink / raw)
  To: Roger Pau Monne, xen-devel, Stefano Stabellini

Ian Jackson writes ("Re: [PATCH v9 06/17] libxl: convert libxl__device_disk_local_attach to an async op"):
> Roger Pau Monne writes ("Re: [PATCH v9 06/17] libxl: convert libxl__device_disk_local_attach to an async op"):
> > [stuff]
> 
> Thanks.
> 
> > Ian Jackson wrote:
> > >> diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
> > > ...
> > >> @@ -2191,6 +2202,7 @@ char * libxl__device_disk_local_attach(libxl__gc *gc,
> > >>              default:
> > >>                  LIBXL__LOG(ctx, LIBXL__LOG_ERROR,
> > >>                             "unrecognized disk format: %d", disk->format);
> > >> +                rc = ERROR_FAIL;
> > >>                  break;
> > > 
> > > Why `break' and not `goto out' ?  (Here and later.)
> > > 
> > > Perhaps this would be clear from context.
> > 
> > This is part of the original code, and I don't think it's a good idea to
> > add more patches to my series, if we want to get them in for 4.2.
> 
> Perhaps this would have been clearer in context.  Can I have a git
> branch to look at next time pretty please ? :-)  (I see you're working
> on that, great, thanks.)

I have looked at this in context and it doesn't seem right to me.  Or
at least not clearly right.

`break' here ends up falling out of the switch and executes this:

     if (disk->vdev != NULL) {
         rc = libxl__device_from_disk(gc, LIBXL_TOOLSTACK_DOMID, disk, &device);
         if (rc < 0)
             goto out;

In the general case vdev will be non-0, so the rc = ERROR_FAIL is
lost.

I think you can fix thi sin the same patch as you add the assignments
to rc, changing the error breaks to `goto out'.  Would that make the
code right in your opinion ?

Ian.

^ permalink raw reply	[flat|nested] 40+ messages in thread

* Re: [PATCH v9 17/17] libxl: convert libxl_device_vfb_add to an async operation
  2012-07-13  9:44 ` [PATCH v9 17/17] libxl: convert libxl_device_vfb_add " Roger Pau Monne
@ 2012-07-26 10:42   ` Ian Jackson
  0 siblings, 0 replies; 40+ messages in thread
From: Ian Jackson @ 2012-07-26 10:42 UTC (permalink / raw)
  To: Roger Pau Monne; +Cc: xen-devel

Roger Pau Monne writes ("[PATCH v9 17/17] libxl: convert libxl_device_vfb_add to an async operation"):
> Split libxl_device_vfb_add into libxl__device_vfb_add (to be used
> inside already running ao's), and make libxl_device_vfb_add a stub
> to call libxl__device_vfb_add.

Acked-by: Ian Jackson <ian.jackson@eu.citrix.com>

^ permalink raw reply	[flat|nested] 40+ messages in thread

end of thread, other threads:[~2012-07-26 10:42 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-07-13  9:44 [PATCH v9 00/15] execute hotplug scripts from libxl Roger Pau Monne
2012-07-13  9:44 ` [PATCH v9 01/17] libxl: change ao_device_remove to ao_device Roger Pau Monne
2012-07-18 16:29   ` Ian Jackson
2012-07-19 15:15     ` Roger Pau Monne
2012-07-13  9:44 ` [PATCH v9 02/17] libxl: move device model creation prototypes Roger Pau Monne
2012-07-13  9:44 ` [PATCH v9 03/17] libxl: convert libxl_domain_destroy to an async op Roger Pau Monne
2012-07-13  9:44 ` [PATCH v9 04/17] libxl: move bootloader data strucutres and prototypes Roger Pau Monne
2012-07-13  9:44 ` [PATCH v9 05/17] libxl: refactor disk addition to take a helper Roger Pau Monne
2012-07-17 16:46   ` Ian Jackson
2012-07-20 10:38     ` Roger Pau Monne
2012-07-13  9:44 ` [PATCH v9 06/17] libxl: convert libxl__device_disk_local_attach to an async op Roger Pau Monne
2012-07-19 16:16   ` Ian Jackson
2012-07-20  9:48     ` Roger Pau Monne
2012-07-20 11:27       ` Ian Jackson
2012-07-20 12:52         ` Roger Pau Monne
2012-07-20 17:45         ` Ian Jackson
2012-07-13  9:44 ` [PATCH v9 07/17] libxl: rename vifs to nics Roger Pau Monne
2012-07-19 15:12   ` Ian Jackson
2012-07-13  9:44 ` [PATCH v9 08/17] libxl: convert libxl_device_disk_add to an async op Roger Pau Monne
2012-07-19 15:58   ` Ian Jackson
2012-07-19 16:14     ` Roger Pau Monne
2012-07-20 10:43       ` Ian Jackson
2012-07-20  9:41   ` Ian Campbell
2012-07-20 10:54     ` Roger Pau Monne
2012-07-20 11:28       ` Ian Jackson
2012-07-13  9:44 ` [PATCH v9 09/17] libxl: convert libxl_device_nic_add to an async operation Roger Pau Monne
2012-07-13  9:44 ` [PATCH v9 10/17] libxl: add option to choose who executes hotplug scripts Roger Pau Monne
2012-07-13  9:44 ` [PATCH v9 11/17] libxl: rename _IOEMU nic type to VIF_IOEMU Roger Pau Monne
2012-07-13  9:44 ` [PATCH v9 12/17] libxl: set correct nic type depending on the guest Roger Pau Monne
2012-07-19 16:29   ` Ian Jackson
2012-07-13  9:44 ` [PATCH v9 13/17] libxl: use libxl__xs_path_cleanup on device_destroy Roger Pau Monne
2012-07-13  9:44 ` [PATCH v9 14/17] libxl: call hotplug scripts for disk devices from libxl Roger Pau Monne
2012-07-13  9:44 ` [PATCH v9 15/17] libxl: call hotplug scripts for nic " Roger Pau Monne
2012-07-13  9:44 ` [PATCH v9 16/17] libxl: convert libxl_device_vkb_add to an async operation Roger Pau Monne
2012-07-19 16:35   ` Ian Jackson
2012-07-19 16:41     ` Roger Pau Monne
2012-07-20 10:49       ` Ian Jackson
2012-07-20 11:00         ` Roger Pau Monne
2012-07-13  9:44 ` [PATCH v9 17/17] libxl: convert libxl_device_vfb_add " Roger Pau Monne
2012-07-26 10:42   ` Ian Jackson

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.