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

Re: [Xen-devel] [PATCH v6 1/2] libxl: Introduce functions to add and remove USB devices to an HVM guest



On Wed, 2013-04-24 at 14:32 +0100, George Dunlap wrote:
> On 24/04/13 13:38, Ian Campbell wrote:
> > I didn't see an implementation of libxl__device_usb_setdefault?
> 
> You mean, for the internal structure?

No, for the external structure, but called only internally in libxl.

>From libxl_internal.h:

/*
 * For each aggregate type which can be used as an input we provide:
 *
 * int libxl__<type>_setdefault(gc, <type> *p):
 *
 *     Idempotently sets any members of "p" which is currently set to
 *     a special value indicating that the defaults should be used
 *     (per libxl_<type>_init) to a specific value.
 *
 *     All libxl API functions are expected to have arranged for this
 *     to be called before using any values within these structures.
 */

> 
> >
> > On Fri, 2013-04-19 at 16:59 +0100, George Dunlap wrote:
> >>       xs_write(ctx->xsh, t, libxl__sprintf(gc, "%s/vm", dom_path), 
> >> vm_path, strlen(vm_path));
> >>       rc = libxl__domain_rename(gc, *domid, 0, info->name, t);
> >>       if (rc)
> >> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> >> index 3ba3a21..d2e00fa 100644
> >> --- a/tools/libxl/libxl_internal.h
> >> +++ b/tools/libxl/libxl_internal.h
> >> @@ -1412,6 +1412,24 @@ _hidden int libxl__qmp_save(libxl__gc *gc, int 
> >> domid, const char *filename);
> >>   /* Set dirty bitmap logging status */
> >>   _hidden int libxl__qmp_set_global_dirty_log(libxl__gc *gc, int domid, 
> >> bool enable);
> >>   _hidden int libxl__qmp_insert_cdrom(libxl__gc *gc, int domid, const 
> >> libxl_device_disk *disk);
> >> +/* Same as normal, but "translated" */
> > You can use the IDL to do internal stuff too -- see
> > tools/libxl/libxl_types_internal.idl
> >
> > What does "translated" mean? Which fields and how? Might it be better to
> > include a pointer to the original libxl_device_usb instead of
> > duplicating some/all of these fields?
> 
> I think one of the biggest thing was avoiding having to look up the
> stubdomain in a bunch of different functions -- that's the dm_domid.

Yet you look it up in the two exact places that you use it...

> There's also the translation of "AUTO" protocol into PV or HVM, and
> (originally) the translation of BACKEND_DEFAULT into the actual backend
> domain.
> 
> If we were willing to have the library change the protocol in the
> structure passed to it, then a pointer might work as well.

This is normal libxl behaviour, implemented via the setdefault function.

> > If you remove this and pass target_domid as a parameter to various
> > functions (which is the convention in libxl) then the need for this
> > weird internal/external representation goes away.
> 
> There's also the resolution of protocol from ANY into PV or HVM; but if
> we're willing to change the structure passed in by the caller, then yes,
> we can get rid of this struct for now and consider re-introducing it
> if/when we actually need it.

Yes, please just nuke it.

> >> +static int libxl__qmp_usb_hostdev_add(libxl__gc *gc, int domid,
> >> +                                      libxl__device_usb *dev)
> >> +{
> >> +    libxl__json_object *args = NULL;
> >> +    char *id;
> >> +
> >> +    id = GCSPRINTF(HOST_USB_QDEV_ID,
> >> +                   (uint16_t)dev->u.hostdev.hostbus,
> >> +                   (uint16_t)dev->u.hostdev.hostaddr);
> > You could make these uint16 in the IDL if you wanted to restrict it like
> > that. Even without that is the cast really necessary though, given the
> > %x format string?
> >
> > If you do use uint16_t then you probably want to use PRIx16 too.
> 
> This actually a vestigial artifact from the fact that you could
> originally specify ANY in the field, which was encoded as -1.  I'll just
> take out now.

OK. BTW I saw some others that I didn't comment on, so you may want to
grep around a bit.

> 
> >> +
> >> +    qmp_parameters_add_string(gc, &args, "driver", "usb-host");
> >> +    QMP_PARAMETERS_SPRINTF(&args, "hostbus", "0x%x", 
> >> dev->u.hostdev.hostbus);
> >> +    QMP_PARAMETERS_SPRINTF(&args, "hostaddr", "0x%x", 
> >> dev->u.hostdev.hostaddr);
> >> +
> >> +    qmp_parameters_add_string(gc, &args, "id", id);
> >> +
> >> +    return qmp_run_command(gc, domid, "device_add", args, NULL, NULL);
> >> +}
> >> +
> >> +int libxl__qmp_usb_add(libxl__gc *gc, int domid, libxl__device_usb 
> >> *usbdev)
> >> +{
> >> +    int rc;
> >> +    switch (usbdev->type) {
> >> +    case LIBXL_DEVICE_USB_TYPE_HOSTDEV:
> > Will this function ever handle anything other than HOSTDEV? AIUI the
> > only other potential type is PV which won't come anywhere near here?
> 
> You're mixing up protocol and device type.  PV will only ever handle
> HOSTDEV types, but qmp allows a wide range of virtual devices: tablets,
> mice, keyboards, thumb drives, &c.  I'd like at some point for all USB
> devices specified in the config file to be able to be listed and
> hot-plugged / hot-unplugged.

Ah, right.

> > (same comments on the remove bits)
> >
> >> diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
> >> index fcb1ecd..3c6a709 100644
> >> --- a/tools/libxl/libxl_types.idl
> >> +++ b/tools/libxl/libxl_types.idl
> >> @@ -408,6 +408,28 @@ libxl_device_vtpm = Struct("device_vtpm", [
> >>       ("uuid",             libxl_uuid),
> >>   ])
> >>
> >> +libxl_device_usb_protocol = Enumeration("usb_protocol", [
> >> +    (0, "AUTO"),
> >> +    (1, "PV"),
> >> +    (2, "DEVICEMODEL"),
> >> +    ])
> >> +
> >> +libxl_device_usb_type = Enumeration("device_usb_type", [
> >> +    (1, "HOSTDEV"),
> >> +    ])
> >> +
> >> +libxl_device_usb = Struct("device_usb", [
> >> +        ("protocol", libxl_device_usb_protocol,
> >> +         {'init_val': 'LIBXL_USB_PROTOCOL_AUTO'}),
> >> +        ("backend_domid", libxl_domid,
> >> +         {'init_val': 'LIBXL_DEVICE_USB_BACKEND_DEFAULT'}),
> >> +        ("u", KeyedUnion(None, libxl_device_usb_type, "type",
> >> +                         [("hostdev", Struct(None, [
> >> +                                ("hostbus",   integer),
> >> +                                ("hostaddr",  integer) ]))
> >> +                          ]))
> >> +    ])
> >> +
> >>   libxl_domain_config = Struct("domain_config", [
> >>       ("c_info", libxl_domain_create_info),
> >>       ("b_info", libxl_domain_build_info),
> > Do you not want to add a list of USB devices to the domain_build_info?
> 
> I don't think I can get that functionality working for 4.3.  It's
> definitely on my plans for the future, though.

It should just be a case of 
        ("usbdevs", Array(libxl_device_usb, "num_usbdevs")),
in the idl and
    for (i = 0; i < d_config->num_usbdevs; i++)
        libxl__device_usb_add(gc, domid, &d_config->usbdevs[i], 1);
in e.g. domcreate_attach_pci (which would then be better named
domcreate_attach_sync_devices or something).

> >
> >> +#define USB_HOSTDEV_ID "hostdev-%04x-%04x"
> >> +
> >> +/*
> >> + * Just use plain numbers for now.  Replace these with strings at some 
> >> point.
> >> + */
> >> +static char * hostdev_xs_path(libxl__gc *gc, uint32_t domid,
> >> +                                    libxl__device_usb *usbdev)
> >> +{
> >> +    return GCSPRINTF(USB_INFO_PATH "/%s",
> >> +                     libxl__xs_libxl_path(gc, domid),
> >> +                     GCSPRINTF(USB_HOSTDEV_ID,
> >> +                               (uint16_t)usbdev->u.hostdev.hostbus,
> >> +                               (uint16_t)usbdev->u.hostdev.hostaddr));
> >> +}
> >> +
> >> +static void hostdev_xs_append_params(libxl__gc *gc, libxl__device_usb 
> >> *usbdev,
> >> +                                  flexarray_t *a)
> >> +{
> >> +    flexarray_append_pair(a, "hostbus",
> >> +                          GCSPRINTF("%d",
> >> +                                    usbdev->u.hostdev.hostbus));
> >> +    flexarray_append_pair(a, "hostaddr",
> >> +                          GCSPRINTF("%d",
> >> +                                    usbdev->u.hostdev.hostaddr));
> > Are the second and third lines > 80 chars in total?
> 
> You mean, "Why did you break the GSPRINTF into two lines?"  Yes, because
> on one line it's > 80 chars.

OK.

> >> +int libxl_device_usb_add(libxl_ctx *ctx, uint32_t domid,
> >> +                         libxl_device_usb *usbdev,
> >> +                         const libxl_asyncop_how *ao_how)
> >> +{
> >> +    AO_CREATE(ctx, domid, ao_how);
> >> +    int rc;
> >> +    rc = libxl__device_usb_add(gc, domid, usbdev);
> >> +    libxl__ao_complete(egc, ao, rc);
> >> +    return AO_INPROGRESS;
> >> +}
> > Please define this (and the remove) using the DEFINE_DEVICE_ADD/REMOVE
> > macros in libxl.c. Not least because I'm not convinced your handling of
> > the AO stuff is correct (or indeed present).
> >
> > This will probably require the libxl__device_usb_add/remove to change to
> > do the AIO stuff too -- i.e. at the end:
> >      aodev->rc = rc;
> >      if (rc) aodev->callback(egc, aodev);
> >      return;
> 
> These follow the template set by
> libxl_pci.c:libxl_device_pci_{add,remove,destroy}(), which were chosen
> specifically because they essentially do a null ASYNC, but
> interface-wise allow for real async to be added in the future.

Ah, OK then.

Ian.


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

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