[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v3 3/7] libxl: add support for hotplug interface v2 in domain creation/destroy
Add a new variable to libxl_device_disk "hotplug_version", that will be automatically set to the detected hotplug script interface version. This patch adds the basic support to handle this new scripts, by adding the prepare private libxl function, and modifying the current domain creation/destruction to call this functions at the appropriate spots. The hotplug interface detection is done in the _prepare call. This patch also adds some helpers, that will be used here and in later patches. Signed-off-by: Roger Pau Monnà <roger.pau@xxxxxxxxxx> Cc: Ian Campbell <ian.campbell@xxxxxxxxxx> Cc: Ian Jackson <ian.jackson@xxxxxxxxxx> --- Changes since v1: * Keep track of hotplug status in xenstore --- tools/libxl/libxl.c | 144 ++++++++++++++++++++++++++++++- tools/libxl/libxl_create.c | 32 +++++++- tools/libxl/libxl_device.c | 199 +++++++++++++++++++++++++++++++++++++---- tools/libxl/libxl_internal.h | 47 ++++++++++ tools/libxl/libxl_types.idl | 1 + 5 files changed, 400 insertions(+), 23 deletions(-) diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index 03a9782..444e039 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -2012,6 +2012,119 @@ int libxl__device_from_disk(libxl__gc *gc, uint32_t domid, return 0; } +/* Callbacks for libxl__device_disk_prepare */ + +static void device_disk_prepare_cb(libxl__egc *, libxl__ao_device *); + +void libxl__device_disk_prepare(libxl__egc *egc, uint32_t domid, + libxl_device_disk *disk, + libxl__ao_device *prepare_aodev) +{ + STATE_AO_GC(prepare_aodev->ao); + char *hotplug_path; + char *script_path; + int rc; + xs_transaction_t t = XBT_NULL; + libxl__disk_prepare *dp; + libxl__ao_device *aodev; + + if (!disk->script) { + /* If script is not set assume v1 */ + disk->hotplug_version = 1; + prepare_aodev->callback(egc, prepare_aodev); + return; + } + + GCNEW(dp); + dp->disk = disk; + /* Save original aodev, since we will call it once hotplug + * script detection has finished + */ + dp->aodev = prepare_aodev; + aodev = &dp->version_aodev; + libxl__prepare_ao_device(ao, aodev); + + GCNEW(aodev->dev); + rc = libxl__device_from_disk(gc, domid, disk, aodev->dev); + if (rc != 0) { + LOG(ERROR, "Invalid or unsupported virtual disk identifier %s", + disk->vdev); + goto error; + } + + script_path = libxl__abs_path(gc, disk->script, + libxl__xen_script_dir_path()); + + hotplug_path = libxl__device_xs_hotplug_path(gc, aodev->dev); + for (;;) { + rc = libxl__xs_transaction_start(gc, &t); + if (rc) goto error; + + rc = libxl__xs_write_checked(gc, t, + GCSPRINTF("%s/params", hotplug_path), + disk->pdev_path); + if (rc) + goto error; + + rc = libxl__xs_write_checked(gc, t, + GCSPRINTF("%s/script", hotplug_path), + script_path); + if (rc) + goto error; + + rc = libxl__xs_transaction_commit(gc, &t); + if (!rc) break; + if (rc < 0) goto error; + } + + aodev->callback = device_disk_prepare_cb; + aodev->action = LIBXL__DEVICE_ACTION_VERSION; + aodev->disk = disk; + aodev->hotplug.version = 2; + libxl__device_hotplug(egc, aodev); + return; + +error: + assert(rc); + libxl__xs_transaction_abort(gc, &t); + prepare_aodev->rc = rc; + prepare_aodev->callback(egc, prepare_aodev); + return; +} + +static void device_disk_prepare_cb(libxl__egc *egc, + libxl__ao_device *version_aodev) +{ + STATE_AO_GC(version_aodev->ao); + libxl__disk_prepare *dp = CONTAINER_OF(version_aodev, *dp, version_aodev); + libxl__ao_device *aodev = dp->aodev; + + if (dp->disk->hotplug_version == 1) { + aodev->callback(egc, aodev); + return; + } + + aodev->action = LIBXL__DEVICE_ACTION_PREPARE; + aodev->hotplug.version = dp->disk->hotplug_version; + aodev->dev = version_aodev->dev; + + /* + * Write status information to xenstore, so we know this device + * has been prepared + */ + aodev->rc = libxl__xs_write_checked(gc, XBT_NULL, + GCSPRINTF("%s/backend_domid", + libxl__device_xs_hotplug_status_path(gc, aodev->dev)), + GCSPRINTF("%u", aodev->dev->backend_domid)); + if (aodev->rc) { + aodev->callback(egc, aodev); + return; + } + + libxl__device_hotplug(egc, aodev); + return; +} + /* Specific function called directly only by local disk attach, * all other users should instead use the regular * libxl__device_disk_add wrapper @@ -2071,8 +2184,15 @@ static void device_disk_add(libxl__egc *egc, uint32_t domid, dev = disk->pdev_path; do_backend_phy: - flexarray_append(back, "params"); - flexarray_append(back, dev); + if (disk->hotplug_version == 1) { + /* + * If the new hotplug version is used params is + * stored under a private path, since it can contain + * data that the guest should not see. + */ + flexarray_append(back, "params"); + flexarray_append(back, dev); + } script = libxl__abs_path(gc, disk->script?: "block", libxl__xen_script_dir_path()); @@ -2168,6 +2288,8 @@ static void device_disk_add(libxl__egc *egc, uint32_t domid, aodev->dev = device; aodev->action = LIBXL__DEVICE_ACTION_ADD; + aodev->hotplug.version = disk->hotplug_version; + aodev->disk = disk; libxl__wait_device_connection(egc, aodev); rc = 0; @@ -2261,6 +2383,7 @@ int libxl_vdev_to_device_disk(libxl_ctx *ctx, uint32_t domid, GC_INIT(ctx); char *dompath, *path; int devid = libxl__device_disk_dev_number(vdev, NULL, NULL); + libxl__device dev; int rc = ERROR_FAIL; if (devid < 0) @@ -2279,6 +2402,23 @@ int libxl_vdev_to_device_disk(libxl_ctx *ctx, uint32_t domid, goto out; rc = libxl__device_disk_from_xs_be(gc, path, disk); + if (rc) { + LOG(ERROR, "unable to parse disk device from path %s", path); + goto out; + } + + /* Check if the device is using the new hotplug interface */ + rc = libxl__device_from_disk(gc, domid, disk, &dev); + if (rc) { + LOG(ERROR, "invalid or unsupported virtual disk identifier %s", + disk->vdev); + goto out; + } + disk->hotplug_version = 1; + path = libxl__device_xs_hotplug_path(gc, &dev); + if (libxl__xs_read(gc, XBT_NULL, path)) + disk->hotplug_version = 2; + out: GC_FREE; return rc; diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c index ae72f21..708e14e 100644 --- a/tools/libxl/libxl_create.c +++ b/tools/libxl/libxl_create.c @@ -595,6 +595,10 @@ static int store_libxl_entry(libxl__gc *gc, uint32_t domid, */ /* Event callbacks, in this order: */ + +static void domcreate_launch_bootloader(libxl__egc *egc, + libxl__multidev *multidev, + int ret); static void domcreate_devmodel_started(libxl__egc *egc, libxl__dm_spawn_state *dmss, int rc); @@ -641,7 +645,6 @@ static void initiate_domain_create(libxl__egc *egc, /* convenience aliases */ libxl_domain_config *const d_config = dcs->guest_config; - const int restore_fd = dcs->restore_fd; memset(&dcs->build_state, 0, sizeof(dcs->build_state)); domid = 0; @@ -674,6 +677,33 @@ static void initiate_domain_create(libxl__egc *egc, if (ret) goto error_out; } + libxl__multidev_begin(ao, &dcs->multidev); + dcs->multidev.callback = domcreate_launch_bootloader; + libxl__prepare_disks(egc, ao, domid, d_config, &dcs->multidev); + libxl__multidev_prepared(egc, &dcs->multidev, 0); + return; + +error_out: + assert(ret); + domcreate_complete(egc, dcs, ret); +} + +static void domcreate_launch_bootloader(libxl__egc *egc, + libxl__multidev *multidev, + int ret) +{ + libxl__domain_create_state *dcs = CONTAINER_OF(multidev, *dcs, multidev); + STATE_AO_GC(dcs->ao); + + /* convenience aliases */ + const int restore_fd = dcs->restore_fd; + libxl_domain_config *const d_config = dcs->guest_config; + + if (ret) { + LOG(ERROR, "unable to prepare devices"); + goto error_out; + } + dcs->bl.ao = ao; libxl_device_disk *bootdisk = d_config->num_disks > 0 ? &d_config->disks[0] : NULL; diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c index 024bc1f..27a411b 100644 --- a/tools/libxl/libxl_device.c +++ b/tools/libxl/libxl_device.c @@ -58,6 +58,37 @@ int libxl__parse_backend_path(libxl__gc *gc, return libxl__device_kind_from_string(strkind, &dev->backend_kind); } +int libxl__parse_hotplug_status_path(libxl__gc *gc, + const char *path, + libxl__device *dev) +{ + /* /libxl/<domid>/hotplug/status/<kind>/<devid> */ + char strkind[16]; + char *xs_path; + const char *backend_domid; + int rc = sscanf(path, "/libxl/%u/hotplug/status/%15[^/]/%u", + &dev->domid, + strkind, + &dev->devid); + + if (rc != 3) + return ERROR_FAIL; + + xs_path = GCSPRINTF("%s/backend_domid", path); + rc = libxl__xs_read_checked(gc, XBT_NULL, xs_path, &backend_domid); + if (rc) + return rc; + + rc = libxl__device_kind_from_string(strkind, &dev->backend_kind); + if (rc) + return rc; + + dev->backend_domid = atoi(backend_domid); + dev->kind = dev->backend_kind; + + return 0; +} + int libxl__nic_type(libxl__gc *gc, libxl__device *dev, libxl_nic_type *nictype) { char *snictype, *be_path; @@ -91,6 +122,14 @@ char *libxl__device_xs_hotplug_path(libxl__gc *gc, libxl__device *dev) dev->devid); } +char *libxl__device_xs_hotplug_status_path(libxl__gc *gc, libxl__device *dev) +{ + return GCSPRINTF("/libxl/%u/hotplug/status/%s/%u", + dev->domid, + libxl__device_kind_to_string(dev->backend_kind), + dev->devid); +} + int libxl__device_generic_add(libxl__gc *gc, xs_transaction_t t, libxl__device *device, char **bents, char **fents) { @@ -500,18 +539,20 @@ void libxl__multidev_prepared(libxl__egc *egc, /******************************************************************************/ -/* Macro for defining the functions that will add a bunch of disks when +/* Macro for defining the functions that will operate a bunch of devices when * inside an async op with multidev. * This macro is added to prevent repetition of code. * * The following functions are defined: + * libxl__prepare_disks * libxl__add_disks * libxl__add_nics * libxl__add_vtpms */ -#define DEFINE_DEVICES_ADD(type) \ - void libxl__add_##type##s(libxl__egc *egc, libxl__ao *ao, uint32_t domid, \ +#define DEFINE_DEVICES_FUNC(type, op) \ + void libxl__##op##_##type##s(libxl__egc *egc, libxl__ao *ao, \ + uint32_t domid, \ libxl_domain_config *d_config, \ libxl__multidev *multidev) \ { \ @@ -519,16 +560,18 @@ void libxl__multidev_prepared(libxl__egc *egc, int i; \ for (i = 0; i < d_config->num_##type##s; i++) { \ libxl__ao_device *aodev = libxl__multidev_prepare(multidev); \ - libxl__device_##type##_add(egc, domid, &d_config->type##s[i], \ + libxl__device_##type##_##op(egc, domid, &d_config->type##s[i], \ aodev); \ } \ } -DEFINE_DEVICES_ADD(disk) -DEFINE_DEVICES_ADD(nic) -DEFINE_DEVICES_ADD(vtpm) +DEFINE_DEVICES_FUNC(disk, add) +DEFINE_DEVICES_FUNC(nic, add) +DEFINE_DEVICES_FUNC(vtpm, add) + +DEFINE_DEVICES_FUNC(disk, prepare) -#undef DEFINE_DEVICES_ADD +#undef DEFINE_DEVICES_FUNC /******************************************************************************/ @@ -536,7 +579,9 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev) { const char *be_path = libxl__device_backend_path(gc, dev); const char *fe_path = libxl__device_frontend_path(gc, dev); + const char *hotplug_path = libxl__device_xs_hotplug_path(gc, dev); const char *tapdisk_path = GCSPRINTF("%s/%s", be_path, "tapdisk-params"); + const char *hotplug_status = libxl__device_xs_hotplug_status_path(gc, dev); const char *tapdisk_params; xs_transaction_t t = 0; int rc; @@ -551,6 +596,8 @@ int libxl__device_destroy(libxl__gc *gc, libxl__device *dev) libxl__xs_path_cleanup(gc, t, fe_path); libxl__xs_path_cleanup(gc, t, be_path); + libxl__xs_path_cleanup(gc, t, hotplug_path); + libxl__xs_path_cleanup(gc, t, hotplug_status); rc = libxl__xs_transaction_commit(gc, &t); if (!rc) break; @@ -578,6 +625,7 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs) char *path; unsigned int num_kinds, num_dev_xsentries; char **kinds = NULL, **devs = NULL; + const char *backend; int i, j, rc = 0; libxl__device *dev; libxl__multidev *multidev = &drs->multidev; @@ -622,6 +670,19 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs) libxl__device_destroy(gc, dev); continue; } + /* + * Check if the device has hotplug entries in xenstore, + * which would mean it's using the new hotplug calling + * convention. + */ + path = libxl__device_xs_hotplug_path(gc, dev); + if (libxl__xs_read(gc, XBT_NULL, path) != NULL) + /* + * This device will be cleaned in the next loop, + * since it's using the new hotplug interface. + */ + continue; + aodev = libxl__multidev_prepare(multidev); aodev->action = LIBXL__DEVICE_ACTION_REMOVE; aodev->dev = dev; @@ -631,6 +692,33 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs) } } + /* Remove devices that are using hotplug interface v2 */ + path = GCSPRINTF("/libxl/%u/hotplug/status/vbd", domid); + devs = libxl__xs_directory(gc, XBT_NULL, path, &num_dev_xsentries); + if (devs) { + for (j = 0; j < num_dev_xsentries; j++) { + path = GCSPRINTF("/libxl/%u/hotplug/status/vbd/%s", domid, devs[j]); + GCNEW(dev); + if (libxl__parse_hotplug_status_path(gc, path, dev) == 0) { + aodev = libxl__multidev_prepare(multidev); + aodev->dev = dev; + aodev->force = drs->force; + aodev->hotplug.version = 2; + /* Check if the device has been connected */ + path = GCSPRINTF("/local/domain/%u/device/vbd/%u/backend", + dev->domid, dev->devid); + rc = libxl__xs_read_checked(gc, XBT_NULL, path, &backend); + if (rc) { + aodev->action = LIBXL__DEVICE_ACTION_UNPREPARE; + libxl__device_hotplug(egc, aodev); + } else { + aodev->action = LIBXL__DEVICE_ACTION_REMOVE; + libxl__initiate_device_remove(egc, aodev); + } + } + } + } + /* 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); @@ -675,8 +763,6 @@ 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_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); @@ -711,7 +797,7 @@ void libxl__wait_device_connection(libxl__egc *egc, libxl__ao_device *aodev) * 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(egc, aodev); + libxl__device_hotplug(egc, aodev); return; } @@ -843,7 +929,7 @@ static void device_qemu_timeout(libxl__egc *egc, libxl__ev_time *ev, rc = libxl__xs_write_checked(gc, XBT_NULL, state_path, "6"); if (rc) goto out; - device_hotplug(egc, aodev); + libxl__device_hotplug(egc, aodev); return; out: @@ -873,7 +959,7 @@ static void device_backend_callback(libxl__egc *egc, libxl__ev_devstate *ds, goto out; } - device_hotplug(egc, aodev); + libxl__device_hotplug(egc, aodev); return; out: @@ -888,7 +974,7 @@ static void device_backend_cleanup(libxl__gc *gc, libxl__ao_device *aodev) libxl__ev_devstate_cancel(gc, &aodev->backend_ds); } -static void device_hotplug(libxl__egc *egc, libxl__ao_device *aodev) +void libxl__device_hotplug(libxl__egc *egc, libxl__ao_device *aodev) { STATE_AO_GC(aodev->ao); char *be_path = libxl__device_backend_path(gc, aodev->dev); @@ -996,10 +1082,13 @@ static void device_hotplug_child_death_cb(libxl__egc *egc, if (hotplug_error) LOG(ERROR, "script: %s", hotplug_error); aodev->rc = ERROR_FAIL; - if (aodev->action == LIBXL__DEVICE_ACTION_ADD) + if (aodev->action == LIBXL__DEVICE_ACTION_ADD || + aodev->action == LIBXL__DEVICE_ACTION_PREPARE || + aodev->action == LIBXL__DEVICE_ACTION_LOCALATTACH) /* - * Only fail on device connection, on disconnection - * ignore error, and continue with the remove process + * Only fail on device connection, prepare or localattach, + * on other cases ignore error, and continue with the remove + * process. */ goto error; } @@ -1009,7 +1098,7 @@ static void device_hotplug_child_death_cb(libxl__egc *egc, * device_hotplug_done breaking the loop. */ aodev->hotplug.num_exec++; - device_hotplug(egc, aodev); + libxl__device_hotplug(egc, aodev); return; @@ -1021,17 +1110,87 @@ error: static void device_hotplug_done(libxl__egc *egc, libxl__ao_device *aodev) { STATE_AO_GC(aodev->ao); + char *hotplug_path; + const char *pdev, *hotplug_version; int rc; device_hotplug_clean(gc, aodev); - /* Clean xenstore if it's a disconnection */ - if (aodev->action == LIBXL__DEVICE_ACTION_REMOVE) { + switch (aodev->action) { + case LIBXL__DEVICE_ACTION_REMOVE: + switch (aodev->hotplug.version) { + case 1: + /* Clean xenstore if it's a disconnection */ + rc = libxl__device_destroy(gc, aodev->dev); + if (!aodev->rc) + aodev->rc = rc; + break; + case 2: + /* + * Chain unprepare hotplug execution + * after disconnection of device. + */ + aodev->hotplug.num_exec = 0; + aodev->action = LIBXL__DEVICE_ACTION_UNPREPARE; + libxl__device_hotplug(egc, aodev); + return; + default: + LOG(ERROR, "unknown hotplug script version (%d)", + aodev->hotplug.version); + if (!aodev->rc) + aodev->rc = ERROR_FAIL; + break; + } + break; + case LIBXL__DEVICE_ACTION_UNPREPARE: + /* Clean hotplug xenstore path */ rc = libxl__device_destroy(gc, aodev->dev); if (!aodev->rc) aodev->rc = rc; + break; + case LIBXL__DEVICE_ACTION_ADD: + if (aodev->hotplug.version == 1) + goto out; + /* + * Update pdev_path in libxl_device_disk to point to the block + * device + */ + hotplug_path = libxl__device_xs_hotplug_path(gc, aodev->dev); + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/pdev", hotplug_path), + &pdev); + if (rc || !pdev) { + LOG(ERROR, "unable to get physical disk from %s", + GCSPRINTF("%s/pdev", hotplug_path)); + aodev->rc = rc ? rc : ERROR_FAIL; + goto out; + } + + free(aodev->disk->pdev_path); + aodev->disk->pdev_path = libxl__strdup(NOGC, pdev); + break; + case LIBXL__DEVICE_ACTION_VERSION: + /* Fetch hotplug version output */ + hotplug_path = libxl__device_xs_hotplug_path(gc, aodev->dev); + rc = libxl__xs_read_checked(gc, XBT_NULL, + GCSPRINTF("%s/version", hotplug_path), + &hotplug_version); + if (rc) { + LOG(ERROR, "unable to get hotplug_version from %s", + GCSPRINTF("%s/version", hotplug_path)); + aodev->rc = rc; + goto out; + } + if (!hotplug_version) + aodev->disk->hotplug_version = 1; + else + aodev->disk->hotplug_version = atoi(hotplug_version); + break; + default: + break; } +out: aodev->callback(egc, aodev); return; } diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index aa0102c..00d9232 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -2019,6 +2019,9 @@ struct libxl__multidev { _hidden void libxl__device_disk_add(libxl__egc *egc, uint32_t domid, libxl_device_disk *disk, libxl__ao_device *aodev); +_hidden void libxl__device_disk_prepare(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, @@ -2071,6 +2074,23 @@ _hidden void libxl__initiate_device_remove(libxl__egc *egc, _hidden char *libxl__device_xs_hotplug_path(libxl__gc *gc, libxl__device *dev); /* + * libxl__device_xs_hotplug_status_path returns the xenstore hotplug + * path that is used to store status information about a device that + * is using the v2 hotplug interface. + */ +_hidden char *libxl__device_xs_hotplug_status_path(libxl__gc *gc, + libxl__device *dev); + +/* + * libxl__parse_hotplug_status_path returns a device that is filled + * with the information stored in xenstore. This should only be used + * on devices that use the v2 hotplug interface + */ +_hidden int libxl__parse_hotplug_status_path(libxl__gc *gc, + const char *path, + libxl__device *dev); + +/* * libxl__get_hotplug_script_info returns the args and env that should * be passed to the hotplug script for the requested device. * @@ -2093,6 +2113,28 @@ _hidden int libxl__get_hotplug_script_info(libxl__gc *gc, libxl__device *dev, libxl__device_action action, libxl__hotplug *hotplug); +/* + * libxl__device_hotplug runs the hotplug script associated + * with the device passed in aodev->dev. + * + * 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__device_hotplug(libxl__egc *egc, + libxl__ao_device *aodev); + +/* Internal structure to hold device_disk_prepare specific information */ +typedef struct libxl__disk_prepare libxl__disk_prepare; +struct libxl__disk_prepare { + libxl__ao_device version_aodev; + libxl__ao_device *aodev; + libxl_device_disk *disk; + libxl__device_callback *callback; +}; + /*----- local disk attach: attach a disk locally to run the bootloader -----*/ typedef struct libxl__disk_local_state libxl__disk_local_state; @@ -2466,6 +2508,11 @@ _hidden void libxl__add_disks(libxl__egc *egc, libxl__ao *ao, uint32_t domid, libxl_domain_config *d_config, libxl__multidev *multidev); +_hidden void libxl__prepare_disks(libxl__egc *egc, libxl__ao *ao, + uint32_t domid, + libxl_domain_config *d_config, + libxl__multidev *multidev); + _hidden void libxl__add_nics(libxl__egc *egc, libxl__ao *ao, uint32_t domid, libxl_domain_config *d_config, libxl__multidev *multidev); diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl index fcb1ecd..a5470f0 100644 --- a/tools/libxl/libxl_types.idl +++ b/tools/libxl/libxl_types.idl @@ -372,6 +372,7 @@ libxl_device_disk = Struct("device_disk", [ ("removable", integer), ("readwrite", integer), ("is_cdrom", integer), + ("hotplug_version", integer), ]) libxl_device_nic = Struct("device_nic", [ -- 1.7.7.5 (Apple Git-26) _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |