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

[Xen-devel] [PATCH v6 06/13] 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 latter 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 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>
Signed-off-by: Roger Pau Monne <roger.pau@xxxxxxxxxx>
---
 tools/libxl/libxl.c          |  166 ++++++++++++++++++++++++++++--------------
 tools/libxl/libxl.h          |    4 +-
 tools/libxl/libxl_create.c   |   40 ++++++++--
 tools/libxl/libxl_device.c   |   69 +++++++++++++++++
 tools/libxl/libxl_dm.c       |   60 +++++++++++----
 tools/libxl/libxl_internal.h |   43 ++++++++++-
 tools/libxl/xl_cmdimpl.c     |    2 +-
 7 files changed, 301 insertions(+), 83 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 43affd1..5f09740 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1655,13 +1655,16 @@ 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)
+void libxl__device_disk_add(libxl__egc *egc, uint32_t domid,
+                            xs_transaction_t t,
+                            libxl_device_disk *disk,
+                            libxl__ao_device *aodev)
 {
+    STATE_AO_GC(aodev->ao);
     flexarray_t *front;
     flexarray_t *back;
     char *dev;
-    libxl__device device;
+    libxl__device *device;
     int major, minor, rc;
     libxl_ctx *ctx = gc->owner;
 
@@ -1686,7 +1689,8 @@ int libxl__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);
@@ -1704,7 +1708,7 @@ int libxl__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);
@@ -1725,7 +1729,7 @@ int libxl__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);
@@ -1757,29 +1761,42 @@ int libxl__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));
 
+    aodev->dev = device;
+    aodev->action = DEVICE_CONNECT;
+    libxl__initiate_device_connection(egc, aodev);
+
     rc = 0;
 
 out_free:
     flexarray_free(back);
     flexarray_free(front);
 out:
-    return rc;
+    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)
+int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid,
+                          libxl_device_disk *disk,
+                          const libxl_asyncop_how *ao_how)
 {
-    GC_INIT(ctx);
-    int rc = libxl__device_disk_add(gc, domid, XBT_NULL, disk);
-    GC_FREE;
-    return rc;
+    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_disk_add(egc, domid, XBT_NULL, disk, aodev);
+
+    return AO_INPROGRESS;
 }
 
 static void libxl__device_disk_from_xs_be(libxl__gc *gc,
@@ -1982,11 +1999,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++)
@@ -2027,15 +2046,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_attach(libxl__egc *egc,
                                      libxl__disk_local_state *dls)
 {
     STATE_AO_GC(dls->ao);
     libxl_ctx *ctx = CTX;
-    char *dev = NULL, *be_path = NULL;
-    int rc, xs_ret;
-    libxl__device device;
-    xs_transaction_t t = XBT_NULL;
+    char *dev = NULL;
+    int rc;
     const libxl_device_disk *in_disk = dls->in_disk;
     libxl_device_disk *disk = &dls->disk;
     const char *blkdev_start = dls->blkdev_start;
@@ -2082,34 +2103,24 @@ void libxl__device_disk_local_attach(libxl__egc *egc,
             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");
-                        rc = ERROR_FAIL;
-                        goto out;
-                    }
-                    disk->vdev = libxl__alloc_vdev(gc, blkdev_start, t);
-                    if (disk->vdev == NULL) {
-                        LOG(ERROR, "libxl__alloc_vdev failed");
-                        rc = ERROR_FAIL;
-                        goto out;
-                    }
-                    rc = libxl__device_disk_add(gc, LIBXL_TOOLSTACK_DOMID,
-                                                t, disk);
-                    if (rc) {
-                        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");
+                dls->t = xs_transaction_start(ctx->xsh);
+                if (dls->t == XBT_NULL) {
+                    LOG(ERROR, "failed to start a xenstore transaction");
+                    rc = ERROR_FAIL;
+                    goto out;
+                }
+                disk->vdev = libxl__alloc_vdev(gc, blkdev_start, dls->t);
+                if (disk->vdev == NULL) {
+                    LOG(ERROR, "libxl__alloc_vdev 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;
+                libxl__device_disk_add(egc, LIBXL_TOOLSTACK_DOMID,
+                                       dls->t, disk, &dls->aodev);
+                return;
             } else {
                 dev = disk->pdev_path;
             }
@@ -2122,15 +2133,60 @@ void libxl__device_disk_local_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);
+    if (dls->t != XBT_NULL)
+        xs_transaction_end(ctx->xsh, dls->t, 1);
+    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);
+    libxl_ctx *ctx = CTX;
+    char *dev = NULL, *be_path = NULL;
+    int rc, xs_ret;
+    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;
+    }
+
+    xs_ret = xs_transaction_end(ctx->xsh, dls->t, 0);
+    if (xs_ret == 0 && errno == EAGAIN) {
+        libxl__device_disk_local_attach(egc, dls);
+        return;
+    }
+    dls->t = XBT_NULL;
+    if (xs_ret == 0) {
+        LOGE(ERROR, "xenstore transaction failed");
+        rc = ERROR_FAIL;
+        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);
 
@@ -2139,8 +2195,8 @@ void libxl__device_disk_local_attach(libxl__egc *egc,
 
  out:
     assert(rc);
-    if (t != XBT_NULL)
-        xs_transaction_end(ctx->xsh, t, 1);
+    if (dls->t != XBT_NULL)
+        xs_transaction_end(ctx->xsh, dls->t, 1);
     dls->callback(egc, dls, rc);
 }
 
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 1967e66..de06f65 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -651,7 +651,9 @@ void libxl_vminfo_list_free(libxl_vminfo *list, int nr);
  */
 
 /* 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 a47bef7..53ecc0d 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -581,6 +581,9 @@ 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 rc);
+
 static void domcreate_console_available(libxl__egc *egc,
                                         libxl__domain_create_state *dcs);
 
@@ -681,7 +684,6 @@ static void domcreate_bootloader_done(libxl__egc *egc,
 {
     libxl__domain_create_state *dcs = CONTAINER_OF(bl, *dcs, bl);
     STATE_AO_GC(bl->ao);
-    int i;
 
     /* convenience aliases */
     const uint32_t domid = dcs->guest_domid;
@@ -720,15 +722,35 @@ static void domcreate_bootloader_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;
+    libxl__add_disks(egc, ao, domid, d_config, &dcs->aodevs,
+                     domcreate_launch_dm);
+
+    return;
+
+ error_out:
+    assert(ret);
+    domcreate_complete(egc, dcs, ret);
+}
+
+static void domcreate_launch_dm(libxl__egc *egc, libxl__ao_devices *aodevs,
+                                int rc)
+{
+    libxl__domain_create_state *dcs = CONTAINER_OF(aodevs, *dcs, aodevs);
+    STATE_AO_GC(dcs->ao);
+    int i, ret = 0;
+
+    /* 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 (rc) {
+        LOG(ERROR, "unable to add disk devices");
+        goto error_out;
     }
+
     for (i = 0; i < d_config->num_vifs; i++) {
         ret = libxl_device_nic_add(ctx, domid, &d_config->vifs[i]);
         if (ret) {
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 9243806..5d34ed5 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -442,6 +442,45 @@ 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.
+ */
+
+/* Capatibility macro, since disk_add now takes a xs transaction parameter */
+#define libxl__device_disk_add(egc, domid, disk, aodev)                       \
+        libxl__device_disk_add(egc, domid, XBT_NULL, disk, aodev)
+
+#define DEFINE_DEVICES_ADD(type)                                              \
+    void libxl__add_##type##s(libxl__egc *egc, libxl__ao *ao, uint32_t domid, \
+                              libxl_domain_config *d_config,                  \
+                              libxl__ao_devices *aodevs,                      \
+                              libxl__devices_callback *callback)              \
+    {                                                                         \
+        AO_GC;                                                                \
+        int i;                                                                \
+        aodevs->size = d_config->num_##type##s;                               \
+        aodevs->callback = callback;                                          \
+        libxl__prepare_ao_devices(ao, aodevs);                                \
+        aodevs->callback = callback;                                          \
+                                                                              \
+        for (i = 0; i < aodevs->size; i++) {                                  \
+            aodevs->array[i].callback = libxl__ao_devices_callback;           \
+            libxl__device_##type##_add(egc, domid, &d_config->type##s[i],     \
+                                       &aodevs->array[i]);                    \
+        }                                                                     \
+    }
+
+DEFINE_DEVICES_ADD(disk)
+
+#undef libxl__device_disk_add
+#undef DEFINE_DEVICES_ADD
+
+/******************************************************************************/
+
 int libxl__device_destroy(libxl__gc *gc, libxl__device *dev)
 {
     libxl_ctx *ctx = libxl__gc_owner(gc);
@@ -554,6 +593,36 @@ static void device_backend_cleanup(libxl__gc *gc,
 
 static void device_xsentries_remove(libxl__egc *egc, libxl__ao_device *aodev);
 
+void libxl__initiate_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) {
+        aodev->callback(egc, aodev);
+        return;
+    }
+
+    rc = libxl__ev_devstate_wait(gc, &aodev->backend_ds,
+                                 device_backend_callback,
+                                 state_path, XenbusStateInitWait,
+                                 LIBXL_INIT_TIMEOUT * 1000);
+    if (rc) {
+        LOGE(ERROR, "unable to initialize device %s", be_path);
+        goto out_fail;
+    }
+
+    return;
+
+out_fail:
+    assert(rc);
+    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 e5d666a..b7979cb 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -677,6 +677,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 rc);
+
 static void spaw_stubdom_pvqemu_destroy_cb(libxl__egc *egc,
                                            libxl__destroy_domid_state *dis,
                                            int rc);
@@ -685,8 +688,7 @@ 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;
+    int ret;
     libxl_device_vfb vfb;
     libxl_device_vkb vkb;
     char **args;
@@ -805,22 +807,53 @@ 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;
+    libxl__add_disks(egc, ao, dm_domid, dm_config, &sdss->aodevs,
+                     spawn_stub_launch_dm);
+
+    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 rc)
+{
+    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, ret = 0;
+    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 (rc) {
+        LOG(ERROR, "error connecting disk devices");
+        goto out;
+     }
+
     for (i = 0; i < dm_config->num_vifs; i++) {
         ret = libxl_device_nic_add(ctx, dm_domid, &dm_config->vifs[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++;
@@ -828,7 +861,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++) {
@@ -864,7 +897,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;
@@ -875,11 +908,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 85c21b4..937ab08 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -70,6 +70,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
@@ -1242,8 +1243,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,
-        xs_transaction_t t, libxl_device_disk *disk);
 
 _hidden char *libxl__uuid2string(libxl__gc *gc, const libxl_uuid uuid);
 
@@ -1752,6 +1751,27 @@ 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__initiate_device_connection to wait for the device to
+ * finish the connection (might involve executing hotplug scripts).
+ */
+_hidden void libxl__device_disk_add(libxl__egc *egc, uint32_t domid,
+                                    xs_transaction_t t,
+                                    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__initiate_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
@@ -1782,6 +1802,8 @@ struct libxl__disk_local_state {
     char *diskpath;
     /* private for implementation of local detach */
     libxl__ao_device aodev;
+    /* private for implementation of local attach */
+    xs_transaction_t t;
 };
 
 /*
@@ -1999,6 +2021,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 be prepared by this
+ * function, so there's no need to call _prepare before calling this
+ * function.
+ *
+ * The "callback" will be called for each device, and the user is responsible
+ * for calling libxl__ao_device_check_last on the callback.
+ */
+void libxl__add_disks(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
+                      libxl_domain_config *d_config,
+                      libxl__ao_devices *aodevs,
+                      libxl__devices_callback *callback);
+
 /*----- device model creation -----*/
 
 /* First layer; wraps libxl__spawn_spawn. */
@@ -2033,6 +2068,8 @@ typedef struct {
     libxl__domain_build_state dm_state;
     libxl__dm_spawn_state pvqemu;
     libxl__destroy_domid_state dis;
+    /* used to store the state of devices being connected */
+    libxl__ao_devices aodevs;
 } libxl__stub_dm_spawn_state;
 
 _hidden void libxl__spawn_stub_dm(libxl__egc *egc, 
libxl__stub_dm_spawn_state*);
@@ -2061,6 +2098,8 @@ struct libxl__domain_create_state {
          * for the non-stubdom device model. */
     /* necessary if the domain creation failed and we have to destroy it */
     libxl__domain_destroy_state dds;
+    /* used to store the state of devices being connected */
+    libxl__ao_devices aodevs;
 };
 
 /*
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 5ba65c2..a40643d 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -5296,7 +5296,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)


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