[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH 9/9] libxl: Convert to asynchronous: device removal



On Fri, 2012-01-13 at 19:25 +0000, Ian Jackson wrote:
> Convert libxl_FOO_device_remove, and the function which does the bulk
> of the work, libxl__device_remove, to the new async ops scheme.
> 
> Adjust all callers.
> 
> Also remove libxl__wait_for_device_state which is now obsolete.
> 
> Signed-off-by: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
> ---
>  tools/libxl/libxl.c          |   60 +++++++++++++--------
>  tools/libxl/libxl.h          |   16 ++++--
>  tools/libxl/libxl_device.c   |  118 
> +++++++++++++-----------------------------
>  tools/libxl/libxl_internal.h |   30 ++---------
>  tools/libxl/xl_cmdimpl.c     |    4 +-
>  5 files changed, 93 insertions(+), 135 deletions(-)
> 
> diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
> index 9890d79..d63da97 100644
> --- a/tools/libxl/libxl.c
> +++ b/tools/libxl/libxl.c
> @@ -1310,19 +1310,23 @@ out:
>  }
> 
>  int libxl_device_disk_remove(libxl_ctx *ctx, uint32_t domid,
> -                             libxl_device_disk *disk)
> +                             libxl_device_disk *disk,
> +                             const libxl_asyncop_how *ao_how)
>  {
> -    GC_INIT(ctx);
> +    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__device_remove(gc, &device, 1);
> +    rc = libxl__initiate_device_remove(ao, &device);
> +    if (rc) goto out;
> +
> +    AO_INPROGRESS;
> +
>  out:
> -    GC_FREE;
> -    return rc;
> +    AO_ABORT(rc);
>  }

After all the internal complexity the actual usage is refreshingly
simple. Phew!

> 
>  int libxl_device_disk_destroy(libxl_ctx *ctx, uint32_t domid,
> @@ -1536,11 +1540,11 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t 
> domid, libxl_device_disk *disk)
> 
>      ret = 0;
> 
> -    libxl_device_disk_remove(ctx, domid, disks + i);
> +    libxl_device_disk_remove(ctx, domid, disks + i, 0);
>      libxl_device_disk_add(ctx, domid, disk);
>      stubdomid = libxl_get_stubdom_id(ctx, domid);
>      if (stubdomid) {
> -        libxl_device_disk_remove(ctx, stubdomid, disks + i);
> +        libxl_device_disk_remove(ctx, stubdomid, disks + i, 0);
>          libxl_device_disk_add(ctx, stubdomid, disk);
>      }
>  out:

The async capability here ought to be propagated to the
libxl_cdrom_insert interface too. I guess that would mean handling
compound asynchronous operations.

...in the fullness of time, of course.


> diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
> index 416d6e8..602bd01 100644
> --- a/tools/libxl/libxl.h
> +++ b/tools/libxl/libxl.h

> diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
> index 5d05e90..e905133 100644
> --- a/tools/libxl/libxl_device.c
> +++ b/tools/libxl/libxl_device.c
> @@ -357,85 +357,41 @@ int libxl__device_disk_dev_number(const char *virtpath, 
> int *pdisk,
>      return -1;
>  }
> 
[...]
> +typedef struct {
> +    libxl__ao *ao;
> +    libxl__ev_devstate ds;
> +} libxl__ao_device_remove;
> +
> +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_remove_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);
>  }
> 
[...]
> +int libxl__initiate_device_remove(libxl__ao *ao, libxl__device *dev)
>  {
> +    /* Arranges that dev will be removed from its guest.  When
> +     * this is done, the ao will be completed.  An error
> +     * return from libxl__device_remove means that the ao
> +     * will _not_ be completed and the caller must do so.

Do you mean aborted or cancelled rather than completed here?

> +     */
> +    AO_GC;
>      libxl_ctx *ctx = libxl__gc_owner(gc);
>      xs_transaction_t t;
>      char *be_path = libxl__device_backend_path(gc, dev);
>      char *state_path = libxl__sprintf(gc, "%s/state", be_path);
>      char *state = libxl__xs_read(gc, XBT_NULL, state_path);
>      int rc = 0;
> +    libxl__ao_device_remove *aorm = 0;
> 
>      if (!state)
>          goto out;
> @@ -458,23 +414,21 @@ retry_transaction:
>          }
>      }
> 
[...]
>      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,
> +                                 state_path, XenbusStateClosed,
> +                                 LIBXL_DESTROY_TIMEOUT * 1000);
> +    if (rc) goto out;
> +
> +    return 0;
> +
> + out:
> +    device_remove_cleanup(gc, aorm);
>      return rc;
>  }
> 
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index b7f0f54..9920fb9 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -653,35 +653,15 @@ _hidden char *libxl__device_backend_path(libxl__gc *gc, 
> libxl__device *device);
[...]
> +/* Arranges that dev will be removed from its guest.  When
> + * this is done, the ao will be completed.  An error
> + * return from libxl__device_remove means that the ao
> + * will _not_ be completed and the caller must do so. */

This is the same comment as at the head of the implementation so the
same comment re aborting applies. Do we need both comments?

> +_hidden int libxl__initiate_device_remove(libxl__ao*, libxl__device *dev);
> 
>  /*
>   * libxl__ev_devstate - waits a given time for a device to
> diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
> index c2b7a1e..659a9e6 100644
> --- a/tools/libxl/xl_cmdimpl.c
> +++ b/tools/libxl/xl_cmdimpl.c
> @@ -4624,7 +4624,7 @@ int main_networkdetach(int argc, char **argv)
>              return 1;
>          }
>      }
> -    if (libxl_device_nic_remove(ctx, domid, &nic)) {
> +    if (libxl_device_nic_remove(ctx, domid, &nic, 0)) {
>          fprintf(stderr, "libxl_device_nic_del failed.\n");
>          return 1;
>      }

There aren't actually any examples of a caller using the ao-ness in xl
are there?

I know that sync is for the most part ao+wait but I'm a bit concerned
that e.g. several of the paths in libxl__ao_complete probably haven't
been run and one of the flow-charts added to tools/libxl/libxl_event.c
in patch 6/8 has probably never happened either.

IMHO this isn't a blocker for this patch but since xl is, in addition to
being a toolstack, a testbed for libxl perhaps one or more "gratuitously
asynchronous" calls could be made? Perhaps the libxl_cdrom_insert case
would be an interesting one? In particular the case in the
create_domain() event loop (e.g. so that the response to a cdrom eject
does not block shutdown processing).

Ian.



_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.