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

[Xen-devel] [PATCH v10 09/19] 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.

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 v9:

 * Removed a wrong comment hunk.

 * Fixed Ocaml bindings.

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@xxxxxxxxxxxxx>
Acked-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
Signed-off-by: Roger Pau Monne <roger.pau@xxxxxxxxxx>
---
 tools/libxl/libxl.c                  |  144 +++++++++++++++++++++++++---------
 tools/libxl/libxl.h                  |    4 +-
 tools/libxl/libxl_create.c           |   42 ++++++++---
 tools/libxl/libxl_device.c           |   77 ++++++++++++++++++
 tools/libxl/libxl_dm.c               |   73 +++++++++++++-----
 tools/libxl/libxl_internal.h         |   39 +++++++++-
 tools/libxl/xl_cmdimpl.c             |    2 +-
 tools/ocaml/libs/xl/xenlight_stubs.c |    2 +-
 8 files changed, 310 insertions(+), 73 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index bd64e0c..d97add5 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1749,16 +1749,18 @@ int libxl__device_from_disk(libxl__gc *gc, uint32_t 
domid,
  * The passed get_vdev_user function is also in charge of printing
  * the corresponding error message when appropiate.
  */
-static int device_disk_add(libxl__gc *gc, uint32_t domid,
+static void device_disk_add(libxl__egc *egc, uint32_t domid,
                            libxl_device_disk *disk,
+                           libxl__ao_device *aodev,
                            void *get_vdev_user(libxl__gc *, const char *,
                                                xs_transaction_t),
                            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;
@@ -1801,7 +1803,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);
@@ -1819,7 +1822,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);
@@ -1840,7 +1843,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);
@@ -1872,11 +1875,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));
 
@@ -1885,6 +1888,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:
@@ -1892,21 +1899,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,
@@ -2109,11 +2110,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 @@ static char * libxl__alloc_vdev(libxl__gc *gc, const 
char *blkdev_start,
     return NULL;
 }
 
+/* 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,
-                                    (void *) 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, (void *) libxl__alloc_vdev,
+                                blkdev_start);
+                return;
             } else {
                 dev = disk->pdev_path;
             }
@@ -2227,15 +2232,48 @@ 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->rc = rc;
+    libxl__device_disk_local_initiate_detach(egc, dls);
+    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);
 
@@ -2973,6 +3011,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 a94beab..a935ced 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -445,6 +445,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);
@@ -573,6 +604,52 @@ static void device_backend_cleanup(libxl__gc *gc,
 
 static void device_hotplug_done(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);
+    libxl_dominfo info;
+    uint32_t domid = aodev->dev->domid;
+    int rc = 0;
+
+    libxl_dominfo_init(&info);
+    rc = libxl_domain_info(CTX, &info, domid);
+    if (rc) {
+        LOG(ERROR, "unable to get info for domain %d", domid);
+        goto out;
+    }
+    if (QEMU_BACKEND(aodev->dev)) {
+        /*
+         * If Qemu is not running, there's no point in waiting for
+         * it to change the state of the device.
+         *
+         * If Qemu is running, it will set the state of the device to
+         * 4 directly, without waiting in state 2 for any hotplug execution.
+         */
+        device_hotplug_done(egc, aodev);
+        return;
+    }
+
+    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;
+    }
+
+    libxl_dominfo_dispose(&info);
+    return;
+
+out:
+    aodev->rc = rc;
+    libxl_dominfo_dispose(&info);
+    device_hotplug_done(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 ab590be..eb69721 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_QEMU_BODGE_TIMEOUT 2
@@ -1297,8 +1298,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);
 
@@ -1883,6 +1882,27 @@ struct libxl__ao_devices {
  *                   DONE.
  */
 
+/* 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
@@ -2253,6 +2273,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. */
@@ -2287,6 +2320,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*);
@@ -2316,6 +2350,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;
diff --git a/tools/ocaml/libs/xl/xenlight_stubs.c 
b/tools/ocaml/libs/xl/xenlight_stubs.c
index 53751b1..a158351 100644
--- a/tools/ocaml/libs/xl/xenlight_stubs.c
+++ b/tools/ocaml/libs/xl/xenlight_stubs.c
@@ -247,7 +247,7 @@ value stub_xl_device_disk_add(value info, value domid)
        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();
-- 
1.7.7.5 (Apple Git-26)


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


 


Rackspace

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