aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--tools/libxl/libxl.c139
-rw-r--r--tools/libxl/libxl.h4
-rw-r--r--tools/libxl/libxl_create.c42
-rw-r--r--tools/libxl/libxl_device.c77
-rw-r--r--tools/libxl/libxl_dm.c73
-rw-r--r--tools/libxl/libxl_internal.h39
-rw-r--r--tools/libxl/xl_cmdimpl.c2
-rw-r--r--tools/ocaml/libs/xl/xenlight_stubs.c2
8 files changed, 306 insertions, 72 deletions
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 900eac1d1f..85475586ba 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1785,16 +1785,18 @@ int libxl__device_from_disk(libxl__gc *gc, uint32_t domid,
* The passed get_vdev 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,
char *get_vdev(libxl__gc *, void *,
xs_transaction_t),
void *get_vdev_user)
{
+ 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;
@@ -1837,7 +1839,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);
@@ -1855,7 +1858,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);
@@ -1876,7 +1879,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);
@@ -1908,11 +1911,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));
@@ -1921,6 +1924,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:
@@ -1928,21 +1935,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,
@@ -2252,14 +2253,17 @@ static char * libxl__alloc_vdev(libxl__gc *gc, void *get_vdev_user,
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;
@@ -2306,14 +2310,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,
- (void *) 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,
+ (void *) blkdev_start);
+ return;
} else {
dev = disk->pdev_path;
}
@@ -2326,15 +2328,48 @@ void libxl__device_disk_local_initiate_attach(libxl__egc *egc,
goto out;
}
- 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 = libxl__strdup(gc, dev);
@@ -3058,6 +3093,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 6f659386ee..cc872ba971 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 3c950bab9c..0d47eb472a 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -560,6 +560,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);
@@ -850,12 +854,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) {
@@ -866,14 +868,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 2429836046..835b4ad235 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -447,6 +447,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)
{
char *be_path = libxl__device_backend_path(gc, dev);
@@ -593,6 +624,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 2c140b0086..8a731ae500 100644
--- a/tools/libxl/libxl_dm.c
+++ b/tools/libxl/libxl_dm.c
@@ -713,6 +713,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);
@@ -726,10 +729,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;
@@ -784,10 +786,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
@@ -845,22 +849,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++;
@@ -868,7 +904,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++) {
@@ -904,7 +940,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;
@@ -915,11 +951,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 03a32faad4..19a9cdc39c 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
@@ -1338,8 +1339,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);
@@ -1923,6 +1922,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
@@ -2295,6 +2315,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. */
@@ -2329,6 +2362,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*);
@@ -2360,6 +2394,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 e7e4016e37..8fbd4483b4 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -5360,7 +5360,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 53751b13a9..a158351794 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();