diff options
-rw-r--r-- | tools/libxl/libxl.c | 229 | ||||
-rw-r--r-- | tools/libxl/libxl.h | 15 | ||||
-rw-r--r-- | tools/libxl/libxl_device.c | 193 | ||||
-rw-r--r-- | tools/libxl/libxl_internal.h | 143 | ||||
-rw-r--r-- | tools/libxl/xl_cmdimpl.c | 2 | ||||
-rw-r--r-- | tools/ocaml/libs/xl/xenlight_stubs.c | 4 |
6 files changed, 390 insertions, 196 deletions
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c index 427774560b..ebc314b46d 100644 --- a/tools/libxl/libxl.c +++ b/tools/libxl/libxl.c @@ -1503,6 +1503,31 @@ int libxl_vncviewer_exec(libxl_ctx *ctx, uint32_t domid, int autopass) /******************************************************************************/ +/* generic callback for devices that only need to set ao_complete */ +static void device_addrm_aocomplete(libxl__egc *egc, libxl__ao_device *aodev) +{ + STATE_AO_GC(aodev->ao); + + if (aodev->rc) { + if (aodev->dev) { + LOG(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); + } else { + LOG(ERROR, "unable to %s device", + aodev->action == DEVICE_CONNECT ? "add" : "remove"); + } + goto out; + } + +out: + libxl__ao_complete(egc, ao, aodev->rc); + return; +} + +/******************************************************************************/ + int libxl__device_disk_setdefault(libxl__gc *gc, libxl_device_disk *disk) { int rc; @@ -1680,42 +1705,6 @@ int libxl_device_disk_add(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *dis return rc; } -int libxl_device_disk_remove(libxl_ctx *ctx, uint32_t domid, - libxl_device_disk *disk, - const libxl_asyncop_how *ao_how) -{ - AO_CREATE(ctx, domid, ao_how); - libxl__device device; - int rc; - - rc = libxl__device_from_disk(gc, domid, disk, &device); - if (rc != 0) goto out; - - rc = libxl__initiate_device_remove(egc, ao, &device); - if (rc) goto out; - - return AO_INPROGRESS; - -out: - return AO_ABORT(rc); -} - -int libxl_device_disk_destroy(libxl_ctx *ctx, uint32_t domid, - libxl_device_disk *disk) -{ - GC_INIT(ctx); - libxl__device device; - int rc; - - rc = libxl__device_from_disk(gc, domid, disk, &device); - if (rc != 0) goto out; - - rc = libxl__device_destroy(gc, &device); -out: - GC_FREE; - return rc; -} - static void libxl__device_disk_from_xs_be(libxl__gc *gc, const char *be_path, libxl_device_disk *disk) @@ -2080,8 +2069,9 @@ int libxl__device_disk_local_detach(libxl__gc *gc, libxl_device_disk *disk) if (disk->vdev != NULL) { libxl_device_disk_remove(gc->owner, LIBXL_TOOLSTACK_DOMID, disk, 0); + /* fixme-ao */ rc = libxl_device_disk_destroy(gc->owner, - LIBXL_TOOLSTACK_DOMID, disk); + LIBXL_TOOLSTACK_DOMID, disk, 0); } break; default: @@ -2249,42 +2239,6 @@ out: return rc; } -int libxl_device_nic_remove(libxl_ctx *ctx, uint32_t domid, - libxl_device_nic *nic, - const libxl_asyncop_how *ao_how) -{ - AO_CREATE(ctx, domid, ao_how); - libxl__device device; - int rc; - - rc = libxl__device_from_nic(gc, domid, nic, &device); - if (rc != 0) goto out; - - rc = libxl__initiate_device_remove(egc, ao, &device); - if (rc) goto out; - - return AO_INPROGRESS; - -out: - return AO_ABORT(rc); -} - -int libxl_device_nic_destroy(libxl_ctx *ctx, uint32_t domid, - libxl_device_nic *nic) -{ - GC_INIT(ctx); - libxl__device device; - int rc; - - rc = libxl__device_from_nic(gc, domid, nic, &device); - if (rc != 0) goto out; - - rc = libxl__device_destroy(gc, &device); -out: - GC_FREE; - return rc; -} - static void libxl__device_nic_from_xs_be(libxl__gc *gc, const char *be_path, libxl_device_nic *nic) @@ -2611,42 +2565,6 @@ out: return rc; } -int libxl_device_vkb_remove(libxl_ctx *ctx, uint32_t domid, - libxl_device_vkb *vkb, - const libxl_asyncop_how *ao_how) -{ - AO_CREATE(ctx, domid, ao_how); - libxl__device device; - int rc; - - rc = libxl__device_from_vkb(gc, domid, vkb, &device); - if (rc != 0) goto out; - - rc = libxl__initiate_device_remove(egc, ao, &device); - if (rc) goto out; - - return AO_INPROGRESS; - -out: - return AO_ABORT(rc); -} - -int libxl_device_vkb_destroy(libxl_ctx *ctx, uint32_t domid, - libxl_device_vkb *vkb) -{ - GC_INIT(ctx); - libxl__device device; - int rc; - - rc = libxl__device_from_vkb(gc, domid, vkb, &device); - if (rc != 0) goto out; - - rc = libxl__device_destroy(gc, &device); -out: - GC_FREE; - return rc; -} - /******************************************************************************/ int libxl__device_vfb_setdefault(libxl__gc *gc, libxl_device_vfb *vfb) @@ -2744,41 +2662,66 @@ out: return rc; } -int libxl_device_vfb_remove(libxl_ctx *ctx, uint32_t domid, - libxl_device_vfb *vfb, - const libxl_asyncop_how *ao_how) -{ - AO_CREATE(ctx, domid, ao_how); - libxl__device device; - int rc; - - rc = libxl__device_from_vfb(gc, domid, vfb, &device); - if (rc != 0) goto out; - - rc = libxl__initiate_device_remove(egc, ao, &device); - if (rc) goto out; - - return AO_INPROGRESS; - -out: - return AO_ABORT(rc); -} - -int libxl_device_vfb_destroy(libxl_ctx *ctx, uint32_t domid, - libxl_device_vfb *vfb) -{ - GC_INIT(ctx); - libxl__device device; - int rc; - - rc = libxl__device_from_vfb(gc, domid, vfb, &device); - if (rc != 0) goto out; +/******************************************************************************/ - rc = libxl__device_destroy(gc, &device); -out: - GC_FREE; - return rc; -} +/* Macro for defining device remove/destroy functions in a compact way */ +/* The following functions are defined: + * libxl_device_disk_remove + * libxl_device_disk_destroy + * libxl_device_nic_remove + * libxl_device_nic_destroy + * libxl_device_vkb_remove + * libxl_device_vkb_destroy + * libxl_device_vfb_remove + * libxl_device_vfb_destroy + */ +#define DEFINE_DEVICE_REMOVE(type, removedestroy, f) \ + int libxl_device_##type##_##removedestroy(libxl_ctx *ctx, \ + uint32_t domid, libxl_device_##type *type, \ + const libxl_asyncop_how *ao_how) \ + { \ + AO_CREATE(ctx, domid, ao_how); \ + libxl__device *device; \ + libxl__ao_device *aodev; \ + int rc; \ + \ + GCNEW(device); \ + rc = libxl__device_from_##type(gc, domid, type, device); \ + if (rc != 0) goto out; \ + \ + GCNEW(aodev); \ + libxl__prepare_ao_device(ao, aodev); \ + aodev->action = DEVICE_DISCONNECT; \ + aodev->dev = device; \ + aodev->callback = device_addrm_aocomplete; \ + aodev->force = f; \ + libxl__initiate_device_remove(egc, aodev); \ + \ + out: \ + if (rc) return AO_ABORT(rc); \ + return AO_INPROGRESS; \ + } + +/* Define all remove/destroy functions and undef the macro */ + +/* disk */ +DEFINE_DEVICE_REMOVE(disk, remove, 0) +DEFINE_DEVICE_REMOVE(disk, destroy, 1) + +/* nic */ +DEFINE_DEVICE_REMOVE(nic, remove, 0) +DEFINE_DEVICE_REMOVE(nic, destroy, 1) + +/* vkb */ +DEFINE_DEVICE_REMOVE(vkb, remove, 0) +DEFINE_DEVICE_REMOVE(vkb, destroy, 1) + +/* vfb */ + +DEFINE_DEVICE_REMOVE(vfb, remove, 0) +DEFINE_DEVICE_REMOVE(vfb, destroy, 1) + +#undef DEFINE_DEVICE_REMOVE /******************************************************************************/ diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h index f5a8f877ea..c2d5c06154 100644 --- a/tools/libxl/libxl.h +++ b/tools/libxl/libxl.h @@ -679,7 +679,8 @@ int libxl_device_disk_remove(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk, const libxl_asyncop_how *ao_how); int libxl_device_disk_destroy(libxl_ctx *ctx, uint32_t domid, - libxl_device_disk *disk); + libxl_device_disk *disk, + const libxl_asyncop_how *ao_how); libxl_device_disk *libxl_device_disk_list(libxl_ctx *ctx, uint32_t domid, int *num); int libxl_device_disk_getinfo(libxl_ctx *ctx, uint32_t domid, @@ -696,7 +697,9 @@ int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic); int libxl_device_nic_remove(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic, const libxl_asyncop_how *ao_how); -int libxl_device_nic_destroy(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic); +int libxl_device_nic_destroy(libxl_ctx *ctx, uint32_t domid, + libxl_device_nic *nic, + const libxl_asyncop_how *ao_how); libxl_device_nic *libxl_device_nic_list(libxl_ctx *ctx, uint32_t domid, int *num); int libxl_device_nic_getinfo(libxl_ctx *ctx, uint32_t domid, @@ -707,14 +710,18 @@ int libxl_device_vkb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb); int libxl_device_vkb_remove(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb, const libxl_asyncop_how *ao_how); -int libxl_device_vkb_destroy(libxl_ctx *ctx, uint32_t domid, libxl_device_vkb *vkb); +int libxl_device_vkb_destroy(libxl_ctx *ctx, uint32_t domid, + libxl_device_vkb *vkb, + const libxl_asyncop_how *ao_how); /* Framebuffer */ int libxl_device_vfb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb); int libxl_device_vfb_remove(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb, const libxl_asyncop_how *ao_how); -int libxl_device_vfb_destroy(libxl_ctx *ctx, uint32_t domid, libxl_device_vfb *vfb); +int libxl_device_vfb_destroy(libxl_ctx *ctx, uint32_t domid, + libxl_device_vfb *vfb, + const libxl_asyncop_how *ao_how); /* PCI Passthrough */ int libxl_device_pci_add(libxl_ctx *ctx, uint32_t domid, libxl_device_pci *pcidev); diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c index d33ac68545..5a07ffb35b 100644 --- a/tools/libxl/libxl_device.c +++ b/tools/libxl/libxl_device.c @@ -361,11 +361,16 @@ int libxl__device_disk_dev_number(const char *virtpath, int *pdisk, return -1; } +/* Device AO operations */ -typedef struct { - libxl__ao *ao; - libxl__ev_devstate ds; -} libxl__ao_device_remove; +void libxl__prepare_ao_device(libxl__ao *ao, libxl__ao_device *aodev) +{ + aodev->ao = ao; + aodev->rc = 0; + aodev->dev = NULL; + /* Initialize timer for QEMU Bodge */ + libxl__ev_time_init(&aodev->timeout); +} int libxl__device_destroy(libxl__gc *gc, libxl__device *dev) { @@ -441,36 +446,81 @@ out: /* Callbacks for device related operations */ -static void device_remove_callback(libxl__egc *egc, libxl__ev_devstate *ds, +/* + * device_backend_callback is the main callback entry point, for both device + * addition and removal. It gets called if we reach the desired state + * (XenbusStateClosed or XenbusStateInitWait). After that, all this + * functions get called in the order displayed below. + * + * If new device types are added, they should only need to modify the + * specific hotplug scripts call, which can be found in each OS specific + * file. If this new devices don't need a hotplug script, no modification + * should be needed. + */ + +/* This callback is part of the Qemu devices Badge */ +static void device_qemu_timeout(libxl__egc *egc, libxl__ev_time *ev, + const struct timeval *requested_abs); + +static void device_backend_callback(libxl__egc *egc, libxl__ev_devstate *ds, int rc); -static void device_remove_cleanup(libxl__gc *gc, - libxl__ao_device_remove *aorm); +static void device_backend_cleanup(libxl__gc *gc, + libxl__ao_device *aodev); -int libxl__initiate_device_remove(libxl__egc *egc, libxl__ao *ao, - libxl__device *dev) +static void device_hotplug_done(libxl__egc *egc, libxl__ao_device *aodev); + +void libxl__initiate_device_remove(libxl__egc *egc, + libxl__ao_device *aodev) { - AO_GC; + STATE_AO_GC(aodev->ao); xs_transaction_t t = 0; - char *be_path = libxl__device_backend_path(gc, dev); + char *be_path = libxl__device_backend_path(gc, aodev->dev); char *state_path = libxl__sprintf(gc, "%s/state", be_path); char *online_path = GCSPRINTF("%s/online", be_path); const char *state; - + libxl_dominfo info; + uint32_t domid = aodev->dev->domid; int rc = 0; - libxl__ao_device_remove *aorm = 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) && + (info.paused || info.dying || info.shutdown)) { + /* + * TODO: 4.2 Bodge due to QEMU, see comment on top of + * libxl__initiate_device_remove in libxl_internal.h + */ + rc = libxl__ev_time_register_rel(gc, &aodev->timeout, + device_qemu_timeout, + LIBXL_QEMU_BODGE_TIMEOUT * 1000); + if (rc) { + LOG(ERROR, "unable to register timeout for Qemu device %s", + be_path); + goto out; + } + return; + } for (;;) { rc = libxl__xs_transaction_start(gc, &t); if (rc) { LOG(ERROR, "unable to start transaction"); - goto out_fail; + goto out; } + if (aodev->force) + libxl__xs_path_cleanup(gc, t, + libxl__device_frontend_path(gc, aodev->dev)); + rc = libxl__xs_read_checked(gc, t, state_path, &state); if (rc) { LOG(ERROR, "unable to read device state from path %s", state_path); - goto out_fail; + goto out; } /* @@ -481,53 +531,118 @@ int libxl__initiate_device_remove(libxl__egc *egc, libxl__ao *ao, rc = libxl__xs_write_checked(gc, t, online_path, "0"); if (rc) { LOG(ERROR, "unable to write to xenstore path %s", online_path); - goto out_fail; + goto out; } rc = libxl__xs_write_checked(gc, t, state_path, "5"); if (rc) { LOG(ERROR, "unable to write to xenstore path %s", state_path); - goto out_fail; + goto out; } } rc = libxl__xs_transaction_commit(gc, &t); if (!rc) break; - if (rc < 0) goto out_fail; + if (rc < 0) goto out; } libxl__device_destroy_tapdisk(gc, be_path); - aorm = libxl__zalloc(gc, sizeof(*aorm)); - aorm->ao = ao; - libxl__ev_devstate_init(&aorm->ds); - - rc = libxl__ev_devstate_wait(gc, &aorm->ds, device_remove_callback, + rc = libxl__ev_devstate_wait(gc, &aodev->backend_ds, + device_backend_callback, state_path, XenbusStateClosed, LIBXL_DESTROY_TIMEOUT * 1000); - if (rc) goto out_fail; + if (rc) { + LOG(ERROR, "unable to remove device %s", be_path); + goto out; + } - libxl__ao_complete(egc, ao, 0); - return 0; + libxl_dominfo_dispose(&info); + return; - out_fail: - assert(rc); +out: + aodev->rc = rc; + libxl_dominfo_dispose(&info); libxl__xs_transaction_abort(gc, &t); - device_remove_cleanup(gc, aorm); - return rc; + device_hotplug_done(egc, aodev); + return; +} + +static void device_qemu_timeout(libxl__egc *egc, libxl__ev_time *ev, + const struct timeval *requested_abs) +{ + libxl__ao_device *aodev = CONTAINER_OF(ev, *aodev, timeout); + STATE_AO_GC(aodev->ao); + char *be_path = libxl__device_backend_path(gc, aodev->dev); + char *state_path = GCSPRINTF("%s/state", be_path); + int rc = 0; + + libxl__ev_time_deregister(gc, &aodev->timeout); + + rc = libxl__xs_write_checked(gc, XBT_NULL, state_path, "6"); + if (rc) goto out; + +out: + aodev->rc = rc; + device_hotplug_done(egc, aodev); } -static void device_remove_callback(libxl__egc *egc, libxl__ev_devstate *ds, +static void device_backend_callback(libxl__egc *egc, libxl__ev_devstate *ds, int rc) { - libxl__ao_device_remove *aorm = CONTAINER_OF(ds, *aorm, ds); - libxl__gc *gc = &aorm->ao->gc; - libxl__ao_complete(egc, aorm->ao, rc); - device_remove_cleanup(gc, aorm); + libxl__ao_device *aodev = CONTAINER_OF(ds, *aodev, backend_ds); + STATE_AO_GC(aodev->ao); + + device_backend_cleanup(gc, aodev); + + if (rc == ERROR_TIMEDOUT && aodev->action == DEVICE_DISCONNECT && + !aodev->force) { + aodev->force = 1; + libxl__initiate_device_remove(egc, aodev); + return; + } + + if (rc) { + LOG(ERROR, "unable to disconnect device with path %s", + libxl__device_backend_path(gc, aodev->dev)); + goto out; + } + +out: + aodev->rc = rc; + device_hotplug_done(egc, aodev); + return; } -static void device_remove_cleanup(libxl__gc *gc, - libxl__ao_device_remove *aorm) { - if (!aorm) return; - libxl__ev_devstate_cancel(gc, &aorm->ds); +static void device_backend_cleanup(libxl__gc *gc, libxl__ao_device *aodev) +{ + if (!aodev) return; + libxl__ev_devstate_cancel(gc, &aodev->backend_ds); +} + +static void device_hotplug_done(libxl__egc *egc, libxl__ao_device *aodev) +{ + STATE_AO_GC(aodev->ao); + char *be_path = libxl__device_backend_path(gc, aodev->dev); + char *fe_path = libxl__device_frontend_path(gc, aodev->dev); + xs_transaction_t t = 0; + int rc; + + if (aodev->action == DEVICE_DISCONNECT) { + for (;;) { + rc = libxl__xs_transaction_start(gc, &t); + if (rc) goto out; + + libxl__xs_path_cleanup(gc, t, fe_path); + libxl__xs_path_cleanup(gc, t, be_path); + + rc = libxl__xs_transaction_commit(gc, &t); + if (!rc) break; + if (rc < 0) goto out; + } + } + +out: + aodev->callback(egc, aodev); + return; } int libxl__wait_for_device_model(libxl__gc *gc, diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h index 2781398be4..5d985ff9aa 100644 --- a/tools/libxl/libxl_internal.h +++ b/tools/libxl/libxl_internal.h @@ -74,6 +74,7 @@ #define LIBXL_DESTROY_TIMEOUT 10 #define LIBXL_DEVICE_MODEL_START_TIMEOUT 10 +#define LIBXL_QEMU_BODGE_TIMEOUT 2 #define LIBXL_XENCONSOLE_LIMIT 1048576 #define LIBXL_XENCONSOLE_PROTOCOL "vt100" #define LIBXL_MAXMEM_CONSTANT 1024 @@ -350,6 +351,12 @@ typedef struct { libxl__device_kind kind; } libxl__device; +/* Used to know if backend of given device is QEMU */ +#define QEMU_BACKEND(dev) (\ + (dev)->backend_kind == LIBXL__DEVICE_KIND_QDISK || \ + (dev)->backend_kind == LIBXL__DEVICE_KIND_VFB || \ + (dev)->backend_kind == LIBXL__DEVICE_KIND_VKBD) + #define XC_PCI_BDF "0x%x, 0x%x, 0x%x, 0x%x" #define PCI_DEVFN(slot, func) ((((slot) & 0x1f) << 3) | ((func) & 0x07)) #define PCI_SLOT(devfn) (((devfn) >> 3) & 0x1f) @@ -899,13 +906,6 @@ _hidden const char *libxl__device_nic_devname(libxl__gc *gc, uint32_t devid, libxl_nic_type type); -/* Arranges that dev will be removed from its guest. When - * this is done, the ao will be completed. An error - * return from libxl__initiate_device_remove means that the ao - * will _not_ be completed and the caller must do so. */ -_hidden int libxl__initiate_device_remove(libxl__egc*, libxl__ao*, - libxl__device *dev); - /* * libxl__ev_devstate - waits a given time for a device to * reach a given state. Follows the libxl_ev_* conventions. @@ -2007,6 +2007,135 @@ _hidden void libxl__bootloader_init(libxl__bootloader_state *bl); * If callback is passed rc==0, will have updated st->info appropriately */ _hidden void libxl__bootloader_run(libxl__egc*, libxl__bootloader_state *st); +/*----- device addition/removal -----*/ + +/* Action to perform (either connect or disconnect) */ +typedef enum { + DEVICE_CONNECT, + DEVICE_DISCONNECT +} libxl__device_action; + +typedef struct libxl__ao_device libxl__ao_device; +typedef void libxl__device_callback(libxl__egc*, libxl__ao_device*); + +/* This functions sets the necessary libxl__ao_device struct values to use + * safely inside functions. It marks the operation as "active" + * since we need to be sure that all device status structs are set + * to active before start queueing events, or we might call + * ao_complete before all devices had finished + * + * libxl__initiate_device_{remove/addition} should not be called without + * calling libxl__prepare_ao_device first, since it initializes the private + * fields of the struct libxl__ao_device to what this functions expect. + * + * Once _prepare has been called on a libxl__ao_device, it is safe to just + * discard this struct, there's no need to call any destroy function. + * _prepare can also be called multiple times with the same libxl__ao_device. + */ +_hidden void libxl__prepare_ao_device(libxl__ao *ao, libxl__ao_device *aodev); + +struct libxl__ao_device { + /* filled in by user */ + libxl__ao *ao; + libxl__device_action action; + libxl__device *dev; + int force; + libxl__device_callback *callback; + /* private for implementation */ + int rc; + libxl__ev_devstate backend_ds; + /* Bodge for Qemu devices */ + libxl__ev_time timeout; +}; + +/* + * Algorithm for handling device removal (including domain + * destruction). This is somewhat subtle because we may already have + * killed the domain and caused the death of qemu. + * + * In current versions of qemu there is no mechanism for ensuring that + * the resources used by its devices (both emulated and any PV devices + * provided by qemu) are freed (eg, fds closed) before it shuts down, + * and no confirmation from a terminating qemu back to the toolstack. + * + * This will need to be fixed in Xen 4.3. In the meantime (Xen 4.2) + * we implement a bodge. + * + * WE WANT TO UNPLUG WE WANT TO SHUT DOWN OR DESTROY + * | | + * | LIBXL SENDS SIGHUP TO QEMU + * | .....................|........................ + * | : XEN 4.3+ PLANNED | : + * | : QEMU TEARS DOWN ALL DEVICES : + * | : FREES RESOURCES (closing fds) : + * | : SETS PV BACKENDS TO STATE 5, : + * | : waits for PV frontends to shut down : + * | : SETS PV BACKENDS TO STATE 6 : + * | : | : + * | : QEMU NOTIFIES TOOLSTACK (via : + * | : xenstore) that it is exiting : + * | : QEMU EXITS (parent may be init) : + * | : | : + * | : TOOLSTACK WAITS FOR QEMU : + * | : notices qemu has finished : + * | :....................|.......................: + * | .--------------------' + * V V + * for each device + * we want to unplug/remove + * ..................|........................................... + * : V XEN 4.2 RACY BODGE : + * : device is provided by qemu : + * : | `-----------. : + * : something| V : + * : else, eg| domain (that is domain for which : + * : blkback| this PV device is the backend, : + * : | which might be the stub dm) : + * : | is still alive? : + * : | | | : + * : | |alive |dead : + * : |<-----------------' | : + * : | hopefully qemu is | : + * : | still running | : + * :............|................. | : + * ,----->| : we may be racing : + * | backend state? : with qemu's death : + * ^ | | : | : + * xenstore| |other |6 : WAIT 2.0s : + * conflict| | | : TIMEOUT : + * | WRITE B.E. | : | : + * | STATE:=5 | : hopefully qemu has : + * `---' | | : gone by now and : + * |ok | : freed its resources : + * | | : | : + * WAIT FOR | : SET B.E. : + * STATE==6 | : STATE:=6 : + * / | | :..........|...................: + * timeout/ ok| | | + * / | | | + * | RUN HOTPLUG <-'<----------------' + * | SCRIPT + * | | + * `---> NUKE + * BACKEND + * | + * DONE. + */ + +/* 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 + * aodev->callback will be called. + * + * 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__initiate_device_remove(libxl__egc *egc, + libxl__ao_device *aodev); + /*----- Domain creation -----*/ typedef struct libxl__domain_create_state libxl__domain_create_state; diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c index 84909fff1d..3b03e5d928 100644 --- a/tools/libxl/xl_cmdimpl.c +++ b/tools/libxl/xl_cmdimpl.c @@ -5415,7 +5415,7 @@ int main_blockdetach(int argc, char **argv) if (libxl_device_disk_remove(ctx, domid, &disk, 0)) { fprintf(stderr, "libxl_device_disk_remove failed.\n"); } else - libxl_device_disk_destroy(ctx, domid, &disk); + libxl_device_disk_destroy(ctx, domid, &disk, 0); return 0; } diff --git a/tools/ocaml/libs/xl/xenlight_stubs.c b/tools/ocaml/libs/xl/xenlight_stubs.c index c712b2bd01..53751b13a9 100644 --- a/tools/ocaml/libs/xl/xenlight_stubs.c +++ b/tools/ocaml/libs/xl/xenlight_stubs.c @@ -351,7 +351,7 @@ value stub_xl_device_vkb_destroy(value info, value domid) device_vkb_val(&gc, &lg, &c_info, info); INIT_CTX(); - ret = libxl_device_vkb_destroy(ctx, Int_val(domid), &c_info); + ret = libxl_device_vkb_destroy(ctx, Int_val(domid), &c_info, 0); if (ret != 0) failwith_xl("vkb_hard_shutdown", &lg); FREE_CTX(); @@ -405,7 +405,7 @@ value stub_xl_device_vfb_destroy(value info, value domid) device_vfb_val(&gc, &lg, &c_info, info); INIT_CTX(); - ret = libxl_device_vfb_destroy(ctx, Int_val(domid), &c_info); + ret = libxl_device_vfb_destroy(ctx, Int_val(domid), &c_info, 0); if (ret != 0) failwith_xl("vfb_hard_shutdown", &lg); FREE_CTX(); |