@@ -661,24 +661,38 @@ int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid,
return rc;
}
+typedef struct {
+ libxl__ao *ao;
+ libxl_domid domid;
+ libxl_device_disk *disk;
+ libxl_device_disk disk_saved;
+ libxl__domain_qmp_lock *qmp_lock;
+ int dm_ver;
+} libxl__cdrom_insert_state;
+
+static void cdrom_insert_ejected(libxl__egc *egc,
+ libxl__cdrom_insert_state *cis);
+static void cdrom_insert_inserted(libxl__egc *egc,
+ libxl__cdrom_insert_state *cis);
+static void cdrom_insert_done(libxl__egc *egc,
+ libxl__cdrom_insert_state *cis,
+ int rc);
+
int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
const libxl_asyncop_how *ao_how)
{
AO_CREATE(ctx, domid, ao_how);
int num = 0, i;
- libxl_device_disk *disks = NULL, disk_saved;
- libxl_domain_config d_config;
- int rc, dm_ver;
- libxl__device device;
- const char *be_path, *libxl_path;
- char * tmp;
- libxl__domain_userdata_lock *lock = NULL;
- xs_transaction_t t = XBT_NULL;
- flexarray_t *insert = NULL, *empty = NULL;
+ libxl_device_disk *disks = NULL;
+ int rc;
+ libxl__cdrom_insert_state *cis;
- libxl_domain_config_init(&d_config);
- libxl_device_disk_init(&disk_saved);
- libxl_device_disk_copy(ctx, &disk_saved, disk);
+ GCNEW(cis);
+ cis->ao = ao;
+ cis->domid = domid;
+ cis->disk = disk;
+ libxl_device_disk_init(&cis->disk_saved);
+ libxl_device_disk_copy(ctx, &cis->disk_saved, disk);
libxl_domain_type type = libxl__domain_type(gc, domid);
if (type == LIBXL_DOMAIN_TYPE_INVALID) {
@@ -697,8 +711,8 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
goto out;
}
- dm_ver = libxl__device_model_version_running(gc, domid);
- if (dm_ver == -1) {
+ cis->dm_ver = libxl__device_model_version_running(gc, domid);
+ if (cis->dm_ver == -1) {
LOGD(ERROR, domid, "Cannot determine device model version");
rc = ERROR_FAIL;
goto out;
@@ -727,17 +741,8 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
disk->format = LIBXL_DISK_FORMAT_EMPTY;
}
- rc = libxl__device_from_disk(gc, domid, disk, &device);
- if (rc) goto out;
-
- be_path = libxl__device_backend_path(gc, &device);
- libxl_path = libxl__device_libxl_path(gc, &device);
-
- /* Note: CTX lock is already held at this point so lock hierarchy
- * is maintained.
- */
- lock = libxl__lock_domain_userdata(gc, domid);
- if (!lock) {
+ cis->qmp_lock = libxl__lock_domain_qmp(gc, domid);
+ if (!cis->qmp_lock) {
rc = ERROR_LOCK_FAIL;
goto out;
}
@@ -746,7 +751,7 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
* by inserting empty media. JSON is not updated.
*/
- if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
+ if (cis->dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
libxl_device_disk disk_empty;
libxl_device_disk_init(&disk_empty);
@@ -761,6 +766,48 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
if (rc) goto out;
}
+ rc = 0;
+
+out:
+ libxl__device_list_free(&libxl__disk_devtype, disks, num);
+ if (rc) {
+ cdrom_insert_done(egc, cis, rc); /* must be last */
+ } else {
+ cdrom_insert_ejected(egc, cis); /* must be last */
+ }
+ return AO_INPROGRESS;
+}
+
+static void cdrom_insert_ejected(libxl__egc *egc,
+ libxl__cdrom_insert_state *cis)
+{
+ EGC_GC;
+ int rc;
+ libxl__domain_userdata_lock *data_lock = NULL;
+ libxl__device device;
+ const char *be_path, *libxl_path;
+ flexarray_t *empty = NULL;
+ xs_transaction_t t = XBT_NULL;
+ char *tmp;
+ libxl_domain_config d_config;
+
+ /* convenience aliases */
+ libxl_domid domid = cis->domid;
+ libxl_device_disk *disk = cis->disk;
+
+ libxl_domain_config_init(&d_config);
+
+ rc = libxl__device_from_disk(gc, domid, disk, &device);
+ if (rc) goto out;
+ be_path = libxl__device_backend_path(gc, &device);
+ libxl_path = libxl__device_libxl_path(gc, &device);
+
+ data_lock = libxl__lock_domain_userdata(gc, domid);
+ if (!data_lock) {
+ rc = ERROR_LOCK_FAIL;
+ goto out;
+ }
+
empty = flexarray_make(gc, 4, 1);
flexarray_append_pair(empty, "type",
libxl__device_disk_string_of_backend(disk->backend));
@@ -799,16 +846,66 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
rc = libxl__get_domain_configuration(gc, domid, &d_config);
if (rc) goto out;
- device_add_domain_config(gc, &d_config, &libxl__disk_devtype, &disk_saved);
+ device_add_domain_config(gc, &d_config, &libxl__disk_devtype,
+ &cis->disk_saved);
rc = libxl__dm_check_start(gc, &d_config, domid);
if (rc) goto out;
- if (dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
+ if (cis->dm_ver == LIBXL_DEVICE_MODEL_VERSION_QEMU_XEN) {
rc = libxl__qmp_insert_cdrom(gc, domid, disk);
if (rc) goto out;
}
+ rc = 0;
+
+out:
+ libxl__xs_transaction_abort(gc, &t);
+ libxl_domain_config_dispose(&d_config);
+ if (data_lock) libxl__unlock_domain_userdata(data_lock);
+ if (rc) {
+ cdrom_insert_done(egc, cis, rc); /* must be last */
+ } else {
+ cdrom_insert_inserted(egc, cis); /* must be last */
+ }
+}
+
+static void cdrom_insert_inserted(libxl__egc *egc,
+ libxl__cdrom_insert_state *cis)
+{
+ EGC_GC;
+ int rc;
+ libxl__domain_userdata_lock *data_lock = NULL;
+ libxl_domain_config d_config;
+ flexarray_t *insert = NULL;
+ xs_transaction_t t = XBT_NULL;
+ libxl__device device;
+ const char *be_path, *libxl_path;
+ char * tmp;
+
+ /* convenience aliases */
+ libxl_domid domid = cis->domid;
+ libxl_device_disk *disk = cis->disk;
+
+ libxl_domain_config_init(&d_config);
+
+ rc = libxl__device_from_disk(gc, domid, disk, &device);
+ if (rc) goto out;
+ be_path = libxl__device_backend_path(gc, &device);
+ libxl_path = libxl__device_libxl_path(gc, &device);
+
+ data_lock = libxl__lock_domain_userdata(gc, domid);
+ if (!data_lock) {
+ rc = ERROR_LOCK_FAIL;
+ goto out;
+ }
+
+ rc = libxl__get_domain_configuration(gc, domid, &d_config);
+ if (rc) goto out;
+
+ device_add_domain_config(gc, &d_config, &libxl__disk_devtype,
+ &cis->disk_saved);
+
insert = flexarray_make(gc, 4, 1);
flexarray_append_pair(insert, "type",
libxl__device_disk_string_of_backend(disk->backend));
@@ -849,21 +946,22 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
if (rc < 0) goto out;
}
- /* success, no actual async */
- libxl__ao_complete(egc, ao, 0);
-
rc = 0;
out:
libxl__xs_transaction_abort(gc, &t);
- libxl__device_list_free(&libxl__disk_devtype, disks, num);
- libxl_device_disk_dispose(&disk_saved);
libxl_domain_config_dispose(&d_config);
+ if (data_lock) libxl__unlock_domain_userdata(data_lock);
+ cdrom_insert_done(egc, cis, rc); /* must be last */
+}
- if (lock) libxl__unlock_domain_userdata(lock);
-
- if (rc) return AO_CREATE_FAIL(rc);
- return AO_INPROGRESS;
+static void cdrom_insert_done(libxl__egc *egc,
+ libxl__cdrom_insert_state *cis,
+ int rc)
+{
+ if (cis->qmp_lock) libxl__unlock_domain_qmp(cis->qmp_lock);
+ libxl_device_disk_dispose(&cis->disk_saved);
+ libxl__ao_complete(egc, cis->ao, rc);
}
/* libxl__alloc_vdev only works on the local domain, that is the domain
.. and use a new "slow" lock. This patch cut libxl_cdrom_insert into different step/function but there are still called synchronously. A later patch will call them asynchronously when QMP is involved. The json_lock has been replaced by the qmp_lock for protection against concurrent changes to the cdrom. The json_lock is now only used when reading/modifying the domain userdata. Signed-off-by: Anthony PERARD <anthony.perard@citrix.com> --- tools/libxl/libxl_disk.c | 172 ++++++++++++++++++++++++++++++--------- 1 file changed, 135 insertions(+), 37 deletions(-)