|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH V5 32/32] libxl: synchronize configuration when we plug / unplug device
On Tue, 2014-05-13 at 22:54 +0100, Wei Liu wrote:
> We synchronize domain configuration in the callback, right before we
> return to caller. We depends solely on the return value of AO to
> determine if AO is successful.
>
> This approach cannot deal with half-baked device state (say, if AO
> returns success but for various reasons other parts just fail and we
> have some xenstore entries written / resource allocated). However we
> cannot make thing worse as the original code cannot handle that either.
> The good side of this approach is that in the future we can compare the
> stored configuration and xenstore entries to spot any half-baked device
> state so it can help fix that issue in the future.
>
> Signed-off-by: Wei Liu <wei.liu2@xxxxxxxxxx>
This looks broadly sensible to me, but I generally defer to Ian J on
anything involving the ao machinery...
> ---
> tools/libxl/libxl.c | 152
> +++++++++++++++++++++++++++++++++++-------
> tools/libxl/libxl_internal.h | 2 +
> 2 files changed, 129 insertions(+), 25 deletions(-)
>
> diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
> index f93096b..a7bf0a4 100644
> --- a/tools/libxl/libxl.c
> +++ b/tools/libxl/libxl.c
> @@ -1794,29 +1794,6 @@ out:
>
>
> /******************************************************************************/
>
> -/* 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",
> - libxl__device_action_to_string(aodev->action),
> - libxl__device_kind_to_string(aodev->dev->kind),
> - aodev->dev->devid);
> - } else {
> - LOG(ERROR, "unable to %s device",
> - libxl__device_action_to_string(aodev->action));
> - }
> - goto out;
> - }
> -
> -out:
> - libxl__ao_complete(egc, ao, aodev->rc);
> - return;
> -}
> -
> /* common function to get next device id */
> static int libxl__device_nextid(libxl__gc *gc, uint32_t domid, char *device)
> {
> @@ -3548,6 +3525,126 @@ out:
> } \
> libxl_domain_config_dispose(&d_config); \
>
> +static void device_nic_fixup(libxl_ctx *ctx, libxl_device_nic *dst,
> + libxl_device_nic *src)
> +{
> + dst->devid = src->devid;
> + libxl_mac_copy(ctx, &dst->mac, &src->mac);
> +}
> +
> +static void device_vtpm_fixup(libxl_ctx *ctx, libxl_device_vtpm *dst,
> + libxl_device_vtpm *src)
> +{
> + libxl_uuid_copy(ctx, &dst->uuid, &src->uuid);
> +}
> +
> +static void device_disk_fixup(libxl_ctx *ctx, libxl_device_disk *dst,
> + libxl_device_disk *src)
> +{
> +}
> +
> +#define DEVICE_AO_FAILED_MSG \
> + do { \
> + if (aodev->dev) { \
> + LOG(ERROR, "unable to %s %s with id %u", \
> + libxl__device_action_to_string(aodev->action), \
> + libxl__device_kind_to_string(aodev->dev->kind), \
> + aodev->dev->devid); \
> + } else { \
> + LOG(ERROR, "unable to %s device", \
> + libxl__device_action_to_string(aodev->action)); \
> + } \
> + } while (0)
> +
> +
> +#define DEFINE_DEVICE_ADD_AOCOMPLETE(type,ptr,cnt) \
> + static void device_add_##type##_aocomplete(libxl__egc *egc, \
> + libxl__ao_device *aodev) \
> + { \
> + STATE_AO_GC(aodev->ao); \
> + int rc; \
> + \
> + if (aodev->rc) { \
> + DEVICE_AO_FAILED_MSG; \
> + goto out; \
> + } else { \
> + libxl_device_##type *p; \
> + \
> + LOAD_DOMAIN_CONFIG(aodev->dev->domid); \
> + \
> + d_config.ptr = \
> + libxl__realloc(gc, d_config.ptr, \
> + (d_config.cnt + 1) * \
> + sizeof(libxl_device_##type)); \
> + p = &d_config.ptr[d_config.cnt]; \
> + d_config.cnt++; \
> + \
> + libxl_device_##type##_copy(CTX, p, aodev->pdev_copy); \
> + \
> + device_##type##_fixup(CTX, p, aodev->pdev); \
> + \
> + STORE_DOMAIN_CONFIG(aodev->dev->domid); \
> + } \
> + \
> + out: \
> + /* Dispose our internal copy, which is allocated at the entry of \
> + * this AO. */ \
> + libxl_device_##type##_dispose(aodev->pdev_copy); \
> + libxl__ao_complete(egc, ao, aodev->rc); \
> + return; \
> + }
> +
> +DEFINE_DEVICE_ADD_AOCOMPLETE(nic, nics, num_nics);
> +DEFINE_DEVICE_ADD_AOCOMPLETE(vtpm, vtpms, num_vtpms);
> +DEFINE_DEVICE_ADD_AOCOMPLETE(disk, disks, num_disks);
> +
> +#define COMPARE_DEVID(a, b) ((a)->devid == (b)->devid)
> +#define COMPARE_DISK(a, b) (!strcmp((a)->vdev, (b)->vdev))
> +
> +#define DEFINE_DEVICE_RM_AOCOMPLETE(type,ptr,cnt,compare) \
> + static void device_rm_##type##_aocomplete(libxl__egc *egc, \
> + libxl__ao_device *aodev) \
> + { \
> + STATE_AO_GC(aodev->ao); \
> + int rc; \
> + \
> + if (aodev->rc) { \
> + DEVICE_AO_FAILED_MSG; \
> + goto out; \
> + } else { \
> + int i, j; \
> + libxl_device_##type *p = aodev->pdev; \
> + LOAD_DOMAIN_CONFIG(aodev->dev->domid); \
> + \
> + for (i = j = 0; i < d_config.cnt; i++) { \
> + if (!compare(&d_config.ptr[i], p)) { \
> + if (i != j) { \
> + libxl_device_##type##_dispose(&d_config.ptr[j]);\
> + d_config.ptr[j] = d_config.ptr[i]; \
> + } \
> + j++; \
> + } \
> + } \
> + \
> + d_config.ptr = \
> + libxl__realloc(gc, d_config.ptr, \
> + j * sizeof(libxl_device_##type)); \
> + d_config.cnt = j; \
> + \
> + STORE_DOMAIN_CONFIG(aodev->dev->domid); \
> + } \
> + \
> + out: \
> + libxl__ao_complete(egc, ao, aodev->rc); \
> + return; \
> + }
> +
> +DEFINE_DEVICE_RM_AOCOMPLETE(nic, nics, num_nics, COMPARE_DEVID);
> +DEFINE_DEVICE_RM_AOCOMPLETE(vtpm, vtpms, num_vtpms, COMPARE_DEVID);
> +DEFINE_DEVICE_RM_AOCOMPLETE(disk, disks, num_disks, COMPARE_DISK);
> +DEFINE_DEVICE_RM_AOCOMPLETE(vkb, vkbs, num_vkbs, COMPARE_DEVID);
> +DEFINE_DEVICE_RM_AOCOMPLETE(vfb, vfbs, num_vfbs, COMPARE_DEVID);
> +
> /* Macro for defining device remove/destroy functions in a compact way */
> /* The following functions are defined:
> * libxl_device_disk_remove
> @@ -3577,9 +3674,11 @@ out:
> \
> GCNEW(aodev); \
> libxl__prepare_ao_device(ao, aodev); \
> + aodev->pdev = type; \
> + aodev->pdev_copy = NULL; /* unused */ \
> aodev->action = LIBXL__DEVICE_ACTION_REMOVE; \
> aodev->dev = device; \
> - aodev->callback = device_addrm_aocomplete; \
> + aodev->callback = device_rm_##type##_aocomplete; \
> aodev->force = f; \
> libxl__initiate_device_remove(egc, aodev); \
> \
> @@ -3631,8 +3730,11 @@ DEFINE_DEVICE_REMOVE(vtpm, destroy, 1)
> libxl__ao_device *aodev; \
> \
> GCNEW(aodev); \
> + aodev->pdev = type; \
> + aodev->pdev_copy = libxl__zalloc(gc, sizeof(*type)); \
> + libxl_device_##type##_copy(CTX, aodev->pdev_copy, aodev->pdev); \
> libxl__prepare_ao_device(ao, aodev); \
> - aodev->callback = device_addrm_aocomplete; \
> + aodev->callback = device_add_##type##_aocomplete; \
> libxl__device_##type##_add(egc, domid, type, aodev); \
> \
> return AO_INPROGRESS; \
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index 21bb774..06503df 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -2106,6 +2106,8 @@ struct libxl__ao_device {
> const char *what;
> int num_exec;
> libxl__ev_child child;
> + void *pdev; /* pointer to libxl_device_nic/vtpm/disk etc. */
> + void *pdev_copy; /* a copy of vanilla structure pointed to by pdev. */
> };
>
> /*
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |