All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V7 0/7] xen pvusb toolstack work
@ 2015-09-25  2:11 Chunyan Liu
  2015-09-25  2:11 ` [PATCH V7 1/7] libxl: export some functions for pvusb use Chunyan Liu
                   ` (6 more replies)
  0 siblings, 7 replies; 59+ messages in thread
From: Chunyan Liu @ 2015-09-25  2:11 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, wei.liu2, ian.campbell, george.dunlap, Ian.Jackson,
	Chunyan Liu, jfehlig

This patch series is to add pvusb toolstack work, supporting hot add|remove
USB device to|from guest and specify USB device in domain configuration file.

Changes to V6:
* Update libxl API hostbus/hostaddr/idVendor/idProduct type, update API to
  check PV/DEVICEMODEL
* address other comments to V6

V6:
http://lists.xen.org/archives/html/xen-devel/2015-08/msg00750.html

V5:
http://lists.xen.org/archives/html/xen-devel/2015-06/msg04052.html

V4:
http://lists.xenproject.org/archives/html/xen-devel/2015-06/msg01327.html

Related Discussion Threads:
http://www.redhat.com/archives/libvir-list/2014-June/msg00038.html
http://lists.xen.org/archives/html/xen-devel/2014-06/msg00086.html

              <<< pvusb work introduction >>>

1. Overview

There are two general methods for passing through individual host
devices to a guest. The first is via an emulated USB device
controller; the second is PVUSB.

Additionally, there are two ways to add USB devices to a guest: via
the config file at domain creation time, and via hot-plug while the VM
is running.

* Emulated USB

In emulated USB, the device model (qemu) presents an emulated USB
controller to the guest. The device model process then grabs control
of the device from domain 0 and and passes the USB commands between
the guest OS and the host USB device.

This method is only available to HVM domains, and is not available for
domains running with device model stubdomains.

* PVUSB

PVUSB uses a paravirtialized front-end/back-end interface, similar to
the traditional Xen PV network and disk protocols. In order to use
PVUSB, you need usbfront in your guest OS, and usbback in dom0 (or
your USB driver domain).

2. Specifying a host USB device

QEMU qmp commands allows USB devices to be specified either by their
bus address (in the form bus.device) or their device tag (in the form
vendorid:deviceid).

Each way of specifying has its advantages:

    Specifying by device tag will always get the same device,
regardless of where the device ends up in the USB bus topology.
However, if there are two identical devices, it will not allow you to
specify which one.

    Specifying by bus address will always allow you to choose a
specific device, even if you have duplicates. However, the bus address
may change depending on which port you plugged the device into, and
possibly also after a reboot.

To avoid duplication of vendorid:deviceid, we'll use bus address to
specify host USB device in xl toolstack.

You can use lsusb to list the USB devices on the system:

Bus 001 Device 003: ID 0424:2514 Standard Microsystems Corp. USB 2.0
Hub
Bus 003 Device 002: ID f617:0905
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 004: ID 0424:2640 Standard Microsystems Corp. USB 2.0
Hub
Bus 001 Device 005: ID 0424:4060 Standard Microsystems Corp. Ultra
Fast Media Reader
Bus 001 Device 006: ID 046d:c016 Logitech, Inc. Optical Wheel Mouse

To pass through the Logitec mouse, for instance, you could specify
1.6 (remove leading zeroes).

Note: USB hubs can not be assigned to guest.

3. PVUSB toolstack

* Specify USB device in xl config file

You can just specify usb devices, like:
usbdev=['1.6']

Then it will create a USB controller automatically and attach the USB
device to the first available USB controller:port.

or, you can explicitly specify usb controllers and usb devices, like:
usbctrl=['verison=1, ports=4', 'version=2, ports=8', ]
usbdev=['1.6, controller=0, port=1']

Then it will create two USB controllers as you specified.
And if controller and port are specified in usb config, then it will
attach the USB device to that controller:port. About the controller
and port value:
Each USB controller has a index (or called devid) based on 0. The 1st
controller has index 0, the 2nd controller has index 1, ...
Under controller, each port has a port number based on 1. In above
configuration, the 1st controller will have port 1,2,3,4.

* Hot-Plug USB device

To attach a USB device, you should first create a USB controller.
e.g.
xl usb-ctrl-attach domain [version=1|2] [ports=value]
By default, it will create a USB2.0 controller with 8 ports.

Then you could attach a USB device.
e.g.
xl usb-attach domain 1.6 [controller=index port=number]
By default, it will find the 1st available controller:port to attach
the USB device.

You could view USB device status of the domain by usb-list.
e.g.
xl usb-list domain
It will list USB controllers and USB devices under each controller.

You could detach a USB device with usb-detach command.
e.g.
xl usb-detach domain 1.6

You can also remove the whole USB controller by usb-ctrl-detach
command.
e.g.
xl usb-ctrl-detach domain 0
It will remove the USB controller with index 0 and all USB devices
under it.

4. PVUSB Libxl implementation

* usb-ctrl-attach
To create a usb controller, we need:
1) generate usb controler related information
2) write usb controller frontend/backend info to xenstore
PVUSB frontend and backend driver will probe xenstore paths and build
connection between frontend and backend.

* usb-ctrl-detach
To remove a usb controller, we need:
1) check if the usb controller exists or not
2) remove all usb devices under controller
3) remove usb controller info from xenstore

* usb-attach
To attach a usb device, we need:
1) check if the usb device type is assignable
2) check if the usb device is already assigned to a domain
3) add 'busid' of the usb device to xenstore contoller/port/.
   PVUSB driver watches the xenstore changes and detects that,
   and needs to use 'busid' to do following work.
4) unbind usb device from original driver and bind to usbback.
   If usb device has many interfaces, then:
   - unbind each interface from its original driver and bind to usbback.
   - store the original driver to xenstore for later rebinding when
     detaching the device.

* usb-detach
To detach a usb device, we need:
1) check if the usb device is assigned to the domain
2) remove the usb device from xenstore controller/port.
3) unbind usb device from usbback and rebind to its original driver.
   If usb device has many interfaces, do it to each interface.

* usb-list
List all USB controllers and USB devices under each controller.

5. PVUSB xenstore information

PVUSB xenstore information includes three parts: frontend, backend
and /libxl part.

A USB controller is corresponding to a "vusb" device in xenstore.
Adding a USB controller will add a new "vusb" device, removing a
USB controller will delete the related "vusb" device.

Following is an example xenstore values of a USB controller.
Backend:
   backend = ""
    vusb = ""
     1 = ""
      0 = ""
       frontend = "/local/domain/1/device/vusb/0"
       frontend-id = "1"
       online = "1"
       state = "4"
       type = "pv"
       usb-ver = "1"
       num-ports = "4"
       port = ""
        1 = ""
        2 = ""
        3 = ""
        4 = ""

Frontend:
   device = ""
    vusb = ""
     0 = ""
      backend = "/local/domain/0/backend/vusb/1/0"
      backend-id = "0"
      state = "4"
      urb-ring-ref = "348"
      conn-ring-ref = "346"
      event-channel = "20"

Adding a USB device won't create a new "vusb" device, but only write
the USB device busid to one port of USB controller.
For example, attaching a USB device (busid is 2-1.6) to above USB
controller port 1, it only need write 2-1.6 to port 1 of this USB
controller:
Backend:
   backend = ""
    vusb = ""
     1 = ""
      0 = ""
       frontend = "/local/domain/1/device/vusb/0"
       frontend-id = "1"
       online = "1"
       state = "4"
       type = "pv"
       usb-ver = "1"
       num-ports = "4"
       port = ""
        1 = "2-1.6"
        2 = ""
        3 = ""
        4 = ""
Frontend doesn't change.

Since assign a host USB device to guest, we'll unbind USB interfaces
from their original drivers and bind them to usbback. After detaching
this USB device from guest, one would hope the USB interfaces could
be rebind to their original drivers, so there should some place to
get the original driver info. To support that, when attaching a USB
device to guest, we'll save the original driver info in xenstore too,
the place is /libxl/usbback, for example:
libxl = ""
 1 = ""
  dm-version = "qemu_xen"
 usbback = ""
  3-11 = ""
   3-11-1_0 = ""
    driver_path = "/sys/bus/usb/drivers/btusb"

In this example, USB device (busid is 3-11, /sys/bus/usb/devices/3-11).
It has interface 3-11:1.0, whose original dirver is btusb.
Since xenstore doesn't allow ':' and '.' in a key, so we encode the
interface by changing ':' to '-' and changing '.' to '_'.

When detaching the USB device from guest, we can rebind 3-11:1.0 to
btusb driver.

Chunyan Liu (7):
  libxl: export some functions for pvusb use
  libxl_read_file_contents: add new entry to read sysfs file
  libxl: add pvusb API
  libxl: add libxl_device_usb_assignable_list API
  xl: add pvusb commands
  xl: add usb-assignable-list command
  domcreate: support pvusb in configuration file

 docs/man/xl.cfg.pod.5                |   75 ++
 docs/man/xl.pod.1                    |   40 +
 tools/libxl/Makefile                 |    2 +-
 tools/libxl/libxl.c                  |   57 +-
 tools/libxl/libxl.h                  |   81 ++
 tools/libxl/libxl_create.c           |   73 +-
 tools/libxl/libxl_device.c           |    8 +
 tools/libxl/libxl_internal.h         |   33 +-
 tools/libxl/libxl_osdeps.h           |   13 +
 tools/libxl/libxl_pvusb.c            | 1477 ++++++++++++++++++++++++++++++++++
 tools/libxl/libxl_types.idl          |   57 ++
 tools/libxl/libxl_types_internal.idl |    1 +
 tools/libxl/libxl_utils.c            |   68 +-
 tools/libxl/libxl_utils.h            |    5 +
 tools/libxl/xl.h                     |    6 +
 tools/libxl/xl_cmdimpl.c             |  364 ++++++++-
 tools/libxl/xl_cmdtable.c            |   29 +
 17 files changed, 2370 insertions(+), 19 deletions(-)
 create mode 100644 tools/libxl/libxl_pvusb.c

-- 
2.1.4

^ permalink raw reply	[flat|nested] 59+ messages in thread

* [PATCH V7 1/7] libxl: export some functions for pvusb use
  2015-09-25  2:11 [PATCH V7 0/7] xen pvusb toolstack work Chunyan Liu
@ 2015-09-25  2:11 ` Chunyan Liu
  2015-09-25  2:11 ` [PATCH V7 2/7] libxl_read_file_contents: add new entry to read sysfs file Chunyan Liu
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 59+ messages in thread
From: Chunyan Liu @ 2015-09-25  2:11 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, wei.liu2, ian.campbell, george.dunlap, Ian.Jackson,
	Chunyan Liu, jfehlig, Simon Cao

Signed-off-by: Chunyan Liu <cyliu@suse.com>
Signed-off-by: Simon Cao <caobosimon@gmail.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
---
 tools/libxl/libxl.c          | 4 ++--
 tools/libxl/libxl_internal.h | 3 +++
 2 files changed, 5 insertions(+), 2 deletions(-)

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 4d27891..aea4887 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -2006,7 +2006,7 @@ out:
 }
 
 /* common function to get next device id */
-static int libxl__device_nextid(libxl__gc *gc, uint32_t domid, char *device)
+int libxl__device_nextid(libxl__gc *gc, uint32_t domid, char *device)
 {
     char *dompath, **l;
     unsigned int nb;
@@ -2025,7 +2025,7 @@ static int libxl__device_nextid(libxl__gc *gc, uint32_t domid, char *device)
     return nextid;
 }
 
-static int libxl__resolve_domid(libxl__gc *gc, const char *name,
+int libxl__resolve_domid(libxl__gc *gc, const char *name,
                                 uint32_t *domid)
 {
     if (!name)
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 5fa55a7..6ff17f9 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1164,6 +1164,9 @@ _hidden int libxl__init_console_from_channel(libxl__gc *gc,
                                              libxl__device_console *console,
                                              int dev_num,
                                              libxl_device_channel *channel);
+_hidden int libxl__device_nextid(libxl__gc *gc, uint32_t domid, char *device);
+_hidden int libxl__resolve_domid(libxl__gc *gc, const char *name,
+                                 uint32_t *domid);
 
 /*
  * For each aggregate type which can be used as an input we provide:
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH V7 2/7] libxl_read_file_contents: add new entry to read sysfs file
  2015-09-25  2:11 [PATCH V7 0/7] xen pvusb toolstack work Chunyan Liu
  2015-09-25  2:11 ` [PATCH V7 1/7] libxl: export some functions for pvusb use Chunyan Liu
@ 2015-09-25  2:11 ` Chunyan Liu
  2015-09-30 11:22   ` George Dunlap
  2015-10-02 13:25   ` Ian Campbell
  2015-09-25  2:11 ` [PATCH V7 3/7] libxl: add pvusb API Chunyan Liu
                   ` (4 subsequent siblings)
  6 siblings, 2 replies; 59+ messages in thread
From: Chunyan Liu @ 2015-09-25  2:11 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, wei.liu2, ian.campbell, george.dunlap, Ian.Jackson,
	Chunyan Liu, jfehlig

Sysfs file has size=4096 but actual file content is less than that.
Current libxl_read_file_contents will treat it as error when file size
and actual file content differs, so reading sysfs file content with
this function always fails.

Add a new entry libxl_read_sysfs_file_contents to handle sysfs file
specially. It would be used in later pvusb work.

Signed-off-by: Chunyan Liu <cyliu@suse.com>
Reviewed-by: Wei Liu <wei.liu2@citrix.com>
---
Changes:
  - check return value after realloc

 tools/libxl/libxl_internal.h |  2 ++
 tools/libxl/libxl_utils.c    | 52 ++++++++++++++++++++++++++++++++++----------
 2 files changed, 43 insertions(+), 11 deletions(-)

diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 6ff17f9..1a2e483 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -4015,6 +4015,8 @@ void libxl__bitmap_copy_best_effort(libxl__gc *gc, libxl_bitmap *dptr,
 
 int libxl__count_physical_sockets(libxl__gc *gc, int *sockets);
 #endif
+_hidden int libxl_read_sysfs_file_contents(libxl_ctx *ctx, const char *filename,
+                                   void **data_r, int *datalen_r);
 
 /*
  * Local variables:
diff --git a/tools/libxl/libxl_utils.c b/tools/libxl/libxl_utils.c
index bfc9699..72f8f4f 100644
--- a/tools/libxl/libxl_utils.c
+++ b/tools/libxl/libxl_utils.c
@@ -322,8 +322,10 @@ out:
     return rc;
 }
 
-int libxl_read_file_contents(libxl_ctx *ctx, const char *filename,
-                             void **data_r, int *datalen_r) {
+static int libxl_read_file_contents_core(libxl_ctx *ctx, const char *filename,
+                                         void **data_r, int *datalen_r,
+                                         bool tolerate_shrinking_file)
+{
     GC_INIT(ctx);
     FILE *f = 0;
     uint8_t *data = 0;
@@ -359,20 +361,35 @@ int libxl_read_file_contents(libxl_ctx *ctx, const char *filename,
     datalen = stab.st_size;
 
     if (stab.st_size && data_r) {
-        data = malloc(datalen);
+        data = malloc(datalen + 1);
         if (!data) goto xe;
 
-        rs = fread(data, 1, datalen, f);
-        if (rs != datalen) {
-            if (ferror(f))
+        rs = fread(data, 1, datalen + 1, f);
+        if (rs > datalen) {
+            LOG(ERROR, "%s increased size while we were reading it",
+                filename);
+            goto xe;
+        }
+
+        if (rs < datalen) {
+            if (ferror(f)) {
                 LOGE(ERROR, "failed to read %s", filename);
-            else if (feof(f))
-                LOG(ERROR, "%s changed size while we were reading it",
-		    filename);
-            else
+                goto xe;
+            } else if (feof(f)) {
+                if (tolerate_shrinking_file) {
+                    datalen = rs;
+                } else {
+                    LOG(ERROR, "%s shrunk size while we were reading it",
+                        filename);
+                    goto xe;
+                }
+            } else {
                 abort();
-            goto xe;
+            }
         }
+
+        data = realloc(data, datalen);
+        if (!data) goto xe;
     }
 
     if (fclose(f)) {
@@ -396,6 +413,19 @@ int libxl_read_file_contents(libxl_ctx *ctx, const char *filename,
     return e;
 }
 
+int libxl_read_file_contents(libxl_ctx *ctx, const char *filename,
+                             void **data_r, int *datalen_r)
+{
+    return libxl_read_file_contents_core(ctx, filename, data_r, datalen_r, 0);
+}
+
+int libxl_read_sysfs_file_contents(libxl_ctx *ctx, const char *filename,
+                                   void **data_r, int *datalen_r)
+{
+    return libxl_read_file_contents_core(ctx, filename, data_r, datalen_r, 1);
+}
+
+
 #define READ_WRITE_EXACTLY(rw, zero_is_eof, constdata)                    \
                                                                           \
   int libxl_##rw##_exactly(libxl_ctx *ctx, int fd,                 \
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH V7 3/7] libxl: add pvusb API
  2015-09-25  2:11 [PATCH V7 0/7] xen pvusb toolstack work Chunyan Liu
  2015-09-25  2:11 ` [PATCH V7 1/7] libxl: export some functions for pvusb use Chunyan Liu
  2015-09-25  2:11 ` [PATCH V7 2/7] libxl_read_file_contents: add new entry to read sysfs file Chunyan Liu
@ 2015-09-25  2:11 ` Chunyan Liu
  2015-09-30 17:55   ` George Dunlap
  2015-10-08 14:41   ` Ian Jackson
  2015-09-25  2:11 ` [PATCH V7 4/7] libxl: add libxl_device_usb_assignable_list API Chunyan Liu
                   ` (3 subsequent siblings)
  6 siblings, 2 replies; 59+ messages in thread
From: Chunyan Liu @ 2015-09-25  2:11 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, wei.liu2, ian.campbell, george.dunlap, Ian.Jackson,
	Chunyan Liu, jfehlig, Simon Cao

Add pvusb APIs, including:
 - attach/detach (create/destroy) virtual usb controller.
 - attach/detach usb device
 - list usb controllers and usb devices
 - get information of usb controller and usb device
 - some other helper functions

Signed-off-by: Chunyan Liu <cyliu@suse.com>
Signed-off-by: Simon Cao <caobosimon@gmail.com>
---
changes:
  - Update hostbus/hostaddr/idVendor/idProduct types in libxl_types.idl
  - Add PV/DEVICEMODEL check in libxl API, take George's HVM patch series
    for reference.

 tools/libxl/Makefile                 |    2 +-
 tools/libxl/libxl.c                  |   53 ++
 tools/libxl/libxl.h                  |   78 ++
 tools/libxl/libxl_device.c           |    4 +
 tools/libxl/libxl_internal.h         |   20 +-
 tools/libxl/libxl_osdeps.h           |   13 +
 tools/libxl/libxl_pvusb.c            | 1422 ++++++++++++++++++++++++++++++++++
 tools/libxl/libxl_types.idl          |   57 ++
 tools/libxl/libxl_types_internal.idl |    1 +
 tools/libxl/libxl_utils.c            |   16 +
 tools/libxl/libxl_utils.h            |    5 +
 11 files changed, 1669 insertions(+), 2 deletions(-)
 create mode 100644 tools/libxl/libxl_pvusb.c

diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index c5ecec1..ef9ccd3 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -103,7 +103,7 @@ LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \
 			libxl_stream_read.o libxl_stream_write.o \
 			libxl_save_callout.o _libxl_save_msgs_callout.o \
 			libxl_qmp.o libxl_event.o libxl_fork.o \
-			libxl_dom_suspend.o $(LIBXL_OBJS-y)
+			libxl_dom_suspend.o libxl_pvusb.o $(LIBXL_OBJS-y)
 LIBXL_OBJS += libxl_genid.o
 LIBXL_OBJS += _libxl_types.o libxl_flask.o _libxl_types_internal.o
 
diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index aea4887..1e2c63e 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -4192,11 +4192,54 @@ DEFINE_DEVICE_REMOVE(vtpm, destroy, 1)
 
 /******************************************************************************/
 
+/* Macro for defining device remove/destroy functions for usbctrl */
+/* Following functions are defined:
+ * libxl_device_usbctrl_remove
+ * libxl_device_usbctrl_destroy
+ */
+
+#define DEFINE_DEVICE_REMOVE_EXT(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 = LIBXL__DEVICE_ACTION_REMOVE;                    \
+        aodev->dev = device;                                            \
+        aodev->callback = device_addrm_aocomplete;                      \
+        aodev->force = f;                                               \
+        libxl__initiate_device_##type##_remove(egc, aodev);             \
+                                                                        \
+    out:                                                                \
+        if (rc) return AO_CREATE_FAIL(rc);                              \
+        return AO_INPROGRESS;                                           \
+    }
+
+
+DEFINE_DEVICE_REMOVE_EXT(usbctrl, remove, 0)
+DEFINE_DEVICE_REMOVE_EXT(usbctrl, destroy, 1)
+
+#undef DEFINE_DEVICE_REMOVE_EXT
+
+/******************************************************************************/
+
 /* Macro for defining device addition functions in a compact way */
 /* The following functions are defined:
  * libxl_device_disk_add
  * libxl_device_nic_add
  * libxl_device_vtpm_add
+ * libxl_device_usbctrl_add
+ * libxl_device_usb_add
  */
 
 #define DEFINE_DEVICE_ADD(type)                                         \
@@ -4228,6 +4271,12 @@ DEFINE_DEVICE_ADD(nic)
 /* vtpm */
 DEFINE_DEVICE_ADD(vtpm)
 
+/* usbctrl */
+DEFINE_DEVICE_ADD(usbctrl)
+
+/* usb */
+DEFINE_DEVICE_ADD(usb)
+
 #undef DEFINE_DEVICE_ADD
 
 /******************************************************************************/
@@ -6741,6 +6790,10 @@ int libxl_retrieve_domain_configuration(libxl_ctx *ctx, uint32_t domid,
 
     MERGE(pci, pcidevs, COMPARE_PCI, {});
 
+    MERGE(usbctrl, usbctrls, COMPARE_USBCTRL, {});
+
+    MERGE(usb, usbs, COMPARE_USB, {});
+
     /* Take care of removable device. We maintain invariant in the
      * insert / remove operation so that:
      * 1. if xenstore is "empty" while JSON is not, the result
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 5f9047c..633bfc1 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -123,6 +123,12 @@
 #define LIBXL_HAVE_DOMAIN_NODEAFFINITY 1
 
 /*
+ * LIBXL_HAVE_PVUSB indicates functions for plugging in USB devices
+ * through pvusb -- both hotplug and at domain creation time..
+ */
+#define LIBXL_HAVE_PVUSB 1
+
+/*
  * LIBXL_HAVE_BUILDINFO_HVM_VENDOR_DEVICE indicates that the
  * libxl_vendor_device field is present in the hvm sections of
  * libxl_domain_build_info. This field tells libxl which
@@ -1389,6 +1395,78 @@ int libxl_cdrom_insert(libxl_ctx *ctx, uint32_t domid, libxl_device_disk *disk,
                        const libxl_asyncop_how *ao_how)
                        LIBXL_EXTERNAL_CALLERS_ONLY;
 
+/*
+ * USB
+ *
+ * For each device removed or added, one of these protocols is available:
+ * - PV (i.e., PVUSB)
+ * - DEVICEMODEL (i.e, qemu)
+ *
+ * PV is available for either PV or HVM domains.  DEVICEMODEL is only
+ * available for HVM domains.  The caller can additionally specify
+ * "AUTO", in which case the library will try to determine the best
+ * protocol automatically.
+ *
+ * At the moment, the only protocol implemented is PV.
+ *
+ * One can add/remove USB controllers to/from guest, and attach/detach USB
+ * devices to/from USB controllers.
+ *
+ * To add USB controllers and USB devices, one can adding USB controllers
+ * first and then attaching USB devices to some USB controller, or adding
+ * USB devices to guest directly, it will automatically create a USB
+ * controller for USB devices to attach.
+ *
+ * To remove USB controllers or USB devices, one can remove USB devices
+ * under USB controller one by one and then remove USB controller, or
+ * remove USB controller directly, it will remove all USB devices under
+ * it automatically.
+ *
+ */
+/* USB Controllers*/
+int libxl_device_usbctrl_add(libxl_ctx *ctx, uint32_t domid,
+                             libxl_device_usbctrl *usbctrl,
+                             const libxl_asyncop_how *ao_how)
+                             LIBXL_EXTERNAL_CALLERS_ONLY;
+
+int libxl_device_usbctrl_remove(libxl_ctx *ctx, uint32_t domid,
+                                libxl_device_usbctrl *usbctrl,
+                                const libxl_asyncop_how *ao_how)
+                                LIBXL_EXTERNAL_CALLERS_ONLY;
+
+int libxl_device_usbctrl_destroy(libxl_ctx *ctx, uint32_t domid,
+                                 libxl_device_usbctrl *usbctrl,
+                                 const libxl_asyncop_how *ao_how)
+                                 LIBXL_EXTERNAL_CALLERS_ONLY;
+
+libxl_device_usbctrl *libxl_device_usbctrl_list(libxl_ctx *ctx,
+                                                uint32_t domid, int *num);
+
+void libxl_device_usbctrl_list_free(libxl_device_usbctrl *list, int nr);
+
+
+int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid,
+                                 libxl_device_usbctrl *usbctrl,
+                                 libxl_usbctrlinfo *usbctrlinfo);
+
+/* USB Devices */
+int libxl_device_usb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_usb *usb,
+                         const libxl_asyncop_how *ao_how)
+                         LIBXL_EXTERNAL_CALLERS_ONLY;
+
+int libxl_device_usb_remove(libxl_ctx *ctx, uint32_t domid, libxl_device_usb *usb,
+                            const libxl_asyncop_how *ao_how)
+                            LIBXL_EXTERNAL_CALLERS_ONLY;
+
+libxl_device_usb *
+libxl_device_usb_list(libxl_ctx *ctx, uint32_t domid, int *num);
+
+void libxl_device_usb_list_free(libxl_device_usb *list, int nr);
+
+int libxl_device_usb_getinfo(libxl_ctx *ctx, uint32_t domid,
+                             libxl_device_usb *usb,
+                             libxl_usbinfo *usbinfo);
+
 /* Network Interfaces */
 int libxl_device_nic_add(libxl_ctx *ctx, uint32_t domid, libxl_device_nic *nic,
                          const libxl_asyncop_how *ao_how)
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index bee5ed5..935f25b 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -676,6 +676,10 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
                 aodev->action = LIBXL__DEVICE_ACTION_REMOVE;
                 aodev->dev = dev;
                 aodev->force = drs->force;
+                if (dev->backend_kind == LIBXL__DEVICE_KIND_VUSB) {
+                    libxl__initiate_device_usbctrl_remove(egc, aodev);
+                    continue;
+                }
                 libxl__initiate_device_remove(egc, aodev);
             }
         }
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 1a2e483..c433a0d 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -2565,6 +2565,14 @@ _hidden void libxl__device_vtpm_add(libxl__egc *egc, uint32_t domid,
                                    libxl_device_vtpm *vtpm,
                                    libxl__ao_device *aodev);
 
+_hidden void libxl__device_usbctrl_add(libxl__egc *egc, uint32_t domid,
+                                       libxl_device_usbctrl *usbctrl,
+                                       libxl__ao_device *aodev);
+
+_hidden void libxl__device_usb_add(libxl__egc *egc, uint32_t domid,
+                                   libxl_device_usb *usb,
+                                   libxl__ao_device *aodev);
+
 /* Internal function to connect a vkb device */
 _hidden int libxl__device_vkb_add(libxl__gc *gc, uint32_t domid,
                                   libxl_device_vkb *vkb);
@@ -2597,6 +2605,13 @@ _hidden void libxl__wait_device_connection(libxl__egc*,
 _hidden void libxl__initiate_device_remove(libxl__egc *egc,
                                            libxl__ao_device *aodev);
 
+_hidden int libxl__device_from_usbctrl(libxl__gc *gc, uint32_t domid,
+                               libxl_device_usbctrl *usbctrl,
+                               libxl__device *device);
+
+_hidden void libxl__initiate_device_usbctrl_remove(libxl__egc *egc,
+                                                   libxl__ao_device *aodev);
+
 /*
  * libxl__get_hotplug_script_info returns the args and env that should
  * be passed to the hotplug script for the requested device.
@@ -3951,7 +3966,10 @@ static inline void libxl__update_config_vtpm(libxl__gc *gc,
 #define COMPARE_PCI(a, b) ((a)->func == (b)->func &&    \
                            (a)->bus == (b)->bus &&      \
                            (a)->dev == (b)->dev)
-
+#define COMPARE_USB(a, b) ((a)->u.hostdev.hostbus == (b)->u.hostdev.hostbus && \
+                           (a)->u.hostdev.hostaddr == (b)->u.hostdev.hostaddr)
+#define COMPARE_USBCTRL(a, b) ((a)->devid == (b)->devid)
+ 
 /* DEVICE_ADD
  *
  * Add a device in libxl_domain_config structure
diff --git a/tools/libxl/libxl_osdeps.h b/tools/libxl/libxl_osdeps.h
index d9661c9..802c762 100644
--- a/tools/libxl/libxl_osdeps.h
+++ b/tools/libxl/libxl_osdeps.h
@@ -24,6 +24,8 @@
 #define _GNU_SOURCE
 
 #if defined(__NetBSD__)
+#define SYSFS_USB_DEV          "/sys/bus/usb/devices"
+#define SYSFS_USBBACK_DRIVER   "/kern/xen/usb"
 #define SYSFS_PCI_DEV          "/sys/bus/pci/devices"
 #define SYSFS_PCIBACK_DRIVER   "/kern/xen/pci"
 #define NETBACK_NIC_NAME       "xvif%ui%d"
@@ -31,6 +33,8 @@
 #elif defined(__OpenBSD__)
 #include <util.h>
 #elif defined(__linux__)
+#define SYSFS_USB_DEV          "/sys/bus/usb/devices"
+#define SYSFS_USBBACK_DRIVER   "/sys/bus/usb/drivers/usbback"
 #define SYSFS_PCI_DEV          "/sys/bus/pci/devices"
 #define SYSFS_PCIBACK_DRIVER   "/sys/bus/pci/drivers/pciback"
 #define NETBACK_NIC_NAME       "vif%u.%d"
@@ -38,6 +42,8 @@
 #elif defined(__sun__)
 #include <stropts.h>
 #elif defined(__FreeBSD__)
+#define SYSFS_USB_DEV          "/dev/null"
+#define SYSFS_USBBACK_DRIVER   "/dev/null"
 #define SYSFS_PCI_DEV          "/dev/null"
 #define SYSFS_PCIBACK_DRIVER   "/dev/null"
 #define NETBACK_NIC_NAME       "xnb%u.%d"
@@ -45,6 +51,13 @@
 #include <sys/endian.h>
 #endif
 
+#ifndef SYSFS_USBBACK_DRIVER
+#error define SYSFS_USBBACK_DRIVER for your platform
+#endif
+#ifndef SYSFS_USB_DEV
+#error define SYSFS_USB_DEV for your platform
+#endif
+
 #ifndef SYSFS_PCIBACK_DRIVER
 #error define SYSFS_PCIBACK_DRIVER for your platform
 #endif
diff --git a/tools/libxl/libxl_pvusb.c b/tools/libxl/libxl_pvusb.c
new file mode 100644
index 0000000..d4b997f
--- /dev/null
+++ b/tools/libxl/libxl_pvusb.c
@@ -0,0 +1,1422 @@
+/*
+ * Copyright (C) 2015 SUSE LINUX Products GmbH, Nuernberg, Germany.
+ * Author Chunyan Liu <cyliu@suse.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation; version 2.1 only. with the special
+ * exception on linking described in file LICENSE.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Lesser General Public License for more details.
+ */
+
+#include "libxl_osdeps.h" /* must come before any other headers */
+
+#include "libxl_internal.h"
+#include <inttypes.h>
+
+#define USBBACK_INFO_PATH "/libxl/usbback"
+
+#define USBHUB_CLASS_CODE 9
+
+/* Utility to read backend xenstore keys */
+#define READ_BACKEND(tgc, subpath)                                    \
+            libxl__xs_read(tgc, XBT_NULL, GCSPRINTF("%s/" subpath, be_path))
+
+/* Utility to read frontend xenstore keys */
+#define READ_FRONTEND(tgc, subpath)                                   \
+            libxl__xs_read(tgc, XBT_NULL, GCSPRINTF("%s/" subpath, fe_path))
+
+static int libxl__device_usbctrl_setdefault(libxl__gc *gc, uint32_t domid,
+                                            libxl_device_usbctrl *usbctrl)
+{
+    int rc;
+    libxl_domain_type domtype = libxl__domain_type(gc, domid);
+
+    if (!usbctrl->version)
+        usbctrl->version = 2;
+
+    if (!usbctrl->ports)
+        usbctrl->ports = 8;
+
+    if (usbctrl->type == LIBXL_USBCTRL_TYPE_AUTO) {
+        if (domtype == LIBXL_DOMAIN_TYPE_PV) {
+            usbctrl->type = LIBXL_USBCTRL_TYPE_PV;
+        } else if (domtype == LIBXL_DOMAIN_TYPE_HVM) {
+            /* FIXME: See if we can detect PV frontend */
+            usbctrl->type = LIBXL_USBCTRL_TYPE_DEVICEMODEL;
+        }
+    }
+
+    rc = libxl__resolve_domid(gc, usbctrl->backend_domname,
+                              &usbctrl->backend_domid);
+    return rc;
+}
+
+int libxl__device_from_usbctrl(libxl__gc *gc, uint32_t domid,
+                               libxl_device_usbctrl *usbctrl,
+                               libxl__device *device)
+{
+    device->backend_devid   = usbctrl->devid;
+    device->backend_domid   = usbctrl->backend_domid;
+    device->backend_kind    = LIBXL__DEVICE_KIND_VUSB;
+    device->devid           = usbctrl->devid;
+    device->domid           = domid;
+    device->kind            = LIBXL__DEVICE_KIND_VUSB;
+
+    return 0;
+}
+
+/* Add usbctrl information to xenstore.
+ *
+ * Adding a usb controller will add a new 'vusb' device in xenstore, and
+ * add corresponding frontend, backend information to it. According to
+ * "update_json", decide wether to update json config file.
+ */
+static int libxl__device_usbctrl_add_xenstore(libxl__gc *gc, uint32_t domid,
+                                              libxl_device_usbctrl *usbctrl,
+                                              bool update_json)
+{
+    libxl__device *device;
+    flexarray_t *front;
+    flexarray_t *back;
+    xs_transaction_t t = XBT_NULL;
+    int i, rc;
+    libxl_domain_config d_config;
+    libxl_device_usbctrl usbctrl_saved;
+    libxl__domain_userdata_lock *lock = NULL;
+
+    libxl_domain_config_init(&d_config);
+    libxl_device_usbctrl_init(&usbctrl_saved);
+    libxl_device_usbctrl_copy(CTX, &usbctrl_saved, usbctrl);
+
+    GCNEW(device);
+    rc = libxl__device_from_usbctrl(gc, domid, usbctrl, device);
+    if (rc) goto out;
+
+    front = flexarray_make(gc, 4, 1);
+    back = flexarray_make(gc, 12, 1);
+
+    flexarray_append_pair(back, "frontend-id", GCSPRINTF("%d", domid));
+    flexarray_append_pair(back, "online", "1");
+    flexarray_append_pair(back, "state", "1");
+    flexarray_append_pair(back, "type",
+                    (char *)libxl_usbctrl_type_to_string(usbctrl->type));
+    flexarray_append_pair(back, "usb-ver", GCSPRINTF("%d", usbctrl->version));
+    flexarray_append_pair(back, "num-ports", GCSPRINTF("%d", usbctrl->ports));
+    flexarray_append_pair(back, "port", "");
+    for (i = 0; i < usbctrl->ports; i++)
+        flexarray_append_pair(back, GCSPRINTF("port/%d", i + 1), "");
+
+    flexarray_append_pair(front, "backend-id",
+                          GCSPRINTF("%d", usbctrl->backend_domid));
+    flexarray_append_pair(front, "state", "1");
+
+    if (update_json) {
+        lock = libxl__lock_domain_userdata(gc, domid);
+        if (!lock) {
+            rc = ERROR_LOCK_FAIL;
+            goto out;
+        }
+
+        rc = libxl__get_domain_configuration(gc, domid, &d_config);
+        if (rc) goto out;
+
+        DEVICE_ADD(usbctrl, usbctrls, domid, &usbctrl_saved,
+                   COMPARE_USBCTRL, &d_config);
+    }
+
+    for (;;) {
+        rc = libxl__xs_transaction_start(gc, &t);
+        if (rc) goto out;
+
+        rc = libxl__device_exists(gc, t, device);
+        if (rc < 0) goto out;
+        if (rc == 1) {
+            /* already exists in xenstore */
+            LOG(ERROR, "device already exists in xenstore");
+            rc = ERROR_DEVICE_EXISTS;
+            goto out;
+        }
+
+        if (update_json) {
+            rc = libxl__set_domain_configuration(gc, domid, &d_config);
+            if (rc) goto out;
+        }
+
+        libxl__device_generic_add(gc, t, device,
+                          libxl__xs_kvs_of_flexarray(gc, back, back->count),
+                          libxl__xs_kvs_of_flexarray(gc, front, front->count),
+                          NULL);
+
+        rc = libxl__xs_transaction_commit(gc, &t);
+        if (!rc) break;
+        if (rc < 0) goto out;
+    }
+
+out:
+    libxl__xs_transaction_abort(gc, &t);
+    if (lock) libxl__unlock_domain_userdata(lock);
+    libxl_device_usbctrl_dispose(&usbctrl_saved);
+    libxl_domain_config_dispose(&d_config);
+    return rc;
+}
+
+/* AO operation to add a usb controller.
+ *
+ * Generally, it does:
+ * 1) fill in necessary usb controler information with default value
+ * 2) write usb controller frontend/backend info to xenstore, update json
+ *    config file if necessary.
+ * 3) wait for device connection. PVUSB frontend and backend driver will
+ *    probe xenstore paths and build connection between frontend and backend.
+ */
+void libxl__device_usbctrl_add(libxl__egc *egc, uint32_t domid,
+                               libxl_device_usbctrl *usbctrl,
+                               libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+    libxl__device *device;
+    int rc;
+
+    rc = libxl__device_usbctrl_setdefault(gc, domid, usbctrl);
+    if (rc < 0) goto out;
+
+    if (usbctrl->devid == -1) {
+        usbctrl->devid = libxl__device_nextid(gc, domid, "vusb");
+        if (usbctrl->devid < 0) {
+            rc = ERROR_FAIL;
+            goto out;
+        }
+    }
+
+    if (usbctrl->type != LIBXL_USBCTRL_TYPE_PV) {
+        LOG(ERROR, "Unsupported USB controller type");
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    rc = libxl__device_usbctrl_add_xenstore(gc, domid, usbctrl,
+                                            aodev->update_json);
+    if (rc) goto out;
+
+    GCNEW(device);
+    rc = libxl__device_from_usbctrl(gc, domid, usbctrl, device);
+    if (rc) goto out;
+
+    aodev->dev = device;
+    aodev->action = LIBXL__DEVICE_ACTION_ADD;
+    libxl__wait_device_connection(egc, aodev);
+    rc = 0;
+
+out:
+    aodev->rc = rc;
+    if (rc) aodev->callback(egc, aodev);
+    return;
+}
+
+static int
+libxl__device_usb_list_for_usbctrl(libxl__gc *gc, uint32_t domid,
+                                   libxl_devid usbctrl,
+                                   libxl_device_usb **usbs, int *num);
+
+static int
+libxl__device_usb_remove(libxl__gc *gc, uint32_t domid, libxl_device_usb *usb);
+
+/* AO function to remove a usb controller.
+ *
+ * Generally, it does:
+ * 1) check if the usb controller exists or not
+ * 2) remove all usb devices under controller
+ * 3) remove usb controller information from xenstore
+ */
+void libxl__initiate_device_usbctrl_remove(libxl__egc *egc,
+                                           libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+    libxl_ctx *ctx = CTX;
+    libxl_device_usb *usbs = NULL;
+    int numusb = 0;
+    int i, rc;
+    uint32_t domid = ao->domid;
+    int usbctrl_devid = aodev->dev->devid;
+    libxl_device_usbctrl usbctrl;
+    libxl_usbctrlinfo usbctrlinfo;
+
+    libxl_device_usbctrl_init(&usbctrl);
+    libxl_usbctrlinfo_init(&usbctrlinfo);
+
+    rc = libxl_devid_to_device_usbctrl(ctx, domid, usbctrl_devid, &usbctrl);
+    if (rc) goto out;
+
+    rc = libxl_device_usbctrl_getinfo(ctx, domid, &usbctrl, &usbctrlinfo);
+    if (rc) goto out;
+
+    if (usbctrlinfo.type != LIBXL_USBCTRL_TYPE_PV) {
+        LOG(ERROR, "Unsupported USB controller type");
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    /* Remove usb devices first */
+    rc  = libxl__device_usb_list_for_usbctrl(gc, domid, usbctrl_devid,
+                                             &usbs, &numusb);
+    if (rc) goto out;
+
+    for (i = 0; i < numusb; i++) {
+        if (libxl__device_usb_remove(gc, domid, &usbs[i])) {
+            LOG(ERROR, "libxl__device_usb_remove failed");
+            rc = ERROR_FAIL;
+            goto out;
+        }
+    }
+
+    libxl_device_usb_list_free(usbs, numusb);
+
+    /* Remove usbctrl */
+    return libxl__initiate_device_remove(egc, aodev);
+
+out:
+    libxl_device_usbctrl_dispose(&usbctrl);
+    libxl_usbctrlinfo_dispose(&usbctrlinfo);
+    libxl_device_usb_list_free(usbs, numusb);
+    aodev->rc = rc;
+    if (rc) aodev->callback(egc, aodev);
+    return;
+}
+
+libxl_device_usbctrl *
+libxl_device_usbctrl_list(libxl_ctx *ctx, uint32_t domid, int *num)
+{
+    GC_INIT(ctx);
+    libxl_device_usbctrl *usbctrls = NULL;
+    char *path = NULL;
+    char **dir = NULL;
+    unsigned int ndirs = 0;
+
+    *num = 0;
+
+    path = GCSPRINTF("%s/device/vusb",
+                     libxl__xs_get_dompath(gc, domid));
+    dir = libxl__xs_directory(gc, XBT_NULL, path, &ndirs);
+
+    if (dir && ndirs) {
+        usbctrls = libxl__zalloc(NOGC, sizeof(*usbctrls) * ndirs);
+        libxl_device_usbctrl *usbctrl;
+        libxl_device_usbctrl *end = usbctrls + ndirs;
+        for (usbctrl = usbctrls; usbctrl < end; usbctrl++, dir++, (*num)++) {
+            const char *tmp, *be_path;
+            const char *fe_path = GCSPRINTF("%s/%s", path, *dir);
+
+            libxl_device_usbctrl_init(usbctrl);
+            usbctrl->devid = atoi(*dir);
+
+            be_path = READ_FRONTEND(gc, "backend");
+            if (!be_path) goto outerr;
+
+            tmp = READ_FRONTEND(gc, "backend-id");
+            if (!tmp) goto outerr;
+            usbctrl->backend_domid = atoi(tmp);
+
+            tmp = READ_BACKEND(gc, "usb-ver");
+            if (!tmp) goto outerr;
+            usbctrl->version = atoi(tmp);
+
+            tmp = READ_BACKEND(gc, "num-ports");
+            if (!tmp) goto outerr;
+            usbctrl->ports = atoi(tmp);
+
+            tmp = READ_BACKEND(gc, "type");
+            if (!tmp) goto outerr;
+            libxl_usbctrl_type_from_string(tmp, &usbctrl->type);
+        }
+    }
+
+    goto out;
+
+outerr:
+    LOG(ERROR, "Unable to list USB Controllers");
+    libxl_device_usbctrl_list_free(usbctrls, *num);
+    *num = 0;
+    usbctrls = NULL;
+
+out:
+    GC_FREE;
+    return usbctrls;
+}
+
+int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid,
+                                libxl_device_usbctrl *usbctrl,
+                                libxl_usbctrlinfo *usbctrlinfo)
+{
+    GC_INIT(ctx);
+    char *dompath;
+    const char *fe_path, *be_path, *tmp;
+    int rc = 0;
+
+    usbctrlinfo->devid = usbctrl->devid;
+
+    dompath = libxl__xs_get_dompath(gc, domid);
+    fe_path = GCSPRINTF("%s/device/vusb/%d", dompath, usbctrl->devid);
+    be_path = READ_FRONTEND(gc, "backend");
+    if (!be_path) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+    usbctrlinfo->backend = libxl__strdup(NOGC, be_path);
+
+    tmp = READ_FRONTEND(gc, "backend-id");
+    usbctrlinfo->backend_id = tmp ? strtoul(tmp, NULL, 10) : -1;
+
+    tmp = READ_FRONTEND(gc, "state");
+    usbctrlinfo->state = tmp ? strtoul(tmp, NULL, 10) : -1;
+
+    tmp = READ_FRONTEND(gc, "event-channel");
+    usbctrlinfo->evtch = tmp ? strtoul(tmp, NULL, 10) : -1;
+
+    tmp = READ_FRONTEND(gc, "urb-ring-ref");
+    usbctrlinfo->ref_urb = tmp ? strtoul(tmp, NULL, 10) : -1;
+
+    tmp = READ_FRONTEND(gc, "conn-ring-ref");
+    usbctrlinfo->ref_conn = tmp ? strtoul(tmp, NULL, 10) : -1;
+
+    tmp = READ_BACKEND(gc, "frontend");
+    usbctrlinfo->frontend = libxl__strdup(NOGC, tmp);
+
+    tmp = READ_BACKEND(gc, "frontend-id");
+    usbctrlinfo->frontend_id = tmp ? strtoul(tmp, NULL, 10) : -1;
+
+    tmp = READ_BACKEND(gc, "num-ports");
+    usbctrlinfo->ports = tmp ? strtoul(tmp, NULL, 10) : -1;
+
+    tmp = READ_BACKEND(gc, "usb-ver");
+    usbctrlinfo->version = tmp ? strtoul(tmp, NULL, 10) : -1;
+
+    tmp = READ_BACKEND(gc, "type");
+    libxl_usbctrl_type_from_string(tmp, &usbctrlinfo->type);
+
+out:
+    GC_FREE;
+    return rc;
+}
+
+int libxl_devid_to_device_usbctrl(libxl_ctx *ctx,
+                                  uint32_t domid,
+                                  int devid,
+                                  libxl_device_usbctrl *usbctrl)
+{
+    GC_INIT(ctx);
+    libxl_device_usbctrl *usbctrls;
+    int nb = 0;
+    int i, rc = -1;
+
+    usbctrls = libxl_device_usbctrl_list(ctx, domid, &nb);
+    if (!nb) goto out;
+
+    for (i = 0; i < nb; i++) {
+        if (devid == usbctrls[i].devid) {
+            *usbctrl = usbctrls[i];
+            rc = 0;
+            break;
+        }
+    }
+
+    libxl_device_usbctrl_list_free(usbctrls, nb);
+
+out:
+    GC_FREE;
+    return rc;
+}
+
+static char *usb_busaddr_to_busid(libxl__gc *gc, int bus, int addr)
+{
+    libxl_ctx *ctx = CTX;
+    struct dirent *de;
+    DIR *dir;
+    char *busid = NULL;
+
+    assert(bus > 0 && addr > 0);
+
+    if (!(dir = opendir(SYSFS_USB_DEV)))
+        return NULL;
+
+    while ((de = readdir(dir))) {
+        char *filename;
+        void *buf;
+        int busnum = -1;
+        int devnum = -1;
+
+        if (!de->d_name)
+            continue;
+
+        filename = GCSPRINTF(SYSFS_USB_DEV"/%s/devnum", de->d_name);
+        if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
+            sscanf(buf, "%d", &devnum);
+
+        filename = GCSPRINTF(SYSFS_USB_DEV"/%s/busnum", de->d_name);
+        if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
+            sscanf(buf, "%d", &busnum);
+
+        if (bus == busnum && addr == devnum) {
+            busid = libxl__strdup(NOGC, de->d_name);
+            break;
+        }
+    }
+
+    closedir(dir);
+    return busid;
+}
+
+static void usb_busaddr_from_busid(libxl__gc *gc, char *busid,
+                                   uint8_t *bus, uint8_t *addr)
+{
+    libxl_ctx *ctx = CTX;
+    char *filename;
+    void *buf;
+
+    assert(busid);
+
+    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/busnum", busid);
+    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
+        sscanf(buf, "%" SCNu8, bus);
+
+    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/devnum", busid);
+    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
+        sscanf(buf, "%" SCNu8, addr);
+}
+
+static int
+get_assigned_devices(libxl__gc *gc,
+                     libxl_device_usb **list, int *num)
+{
+    char **domlist;
+    unsigned int nd = 0, i, j;
+    libxl_device_usb *usb;
+
+    *list = NULL;
+    *num = 0;
+
+    domlist = libxl__xs_directory(gc, XBT_NULL, "/local/domain", &nd);
+    for (i = 0; i < nd; i++) {
+        char *path, **ctrl_list;
+        unsigned int nc = 0;
+
+        path = GCSPRINTF("/local/domain/%s/device/vusb", domlist[i]);
+        ctrl_list = libxl__xs_directory(gc, XBT_NULL, path, &nc);
+
+        for (j = 0; j < nc; j++) {
+            char *be_path, *num_ports;
+
+            be_path = libxl__xs_read(gc, XBT_NULL,
+                          GCSPRINTF("%s/%s/backend", path, ctrl_list[j]));
+            num_ports = READ_BACKEND(gc, "num-ports");
+            if (num_ports) {
+                int nport = atoi(num_ports), k;
+                char *devpath, *busid;
+
+                for (k = 0; k < nport; k++) {
+                    devpath = GCSPRINTF("%s/port/%d", be_path, k + 1);
+                    busid = libxl__xs_read(gc, XBT_NULL, devpath);
+                    /* If there is USB device attached, add it to list */
+                    if (busid && strcmp(busid, "")) {
+                        GCREALLOC_ARRAY(*list, *num + 1);
+                        usb = *list + *num;
+                        usb->ctrl = atoi(ctrl_list[j]);
+                        usb->port = k + 1;
+                        usb_busaddr_from_busid(gc, busid,
+                                               &usb->u.hostdev.hostbus,
+                                               &usb->u.hostdev.hostaddr);
+                        (*num)++;
+                    }
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
+static bool is_usbdev_in_array(libxl_device_usb *usbs, int num,
+                               libxl_device_usb *usb)
+{
+    int i;
+
+    for (i = 0; i < num; i++) {
+        if (COMPARE_USB(&usbs[i], usb))
+            return true;
+    }
+
+    return false;
+}
+
+/* check if USB device is already assigned to a domain */
+/* check if USB device type is assignable */
+static bool is_usb_assignable(libxl__gc *gc, libxl_device_usb *usb)
+{
+    libxl_ctx *ctx = CTX;
+    int classcode;
+    char *filename;
+    void *buf = NULL;
+    char *busid = NULL;
+
+    assert(usb->u.hostdev.hostbus > 0 && usb->u.hostdev.hostaddr > 0);
+    busid = usb_busaddr_to_busid(gc, usb->u.hostdev.hostbus, usb->u.hostdev.hostaddr);
+
+    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/bDeviceClass", busid);
+    if (libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
+        return false;
+
+    sscanf(buf, "%d", &classcode);
+    return classcode != USBHUB_CLASS_CODE;
+}
+
+/* get usb devices under certain usb controller */
+static int
+libxl__device_usb_list_for_usbctrl(libxl__gc *gc, uint32_t domid,
+                                   libxl_devid usbctrl,
+                                   libxl_device_usb **usbs, int *num)
+{
+    char *fe_path, *be_path, *num_devs;
+    int n, i;
+
+    *usbs = NULL;
+    *num = 0;
+
+    fe_path = GCSPRINTF("%s/device/vusb/%d",
+                        libxl__xs_get_dompath(gc, domid), usbctrl);
+    if (!fe_path)
+        return -1;
+
+    be_path = READ_FRONTEND(gc, "backend");
+    if (!be_path)
+        return -1;
+
+    num_devs = READ_BACKEND(gc, "num-ports");
+    if (!num_devs)
+        return 0;
+
+    n = atoi(num_devs);
+    *usbs = libxl__calloc(NOGC, n, sizeof(libxl_device_usb));
+
+    for (i = 0; i < n; i++) {
+        char *busid;
+        libxl_device_usb *usb = NULL;
+
+        busid = libxl__xs_read(gc, XBT_NULL,
+                               GCSPRINTF("%s/port/%d", be_path, i + 1));
+        if (busid && strcmp(busid, "")) {
+            usb = *usbs + *num;
+            usb->ctrl = usbctrl;
+            usb->port = i + 1;
+            usb_busaddr_from_busid(gc, busid,
+                                   &usb->u.hostdev.hostbus,
+                                   &usb->u.hostdev.hostaddr);
+            (*num)++;
+        }
+    }
+
+    return 0;
+}
+
+/* get all usb devices of the domain */
+libxl_device_usb *
+libxl_device_usb_list(libxl_ctx *ctx, uint32_t domid, int *num)
+{
+    GC_INIT(ctx);
+    char *path;
+    char **usbctrls;
+    unsigned int nc = 0;
+    int i, j;
+    libxl_device_usb *usbs = NULL;
+
+    *num = 0;
+
+    path = GCSPRINTF("%s/device/vusb",
+                        libxl__xs_get_dompath(gc, domid));
+    usbctrls = libxl__xs_directory(gc, XBT_NULL, path, &nc);
+
+    for (i = 0; i < nc; i++) {
+        int nd = 0;
+        libxl_device_usb *tmp = NULL;
+        libxl__device_usb_list_for_usbctrl(gc, domid,
+                                           atoi(usbctrls[i]), &tmp, &nd);
+        if (!nd) continue;
+
+        usbs = libxl__realloc(NOGC, usbs, sizeof(*usbs) * (*num + nd));
+        for (j = 0; j < nd; j++) {
+            usbs[*num] = tmp[j];
+            (*num)++;
+        }
+        libxl_device_usb_list_free(tmp, nd);
+    }
+
+    GC_FREE;
+    return usbs;
+}
+
+/* find first unused controller:port and give that to usb device */
+static int
+libxl__device_usb_set_default_usbctrl(libxl__gc *gc, uint32_t domid,
+                                      libxl_device_usb *usb)
+{
+    libxl_ctx *ctx = CTX;
+    libxl_device_usbctrl *usbctrls = NULL;
+    int numctrl = 0;
+    int i, j, rc = -1;
+
+    usbctrls = libxl_device_usbctrl_list(ctx, domid, &numctrl);
+    if (!numctrl)
+        goto out;
+
+    for (i = 0; i < numctrl; i++) {
+        for (j = 0; j < usbctrls[i].ports; j++) {
+            char *path, *tmp;
+
+            path = GCSPRINTF("%s/backend/vusb/%d/%d/port/%d",
+                             libxl__xs_get_dompath(gc, LIBXL_TOOLSTACK_DOMID),
+                             domid, usbctrls[i].devid, j + 1);
+            tmp = libxl__xs_read(gc, XBT_NULL, path);
+            if (tmp && !strcmp(tmp, "")) {
+                usb->ctrl = usbctrls[i].devid;
+                usb->port = j + 1;
+                rc = 0;
+                goto out;
+            }
+        }
+    }
+
+out:
+    libxl_device_usbctrl_list_free(usbctrls, numctrl);
+    return rc;
+}
+
+/* Fill in usb information with default value.
+ *
+ * Generally, it does:
+ * 1) if "controller" is not specified:
+ *    - if "port" is not specified, try to find an available controller:port,
+ *      if found, use that; otherwise, create a new controller, use this
+ *      controller and its first port
+ *    - if "port" is specified, report error.
+ * 2) if "controller" is specified, but port is not specified:
+ *    try to find an available port under this controller, if found, use
+ *    that, otherwise, report error.
+ * 3) if both "controller" and "port" are specified:
+ *    check the controller:port is available, if not, report error.
+ */
+static int libxl__device_usb_setdefault(libxl__gc *gc, uint32_t domid,
+                                        libxl_device_usb *usb,
+                                        bool update_json)
+{
+    int rc = -1;
+
+    if (!usb->devtype)
+        usb->devtype = LIBXL_USBDEV_TYPE_HOSTDEV;
+
+    if (usb->ctrl == -1) {
+        if (usb->port) {
+            LOG(ERROR, "USB controller must be specified if you specify port");
+            return ERROR_INVAL;
+        }
+
+        rc = libxl__device_usb_set_default_usbctrl(gc, domid, usb);
+        /* If no existing controller to host this usb device, add a new one */
+        if (rc) {
+            libxl_device_usbctrl *usbctrl;
+
+            GCNEW(usbctrl);
+            libxl_device_usbctrl_init(usbctrl);
+            rc = libxl__device_usbctrl_setdefault(gc, domid, usbctrl);
+            if (rc < 0) goto out;
+
+            if (usbctrl->devid == -1) {
+                usbctrl->devid = libxl__device_nextid(gc, domid, "vusb");
+                if (usbctrl->devid < 0) {
+                    goto out;
+                }
+            }
+
+            rc = libxl__device_usbctrl_add_xenstore(gc, domid, usbctrl,
+                                                    update_json);
+            if (rc) goto out;
+
+            usb->ctrl = usbctrl->devid;
+            usb->port = 1;
+        }
+    } else if (!usb->port) {
+        /* Valid port starts from 1. Choose port for us. */
+        int i, ports;
+        char *fe_path, *be_path, *tmp;
+
+        fe_path = GCSPRINTF("%s/device/vusb/%d",
+                         libxl__xs_get_dompath(gc, domid), usb->ctrl);
+        be_path = READ_FRONTEND(gc, "backend");
+        tmp = READ_BACKEND(gc, "num-ports");
+        ports = tmp ? atoi(tmp) : 0;
+
+        for (i = 0; i < ports; i++) {
+            tmp = libxl__xs_read(gc, XBT_NULL,
+                                 GCSPRINTF("%s/port/%d", be_path, i + 1));
+            if (tmp && !strcmp(tmp, "")) {
+                usb->port = i + 1;
+                break;
+            }
+        }
+
+        if (!usb->port) {
+            LOG(ERROR, "No available port under specified controller");
+            goto out;
+        }
+    } else {
+        char *fe_path, *be_path, *tmp;
+
+        fe_path = GCSPRINTF("%s/device/vusb/%d",
+                         libxl__xs_get_dompath(gc, domid), usb->ctrl);
+        be_path = READ_FRONTEND(gc, "backend");
+        tmp = libxl__xs_read(gc, XBT_NULL,
+                             GCSPRINTF("%s/port/%d", be_path, usb->port));
+        if (!tmp || strcmp(tmp, "")) {
+            LOG(ERROR, "The controller port isn't available");
+            goto out;
+        }
+    }
+
+    rc = 0;
+
+out:
+    return rc;
+}
+
+/* Add usb information to xenstore
+ *
+ * Adding a usb device won't create new 'vusb' device, but only write
+ * the device busid to the controller:port in xenstore.
+ */
+static int libxl__device_usb_add_xenstore(libxl__gc *gc, uint32_t domid,
+                                          libxl_device_usb *usb,
+                                          bool update_json)
+{
+    char *be_path;
+    char *busid;
+    int rc;
+    xs_transaction_t t = XBT_NULL;
+    libxl_domain_config d_config;
+    libxl_device_usb usb_saved;
+    libxl__domain_userdata_lock *lock = NULL;
+
+    libxl_domain_config_init(&d_config);
+    libxl_device_usb_init(&usb_saved);
+    libxl_device_usb_copy(CTX, &usb_saved, usb);
+
+    busid = usb_busaddr_to_busid(gc, usb->u.hostdev.hostbus,
+                                 usb->u.hostdev.hostaddr);
+    if (!busid) {
+        LOG(DEBUG, "Fail to get busid of usb device");
+        goto out;
+    }
+
+    if (update_json) {
+        lock = libxl__lock_domain_userdata(gc, domid);
+        if (!lock) {
+            rc = ERROR_LOCK_FAIL;
+            goto out;
+        }
+
+        rc = libxl__get_domain_configuration(gc, domid, &d_config);
+        if (rc) goto out;
+
+        DEVICE_ADD(usb, usbs, domid, &usb_saved, COMPARE_USB, &d_config);
+    }
+
+    for (;;) {
+        rc = libxl__xs_transaction_start(gc, &t);
+        if (rc) goto out;
+
+        if (update_json) {
+            rc = libxl__set_domain_configuration(gc, domid, &d_config);
+            if (rc) goto out;
+        }
+
+        be_path = GCSPRINTF("%s/backend/vusb/%d/%d/port/%d",
+                            libxl__xs_get_dompath(gc, LIBXL_TOOLSTACK_DOMID),
+                            domid, usb->ctrl, usb->port);
+
+        LOG(DEBUG, "Adding new usb device to xenstore");
+        if (libxl__xs_write_checked(gc, t, be_path, busid))
+            goto out;
+
+        rc = libxl__xs_transaction_commit(gc, &t);
+        if (!rc) break;
+        if (rc < 0) goto out;
+    }
+
+    rc = 0;
+
+out:
+    if (lock) libxl__unlock_domain_userdata(lock);
+    libxl_device_usb_dispose(&usb_saved);
+    libxl_domain_config_dispose(&d_config);
+    return rc;
+}
+
+static int libxl__device_usb_remove_xenstore(libxl__gc *gc, uint32_t domid,
+                                             libxl_device_usb *usb)
+{
+    char *be_path;
+
+    be_path = GCSPRINTF("%s/backend/vusb/%d/%d/port/%d",
+                        libxl__xs_get_dompath(gc, LIBXL_TOOLSTACK_DOMID),
+                        domid, usb->ctrl, usb->port);
+    LOG(DEBUG, "Removing USB device from xenstore");
+    if (libxl__xs_write_checked(gc,XBT_NULL, be_path, ""))
+        return ERROR_FAIL;
+
+    return 0;
+}
+
+/* bind/unbind usb device interface */
+static int unbind_usb_intf(libxl__gc *gc, char *intf, char **drvpath)
+{
+    char *path, *spath, *dp = NULL;
+    int fd = -1;
+    int rc = 0;
+    struct stat st;
+
+    spath = GCSPRINTF(SYSFS_USB_DEV"/%s/driver", intf);
+    if (!lstat(spath, &st)) {
+        /* Find the canonical path to the driver. */
+        dp = libxl__zalloc(gc, PATH_MAX);
+        dp = realpath(spath, dp);
+
+        path = GCSPRINTF("%s/unbind", spath);
+        fd = open(path, O_WRONLY);
+        if (fd < 0)
+            return ERROR_FAIL;
+        rc = write(fd, intf, strlen(intf));
+        close(fd);
+        if (rc < 0)
+            return ERROR_FAIL;
+    }
+
+    if (drvpath)
+        *drvpath = dp;
+
+    return 0;
+}
+
+static int bind_usb_intf(libxl__gc *gc, char *intf, char *drvpath)
+{
+    char *path;
+    struct stat st;
+    int fd, rc = 0;
+
+    path = GCSPRINTF("%s/%s", drvpath, intf);
+    rc = lstat(path, &st);
+    /* already bind, return */
+    if (rc == 0)
+        return 0;
+
+    path = GCSPRINTF("%s/bind", drvpath);
+    fd = open(path, O_WRONLY);
+    if (fd < 0)
+        return ERROR_FAIL;
+
+    rc = write(fd, intf, strlen(intf));
+    close(fd);
+    if (rc < 0)
+        return ERROR_FAIL;
+
+    return 0;
+}
+
+/* Is usb interface bound to usbback? */
+static int usb_intf_is_assigned(libxl__gc *gc, char *intf)
+{
+    char *spath;
+    int rc;
+    struct stat st;
+
+    spath = GCSPRINTF(SYSFS_USBBACK_DRIVER"/%s", intf);
+    rc = lstat(spath, &st);
+
+    if (rc == 0)
+        return 1;
+    if (rc < 0 && errno == ENOENT)
+        return 0;
+    LOGE(ERROR, "Accessing %s", spath);
+    return -1;
+}
+
+static int usb_get_all_interfaces(libxl__gc *gc, libxl_device_usb *usb,
+                                  char ***intfs, int *num)
+{
+    DIR *dir;
+    struct dirent *entry;
+    char *buf;
+    char *busid;
+    int rc = 0;
+
+    *intfs = NULL;
+    *num = 0;
+
+    busid = usb_busaddr_to_busid(gc, usb->u.hostdev.hostbus,
+                                 usb->u.hostdev.hostaddr);
+    if (!busid) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    buf = GCSPRINTF("%s:", busid);
+
+    if (!(dir = opendir(SYSFS_USB_DEV))) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    while ((entry = readdir(dir)) != NULL) {
+        if (!strncmp(entry->d_name, buf, strlen(buf))) {
+            GCREALLOC_ARRAY(*intfs, *num + 1);
+            if (*intfs == NULL) {
+                rc = ERROR_FAIL;
+                goto out;
+            }
+            (*intfs)[*num] = libxl__strdup(gc, entry->d_name);
+            (*num)++;
+        }
+    }
+
+    closedir(dir);
+
+out:
+    return rc;
+}
+
+/* Encode usb interface so that it could be written to xenstore as a key.
+ *
+ * Since xenstore key cannot include '.' or ':', we'll change '.' to '_',
+ * change ':' to '-'. For example, 3-1:2.1 will be encoded to 3-1-2_1.
+ * This will be used to save original driver of USB device to xenstore.
+ */
+static char *usb_interface_xenstore_encode(char *busid)
+{
+    char *str = strdup(busid);
+    int i, len = strlen(str);
+
+    for (i = 0; i < len; i++) {
+        if (str[i] == '.')
+            str[i] = '_';
+         if (str[i] == ':')
+            str[i] = '-';
+    }
+    return str;
+}
+
+/* Unbind USB device from "usbback" driver.
+ *
+ * If there are many interfaces under USB device, check each interface,
+ * unbind from "usbback" driver and rebind to its original driver.
+ */
+static int usbback_dev_unassign(libxl__gc *gc, libxl_device_usb *usb)
+{
+    char **intfs = NULL;
+    char *path;
+    int num = 0, i;
+    int rc = 0;
+    char *busid;
+    char *usb_encode = NULL;
+
+    if (usb_get_all_interfaces(gc, usb, &intfs, &num) < 0)
+        return ERROR_FAIL;
+
+    busid = usb_busaddr_to_busid(gc, usb->u.hostdev.hostbus,
+                                 usb->u.hostdev.hostaddr);
+    usb_encode = usb_interface_xenstore_encode(busid);
+
+    for (i = 0; i < num; i++) {
+        char *intf = intfs[i];
+        char *drvpath = NULL;
+
+        /* check if the USB interface is already bound to "usbbcak" */
+        if (usb_intf_is_assigned(gc, intf) > 0) {
+            /* unbind interface from usbback driver */
+            if (unbind_usb_intf(gc, intf, NULL) < 0) {
+                rc = ERROR_FAIL;
+                goto out;
+            }
+        }
+
+        /* bind interface to its originial driver */
+        drvpath = libxl__xs_read(gc, XBT_NULL,
+                  GCSPRINTF(USBBACK_INFO_PATH"/%s/%s/driver_path",
+                  usb_encode, usb_interface_xenstore_encode(intf)));
+        if (drvpath && bind_usb_intf(gc, intf, drvpath))
+            LOGE(WARN, "Couldn't bind %s to %s", intf, drvpath);
+    }
+
+    /* finally, remove xs driver path */
+    path = GCSPRINTF(USBBACK_INFO_PATH"/%s", usb_encode);
+    libxl__xs_rm_checked(gc, XBT_NULL, path);
+
+out:
+    free(usb_encode);
+    return rc;
+}
+
+/* Bind USB device to "usbback" driver.
+ *
+ * If there are many interfaces under USB device, check each interface,
+ * unbind from original driver and bind to "usbback" driver.
+ */
+static int usbback_dev_assign(libxl__gc *gc, libxl_device_usb *usb)
+{
+    char **intfs = NULL;
+    int num = 0, i;
+    int rc = 0;
+    char *busid;
+    char *usb_encode = NULL;
+
+    if (usb_get_all_interfaces(gc, usb, &intfs, &num) < 0)
+        return ERROR_FAIL;
+
+    busid = usb_busaddr_to_busid(gc, usb->u.hostdev.hostbus,
+                                 usb->u.hostdev.hostaddr);
+    usb_encode = usb_interface_xenstore_encode(busid);
+
+    for (i = 0; i < num; i++) {
+        char *intf = intfs[i];
+        char *path = NULL;
+        char *drvpath = NULL;
+
+        /* already assigned to usbback */
+        if (usb_intf_is_assigned(gc, intf) > 0)
+            continue;
+
+        /* unbind interface from original driver */
+        if (unbind_usb_intf(gc, intf, &drvpath) < 0) {
+            rc = ERROR_FAIL;
+            goto out_rebind;
+        }
+
+        if (drvpath) {
+            /* write driver path to xenstore for later rebinding */
+            path = GCSPRINTF(USBBACK_INFO_PATH"/%s/%s/driver_path",
+                             usb_encode, usb_interface_xenstore_encode(intf));
+            if (libxl__xs_write_checked(gc, XBT_NULL, path, drvpath) < 0) {
+                LOG(WARN, "Write of %s to node %s failed", drvpath, path);
+            }
+        }
+
+        /* bind interface to usbback */
+        if (bind_usb_intf(gc, intf, SYSFS_USBBACK_DRIVER) < 0) {
+            LOGE(ERROR, "Couldn't bind %s to %s", intf, SYSFS_USBBACK_DRIVER);
+            rc = ERROR_FAIL;
+            goto out_rebind;
+        }
+    }
+
+    goto out;
+
+out_rebind:
+    /* some interfaces might be bound to usbback, unbind it then and
+     * rebind to its original driver
+     */
+    usbback_dev_unassign(gc, usb);
+out:
+    free(usb_encode);
+    return rc;
+}
+
+/*
+ * USB add
+ */
+static int do_usb_add(libxl__gc *gc, uint32_t domid,
+                      libxl_device_usb *usbdev,
+                      libxl__ao_device *aodev)
+{
+    libxl_ctx *ctx = CTX;
+    libxl_usbctrlinfo usbctrlinfo;
+    libxl_device_usbctrl usbctrl;
+    int rc;
+
+    libxl_usbctrlinfo_init(&usbctrlinfo);
+    usbctrl.devid = usbdev->ctrl;
+    rc = libxl_device_usbctrl_getinfo(ctx, domid, &usbctrl, &usbctrlinfo);
+    if (rc)
+        goto out;
+
+    switch (usbctrlinfo.type) {
+    case LIBXL_USBCTRL_TYPE_DEVICEMODEL:
+        LOG(ERROR, "Not supported");
+        break;
+    case LIBXL_USBCTRL_TYPE_PV:
+        rc = libxl__device_usb_add_xenstore(gc, domid, usbdev,
+                                            aodev->update_json);
+        if (rc) goto out;
+
+        rc = usbback_dev_assign(gc, usbdev);
+        if (rc) {
+            libxl__device_usb_remove_xenstore(gc, domid, usbdev);
+            goto out;
+        }
+        break;
+    default:
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+out:
+    libxl_usbctrlinfo_dispose(&usbctrlinfo);
+    return rc;
+}
+
+/* AO operation to add a usb device.
+ *
+ * Generally, it does:
+ * 1) check if the usb device type is assignable
+ * 2) check if the usb device is already assigned to a domain
+ * 3) add 'busid' of the usb device to xenstore contoller/port/.
+ *    (PVUSB driver watches the xenstore changes and will detect that.)
+ * 4) unbind usb device from original driver and bind to usbback.
+ *    If usb device has many interfaces, then:
+ *    - unbind each interface from its original driver and bind to usbback.
+ *    - store the original driver to xenstore for later rebinding when
+ *      detaching the device.
+ */
+void libxl__device_usb_add(libxl__egc *egc, uint32_t domid,
+                           libxl_device_usb *usb,
+                           libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+    int rc = ERROR_FAIL;
+    char *busid = NULL;
+    libxl_device_usb *assigned;
+    int num_assigned;
+
+    assert(usb->u.hostdev.hostbus > 0 && usb->u.hostdev.hostaddr > 0);
+
+    busid = usb_busaddr_to_busid(gc, usb->u.hostdev.hostbus,
+                                 usb->u.hostdev.hostaddr);
+    if (!busid) {
+        LOG(ERROR, "USB device doesn't exist in sysfs");
+        goto out;
+    }
+
+    if (!is_usb_assignable(gc, usb)) {
+        LOG(ERROR, "USB device is not assignable.");
+        goto out;
+    }
+
+    /* check usb device is already assigned */
+    rc = get_assigned_devices(gc, &assigned, &num_assigned);
+    if (rc) {
+        LOG(ERROR, "cannot determine if device is assigned,"
+                   " refusing to continue");
+        goto out;
+    }
+
+    if (is_usbdev_in_array(assigned, num_assigned, usb)) {
+        LOG(ERROR, "USB device already attached to a domain");
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    rc = libxl__device_usb_setdefault(gc, domid, usb, aodev->update_json);
+    if (rc) goto out;
+
+    /* Do the add */
+    if (do_usb_add(gc, domid, usb, aodev))
+        rc = ERROR_FAIL;
+
+    libxl__ao_complete(egc, ao, 0);
+    rc = 0;
+
+out:
+    aodev->rc = rc;
+    if (rc) aodev->callback(egc, aodev);
+    return;
+}
+
+static int do_usb_remove(libxl__gc *gc, uint32_t domid,
+                         libxl_device_usb *usbdev)
+{
+    libxl_ctx *ctx = CTX;
+    libxl_usbctrlinfo usbctrlinfo;
+    libxl_device_usbctrl usbctrl;
+    int rc;
+
+    libxl_usbctrlinfo_init(&usbctrlinfo);
+    usbctrl.devid = usbdev->ctrl;
+    rc = libxl_device_usbctrl_getinfo(ctx, domid, &usbctrl, &usbctrlinfo);
+    if (rc)
+        goto out;
+
+    switch (usbctrlinfo.type) {
+    case LIBXL_USBCTRL_TYPE_DEVICEMODEL:
+        LOG(ERROR, "Not supported");
+        break;
+    case LIBXL_USBCTRL_TYPE_PV:
+        rc = libxl__device_usb_remove_xenstore(gc, domid, usbdev);
+        if (rc) goto out;
+
+        usbback_dev_unassign(gc, usbdev);
+        break;
+    default:
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+out:
+    libxl_usbctrlinfo_dispose(&usbctrlinfo);
+    return rc;
+}
+
+/* Operation to remove usb device.
+ *
+ * Generally, it does:
+ * 1) check if the usb device is assigned to the domain
+ * 2) remove the usb device from xenstore controller/port.
+ * 3) unbind usb device from usbback and rebind to its original driver.
+ *    If usb device has many interfaces, do it to each interface.
+ */
+static int libxl__device_usb_remove(libxl__gc *gc, uint32_t domid,
+                                    libxl_device_usb *usb)
+{
+    int rc = ERROR_FAIL;
+
+    if (usb->ctrl < 0 || usb->port < 1) {
+        LOG(ERROR, "Invalid USB device");
+        goto out;
+    }
+
+    if (usb->devtype == LIBXL_USBDEV_TYPE_HOSTDEV &&
+        (usb->u.hostdev.hostbus < 1 || usb->u.hostdev.hostaddr < 1)) {
+        LOG(ERROR, "Invalid USB device of hostdev");
+        goto out;
+    }
+
+    /* Do the remove */
+    rc = do_usb_remove(gc, domid, usb);
+
+out:
+    return rc;
+}
+
+int libxl_device_usb_remove(libxl_ctx *ctx, uint32_t domid,
+                            libxl_device_usb *usb,
+                            const libxl_asyncop_how *ao_how)
+
+{
+    AO_CREATE(ctx, domid, ao_how);
+    int rc;
+
+    rc = libxl__device_usb_remove(gc, domid, usb);
+
+    libxl__ao_complete(egc, ao, rc);
+    return AO_INPROGRESS;
+}
+
+int libxl_ctrlport_to_device_usb(libxl_ctx *ctx,
+                                 uint32_t domid,
+                                 int ctrl,
+                                 int port,
+                                 libxl_device_usb *usb)
+{
+    GC_INIT(ctx);
+    char *dompath, *be_path, *busid;
+    int rc = ERROR_FAIL;
+
+    dompath = libxl__xs_get_dompath(gc, domid);
+    if (!dompath)
+        goto out;
+
+    be_path = libxl__xs_read(gc, XBT_NULL,
+                  GCSPRINTF("%s/device/vusb/%d/backend", dompath, ctrl));
+    if (!be_path)
+        goto out;
+
+    busid = libxl__xs_read(gc, XBT_NULL,
+                           GCSPRINTF("%s/port/%d", be_path, port));
+    if (busid && strcmp(busid, "")) {
+        usb->ctrl = ctrl;
+        usb->port = port;
+        usb_busaddr_from_busid(gc, busid, &usb->u.hostdev.hostbus,
+                               &usb->u.hostdev.hostaddr);
+        rc = 0;
+    }
+
+out:
+    GC_FREE;
+    return rc;
+}
+
+int libxl_device_usb_getinfo(libxl_ctx *ctx, uint32_t domid,
+                             libxl_device_usb *usb,
+                             libxl_usbinfo *usbinfo)
+{
+    GC_INIT(ctx);
+    char *filename;
+    char *busid;
+    void *buf = NULL;
+    int buflen, rc;
+
+    usbinfo->ctrl = usb->ctrl;
+    usbinfo->port = usb->port;
+
+    if (libxl_ctrlport_to_device_usb(ctx, domid,
+                                     usb->ctrl, usb->port, usb) < 0) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    usbinfo->devnum = usb->u.hostdev.hostaddr;
+    usbinfo->busnum = usb->u.hostdev.hostbus;
+
+    busid = usb_busaddr_to_busid(gc, usb->u.hostdev.hostbus,
+                                 usb->u.hostdev.hostaddr);
+    if (!busid) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idVendor", busid);
+    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
+        sscanf(buf, "%" SCNx16, &usbinfo->idVendor);
+
+    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idProduct", busid);
+    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
+        sscanf(buf, "%" SCNx16, &usbinfo->idProduct);
+
+    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/manufacturer", busid);
+    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, &buflen) &&
+        buflen > 0) {
+        /* replace \n to \0 */
+        if (((char *)buf)[buflen - 1] == '\n')
+            ((char *)buf)[buflen - 1] = '\0';
+        usbinfo->manuf = libxl__strdup(NOGC, buf);
+   }
+
+    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/product", busid);
+    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, &buflen) &&
+        buflen > 0) {
+        /* replace \n to \0 */
+        if (((char *)buf)[buflen - 1] == '\n')
+            ((char *)buf)[buflen - 1] = '\0';
+        usbinfo->prod = libxl__strdup(NOGC, buf);
+    }
+
+    rc = 0;
+
+out:
+    GC_FREE;
+    return rc;
+}
+/*
+ * Local variables:
+ * mode: C
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
index 9f6ec00..4844f18 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -595,6 +595,35 @@ libxl_device_rdm = Struct("device_rdm", [
     ("policy", libxl_rdm_reserve_policy),
     ])
 
+libxl_usbctrl_type = Enumeration("usbctrl_type", [
+    (0, "AUTO"),
+    (1, "PV"),
+    (2, "DEVICEMODEL"),
+    ])
+
+libxl_usbdev_type = Enumeration("usbdev_type", [
+    (1, "hostdev"),
+    ])
+
+libxl_device_usbctrl = Struct("device_usbctrl", [
+    ("type", libxl_usbctrl_type),
+    ("devid", libxl_devid),
+    ("version", integer),
+    ("ports", integer),
+    ("backend_domid", libxl_domid),
+    ("backend_domname", string),
+   ])
+
+libxl_device_usb = Struct("device_usb", [
+    ("ctrl", libxl_devid),
+    ("port", integer),
+    ("u", KeyedUnion(None, libxl_usbdev_type, "devtype",
+           [("hostdev", Struct(None, [
+                 ("hostbus",   uint8),
+                 ("hostaddr",  uint8)])),
+           ])),
+    ])
+
 libxl_device_dtdev = Struct("device_dtdev", [
     ("path", string),
     ])
@@ -627,6 +656,8 @@ libxl_domain_config = Struct("domain_config", [
     ("pcidevs", Array(libxl_device_pci, "num_pcidevs")),
     ("rdms", Array(libxl_device_rdm, "num_rdms")),
     ("dtdevs", Array(libxl_device_dtdev, "num_dtdevs")),
+    ("usbctrls", Array(libxl_device_usbctrl, "num_usbctrls")),
+    ("usbs", Array(libxl_device_usb, "num_usbs")),
     ("vfbs", Array(libxl_device_vfb, "num_vfbs")),
     ("vkbs", Array(libxl_device_vkb, "num_vkbs")),
     ("vtpms", Array(libxl_device_vtpm, "num_vtpms")),
@@ -676,6 +707,32 @@ libxl_vtpminfo = Struct("vtpminfo", [
     ("uuid", libxl_uuid),
     ], dir=DIR_OUT)
 
+libxl_usbctrlinfo = Struct("usbctrlinfo", [
+    ("type", libxl_usbctrl_type),
+    ("devid", libxl_devid),
+    ("version", integer),
+    ("ports", integer),
+    ("backend", string),
+    ("backend_id", uint32),
+    ("frontend", string),
+    ("frontend_id", uint32),
+    ("state", integer),
+    ("evtch", integer),
+    ("ref_urb", integer),
+    ("ref_conn", integer),
+    ], dir=DIR_OUT)
+
+libxl_usbinfo = Struct("usbinfo", [
+    ("ctrl", libxl_devid),
+    ("port", integer),
+    ("busnum", uint8),
+    ("devnum", uint8),
+    ("idVendor", uint16),
+    ("idProduct", uint16),
+    ("prod", string),
+    ("manuf", string),
+    ], dir=DIR_OUT)
+
 libxl_vcpuinfo = Struct("vcpuinfo", [
     ("vcpuid", uint32),
     ("cpu", uint32),
diff --git a/tools/libxl/libxl_types_internal.idl b/tools/libxl/libxl_types_internal.idl
index 5e55685..696f5f8 100644
--- a/tools/libxl/libxl_types_internal.idl
+++ b/tools/libxl/libxl_types_internal.idl
@@ -22,6 +22,7 @@ libxl__device_kind = Enumeration("device_kind", [
     (6, "VKBD"),
     (7, "CONSOLE"),
     (8, "VTPM"),
+    (9, "VUSB"),
     ])
 
 libxl__console_backend = Enumeration("console_backend", [
diff --git a/tools/libxl/libxl_utils.c b/tools/libxl/libxl_utils.c
index 72f8f4f..2ba564c 100644
--- a/tools/libxl/libxl_utils.c
+++ b/tools/libxl/libxl_utils.c
@@ -1242,6 +1242,22 @@ int libxl__random_bytes(libxl__gc *gc, uint8_t *buf, size_t len)
     return ret;
 }
 
+void libxl_device_usbctrl_list_free(libxl_device_usbctrl* list, int nr)
+{
+   int i;
+   for (i = 0; i < nr; i++)
+      libxl_device_usbctrl_dispose(&list[i]);
+   free(list);
+}
+
+void libxl_device_usb_list_free(libxl_device_usb* list, int nr)
+{
+   int i;
+   for (i = 0; i < nr; i++)
+      libxl_device_usb_dispose(&list[i]);
+   free(list);
+}
+
 /*
  * Local variables:
  * mode: C
diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h
index 1e5ca8a..ef049e3 100644
--- a/tools/libxl/libxl_utils.h
+++ b/tools/libxl/libxl_utils.h
@@ -76,6 +76,11 @@ int libxl_uuid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid,
                                libxl_uuid *uuid, libxl_device_vtpm *vtpm);
 int libxl_devid_to_device_vtpm(libxl_ctx *ctx, uint32_t domid,
                                int devid, libxl_device_vtpm *vtpm);
+int libxl_devid_to_device_usbctrl(libxl_ctx *ctx, uint32_t domid,
+                                  int devid, libxl_device_usbctrl *usbctrl);
+int libxl_ctrlport_to_device_usb(libxl_ctx *ctx, uint32_t domid,
+                                 int ctrl, int port,
+                                 libxl_device_usb *usb);
 
 int libxl_bitmap_alloc(libxl_ctx *ctx, libxl_bitmap *bitmap, int n_bits);
     /* Allocated bimap is from malloc, libxl_bitmap_dispose() to be
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH V7 4/7] libxl: add libxl_device_usb_assignable_list API
  2015-09-25  2:11 [PATCH V7 0/7] xen pvusb toolstack work Chunyan Liu
                   ` (2 preceding siblings ...)
  2015-09-25  2:11 ` [PATCH V7 3/7] libxl: add pvusb API Chunyan Liu
@ 2015-09-25  2:11 ` Chunyan Liu
  2015-10-01 11:32   ` George Dunlap
  2015-09-25  2:11 ` [PATCH V7 5/7] xl: add pvusb commands Chunyan Liu
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 59+ messages in thread
From: Chunyan Liu @ 2015-09-25  2:11 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, wei.liu2, ian.campbell, george.dunlap, Ian.Jackson,
	Chunyan Liu, jfehlig

Add API for listing assignable USB devices info.
Assignable USB device means the USB device type is assignable and
it's not assigned to any guest yet.

Signed-off-by: Chunyan Liu <cyliu@suse.com>
---
This could be squashed with previous patch. Split because there is
some dispute on this. If this is acceptable, could be squashed,
otherwise could be removed.

 tools/libxl/libxl.h       |  3 +++
 tools/libxl/libxl_pvusb.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 58 insertions(+)

diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 633bfc1..c41b9de 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -1450,6 +1450,9 @@ int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid,
                                  libxl_usbctrlinfo *usbctrlinfo);
 
 /* USB Devices */
+libxl_device_usb *
+libxl_device_usb_assignable_list(libxl_ctx *ctx, int *num);
+
 int libxl_device_usb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_usb *usb,
                          const libxl_asyncop_how *ao_how)
                          LIBXL_EXTERNAL_CALLERS_ONLY;
diff --git a/tools/libxl/libxl_pvusb.c b/tools/libxl/libxl_pvusb.c
index d4b997f..b683e60 100644
--- a/tools/libxl/libxl_pvusb.c
+++ b/tools/libxl/libxl_pvusb.c
@@ -573,6 +573,61 @@ static bool is_usb_assignable(libxl__gc *gc, libxl_device_usb *usb)
     return classcode != USBHUB_CLASS_CODE;
 }
 
+libxl_device_usb *
+libxl_device_usb_assignable_list(libxl_ctx *ctx, int *num)
+{
+    GC_INIT(ctx);
+    libxl_device_usb *usbs = NULL;
+    libxl_device_usb *assigned;
+    int num_assigned;
+    struct dirent *de;
+    DIR *dir;
+
+    *num = 0;
+
+    if (get_assigned_devices(gc, &assigned, &num_assigned) < 0) {
+        LOG(ERROR, "cannot determine if device is assigned");
+        goto out;
+    }
+
+    if (!(dir = opendir(SYSFS_USB_DEV)))
+        goto out;
+
+    while ((de = readdir(dir))) {
+        libxl_device_usb *usb;
+        uint8_t bus = -1, addr = -1;
+
+        if (!de->d_name)
+            continue;
+
+        usb_busaddr_from_busid(gc, de->d_name, &bus, &addr);
+        if (bus < 1 || addr < 1)
+            continue;
+
+        GCNEW(usb);
+        usb->u.hostdev.hostbus = bus;
+        usb->u.hostdev.hostaddr = addr;
+
+        if (!is_usb_assignable(gc, usb))
+            continue;
+
+        if (is_usbdev_in_array(assigned, num_assigned, usb))
+            continue;
+
+        usbs = libxl__realloc(NOGC, usbs, sizeof(*usbs) * (*num + 1));
+        libxl_device_usb_init(usbs + *num);
+        usbs[*num].u.hostdev.hostbus = bus;
+        usbs[*num].u.hostdev.hostaddr = addr;
+        (*num)++;
+    }
+
+    closedir(dir);
+
+out:
+    GC_FREE;
+    return usbs;
+}
+
 /* get usb devices under certain usb controller */
 static int
 libxl__device_usb_list_for_usbctrl(libxl__gc *gc, uint32_t domid,
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH V7 5/7] xl: add pvusb commands
  2015-09-25  2:11 [PATCH V7 0/7] xen pvusb toolstack work Chunyan Liu
                   ` (3 preceding siblings ...)
  2015-09-25  2:11 ` [PATCH V7 4/7] libxl: add libxl_device_usb_assignable_list API Chunyan Liu
@ 2015-09-25  2:11 ` Chunyan Liu
  2015-10-01 17:02   ` George Dunlap
  2015-09-25  2:11 ` [PATCH V7 6/7] xl: add usb-assignable-list command Chunyan Liu
  2015-09-25  2:11 ` [PATCH V7 7/7] domcreate: support pvusb in configuration file Chunyan Liu
  6 siblings, 1 reply; 59+ messages in thread
From: Chunyan Liu @ 2015-09-25  2:11 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, wei.liu2, ian.campbell, george.dunlap, Ian.Jackson,
	Chunyan Liu, jfehlig, Simon Cao

Add pvusb commands: usb-ctrl-attach, usb-ctrl-detach, usb-list,
usb-attach and usb-detach.

To attach a usb device to guest through pvusb, one could follow
following example:

 #xl usb-ctrl-attach test_vm version=1 num_ports=8

 #xl usb-list test_vm
 will show the usb controllers and port usage under the domain.

 #xl usb-attach test_vm 1.6
 will find the first usable controller:port, and attach usb
 device whose bus address is 1.6 (busnum is 1, devnum is 6)
 to it. One could also specify which <controller> and which <port>.

 #xl usb-detach test_vm 0 1
 will detach USB device under controller 0 port 1.

 #xl usb-ctrl-detach test_vm dev_id
 will destroy the controller with specified dev_id. Dev_id
 can be traced in usb-list info.

Signed-off-by: Chunyan Liu <cyliu@suse.com>
Signed-off-by: Simon Cao <caobosimon@gmail.com>
---
 docs/man/xl.pod.1         |  40 ++++++++
 tools/libxl/xl.h          |   5 +
 tools/libxl/xl_cmdimpl.c  | 232 ++++++++++++++++++++++++++++++++++++++++++++++
 tools/libxl/xl_cmdtable.c |  25 +++++
 4 files changed, 302 insertions(+)

diff --git a/docs/man/xl.pod.1 b/docs/man/xl.pod.1
index f22c3f3..4c92c78 100644
--- a/docs/man/xl.pod.1
+++ b/docs/man/xl.pod.1
@@ -1345,6 +1345,46 @@ List pass-through pci devices for a domain.
 
 =back
 
+=head1 USB PASS-THROUGH
+
+=over 4
+
+=item B<usb-ctrl-attach> I<domain-id> I[<type=val>] [I<version=val>] [I<ports=number>]
+
+Create a new USB controller for the specified domain.
+B<type=val> is the usb controller type, currently only support 'pv'.
+B<version=val> is the usb controller version, could be 1 (USB1.1) or 2 (USB2.0).
+B<ports=number> is the total ports of the usb controller.
+By default, it will create a USB2.0 controller with 8 ports.
+
+=item B<usb-ctrl-detach> I<domain-id> I<devid>
+
+Destroy a USB controller from the specified domain.
+B<devid> is devid of the USB controller.
+
+If B<-f> is specified, B<xl> is going to forcefully remove the device even
+without guest's collaboration.
+
+=item B<usb-attach> I<domain-id> I<bus.addr> [I<controller=devid> [I<port=number>]]
+
+Hot-plug a new pass-through USB device to the specified domain.
+B<bus.addr> is the busnum.devnum of the physical USB device to pass-through.
+B<controller=devid> B<port=number> is the USB controller:port to hotplug the
+USB device to. By default, it will find the first available controller:port
+and use it; if there is no controller, it will create one.
+
+=item B<usb-detach> I<domain-id> I<controller=devid> I<port=number>
+
+Hot-unplug a previously assigned USB device from a domain.
+B<controller=devid> and B<port=number> is USB controller:port in guest where the
+USB device is attached to.
+
+=item B<usb-list> I<domain-id>
+
+List pass-through usb devices for a domain.
+
+=back
+
 =head1 TMEM
 
 =over 4
diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h
index 6c19c0d..26f6c1e 100644
--- a/tools/libxl/xl.h
+++ b/tools/libxl/xl.h
@@ -85,6 +85,11 @@ int main_blockdetach(int argc, char **argv);
 int main_vtpmattach(int argc, char **argv);
 int main_vtpmlist(int argc, char **argv);
 int main_vtpmdetach(int argc, char **argv);
+int main_usbctrl_attach(int argc, char **argv);
+int main_usbctrl_detach(int argc, char **argv);
+int main_usbattach(int argc, char **argv);
+int main_usbdetach(int argc, char **argv);
+int main_usblist(int argc, char **argv);
 int main_uptime(int argc, char **argv);
 int main_claims(int argc, char **argv);
 int main_tmem_list(int argc, char **argv);
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 2706759..6ae9479 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -3367,6 +3367,238 @@ int main_cd_insert(int argc, char **argv)
     return 0;
 }
 
+int main_usbctrl_attach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, rc = 1;
+    char *oparg;
+    libxl_device_usbctrl usbctrl;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-ctrl-attach", 1) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind++]);
+
+    libxl_device_usbctrl_init(&usbctrl);
+
+    while (argc > optind) {
+        if (MATCH_OPTION("type", argv[optind], oparg)) {
+            if (!strcmp(oparg, "pv")) {
+                usbctrl.type = LIBXL_USBCTRL_TYPE_PV;
+            } else {
+                fprintf(stderr, "unsupported type `%s'\n", oparg);
+                goto out;
+            }
+        } else if (MATCH_OPTION("version", argv[optind], oparg)) {
+            usbctrl.version = atoi(oparg);
+            if (usbctrl.version != 1 && usbctrl.version != 2) {
+                fprintf(stderr, "unsupported version `%s'\n", oparg);
+                goto out;
+            }
+        } else if (MATCH_OPTION("ports", argv[optind], oparg)) {
+            usbctrl.ports = atoi(oparg);
+            if (usbctrl.ports < 1 || usbctrl.ports > 31) {
+                fprintf(stderr, "unsupported ports `%s'\n", oparg);
+                goto out;
+            }
+        } else {
+            fprintf(stderr, "unrecognized argument `%s'\n", argv[optind]);
+            goto out;
+        }
+        optind++;
+    }
+
+    rc = libxl_device_usbctrl_add(ctx, domid, &usbctrl, 0);
+    if (rc)
+        fprintf(stderr, "libxl_device_usbctrl_add failed.\n");
+
+out:
+    libxl_device_usbctrl_dispose(&usbctrl);
+    return rc;
+}
+
+int main_usbctrl_detach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt, devid, rc;
+    libxl_device_usbctrl usbctrl;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-ctrl-detach", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    devid = atoi(argv[optind+1]);
+
+    libxl_device_usbctrl_init(&usbctrl);
+    if (libxl_devid_to_device_usbctrl(ctx, domid, devid, &usbctrl)) {
+        fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
+        return 1;
+    }
+
+    rc = libxl_device_usbctrl_remove(ctx, domid, &usbctrl, 0);
+    if (rc)
+        fprintf(stderr, "libxl_device_usbctrl_remove failed.\n");
+
+    libxl_device_usbctrl_dispose(&usbctrl);
+    return rc;
+
+}
+
+int main_usbattach(int argc, char **argv)
+{
+    uint32_t domid;
+    char *devname, *p;
+    int opt, rc = 1;
+    char *oparg;
+    libxl_device_usb usb;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-attach", 2) {
+        /* No options */
+    }
+
+    libxl_device_usb_init(&usb);
+
+    domid = find_domain(argv[optind++]);
+    devname = argv[optind++];
+    p = strchr(devname, '.');
+    if (p) {
+        usb.u.hostdev.hostbus = strtoul(devname, NULL, 0);
+        usb.u.hostdev.hostaddr = strtoul(p + 1, NULL, 0);
+    }
+
+    if (usb.u.hostdev.hostbus < 1 || usb.u.hostdev.hostaddr < 1) {
+        fprintf(stderr, "Invalid usb device.\n");
+        goto out;
+    }
+
+    while (argc > optind) {
+        if (MATCH_OPTION("controller", argv[optind], oparg)) {
+            usb.ctrl = atoi(oparg);
+        } else if (MATCH_OPTION("port", argv[optind], oparg)) {
+            usb.port = atoi(oparg);
+        } else {
+            fprintf(stderr, "unrecognized argument `%s'\n", argv[optind]);
+            goto out;
+        }
+        optind++;
+    }
+
+    rc = libxl_device_usb_add(ctx, domid, &usb, 0);
+    if (rc)
+        fprintf(stderr, "libxl_device_usb_add failed.\n");
+
+out:
+    libxl_device_usb_dispose(&usb);
+    return rc;
+}
+
+int main_usbdetach(int argc, char **argv)
+{
+    uint32_t domid;
+    int ctrl, port;
+    int opt, rc = 1;
+    libxl_device_usb usb;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-detach", 3) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+    ctrl = atoi(argv[optind+1]);
+    port = atoi(argv[optind+2]);
+
+    if (argc - optind > 3) {
+        fprintf(stderr, "Invalid arguments.\n");
+        goto out;
+    }
+
+    libxl_device_usb_init(&usb);
+    if (libxl_ctrlport_to_device_usb(ctx, domid, ctrl, port, &usb)) {
+        fprintf(stderr, "Unknown device at controller %d port %d.\n",
+                ctrl, port);
+        goto out;
+    }
+
+    rc = libxl_device_usb_remove(ctx, domid, &usb, 0);
+    if (rc)
+        fprintf(stderr, "libxl_device_usb_remove failed.\n");
+
+out:
+    libxl_device_usb_dispose(&usb);
+    return rc;
+}
+
+int main_usblist(int argc, char **argv)
+{
+    uint32_t domid;
+    libxl_device_usbctrl *usbctrls;
+    libxl_usbctrlinfo usbctrlinfo;
+    int numctrl, i, j, opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-list", 1) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind++]);
+
+    if (argc > optind) {
+        fprintf(stderr, "Invalid arguments.\n");
+        exit(-1);
+    }
+
+    usbctrls = libxl_device_usbctrl_list(ctx, domid, &numctrl);
+    if (!usbctrls) {
+        return 0;
+    }
+
+    for (i = 0; i < numctrl; ++i) {
+        printf("%-6s %-6s %-3s %-5s %-7s %-5s %-30s\n",
+                "Devid", "Type", "BE", "state", "usb-ver", "ports", "BE-path");
+
+        libxl_usbctrlinfo_init(&usbctrlinfo);
+
+        if (!libxl_device_usbctrl_getinfo(ctx, domid,
+                                &usbctrls[i], &usbctrlinfo)) {
+            printf("%-6d %-6s %-3d %-5d %-7d %-5d %-30s\n",
+                    usbctrlinfo.devid,
+                    libxl_usbctrl_type_to_string(usbctrlinfo.type),
+                    usbctrlinfo.backend_id, usbctrlinfo.state,
+                    usbctrlinfo.version, usbctrlinfo.ports,
+                    usbctrlinfo.backend);
+
+            for (j = 1; j <= usbctrlinfo.ports; j++) {
+                libxl_device_usb usb;
+                libxl_usbinfo usbinfo;
+
+                libxl_device_usb_init(&usb);
+                libxl_usbinfo_init(&usbinfo);
+
+                printf("  Port %d:", j);
+
+                usb.ctrl = usbctrlinfo.devid;
+                usb.port = j;
+                if (!libxl_device_usb_getinfo(ctx, domid, &usb, &usbinfo)) {
+                    printf(" Bus %03x Device %03x: ID %04x:%04x %s %s\n",
+                            usbinfo.busnum, usbinfo.devnum,
+                            usbinfo.idVendor, usbinfo.idProduct,
+                            usbinfo.manuf ?: "", usbinfo.prod ?: "");
+                } else {
+                    printf("\n");
+                }
+                libxl_usbinfo_dispose(&usbinfo);
+                libxl_device_usb_dispose(&usb);
+            }
+        }
+
+        libxl_usbctrlinfo_dispose(&usbctrlinfo);
+    }
+
+    libxl_device_usbctrl_list_free(usbctrls, numctrl);
+    return 0;
+}
+
 int main_console(int argc, char **argv)
 {
     uint32_t domid;
diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
index 0071f12..46f276e 100644
--- a/tools/libxl/xl_cmdtable.c
+++ b/tools/libxl/xl_cmdtable.c
@@ -551,6 +551,31 @@ struct cmd_spec cmd_table[] = {
     },
 
 #endif
+    { "usb-ctrl-attach",
+      &main_usbctrl_attach, 0, 1,
+      "Create a virtual USB controller for a domain",
+      "<Domain> [type=pv] [version=<version>] [ports=<number>]",
+    },
+    { "usb-ctrl-detach",
+      &main_usbctrl_detach, 0, 1,
+      "Remove the virtual USB controller specified by <DevId> for a domain",
+      "<Domain> <DevId>",
+    },
+    { "usb-attach",
+      &main_usbattach, 0, 1,
+      "Attach a USB device to a domain",
+      "<Domain> <bus.addr> [controller=<DevId> [port=<port>]]",
+    },
+    { "usb-detach",
+      &main_usbdetach, 0, 1,
+      "Detach a USB device from a domain",
+      "<Domain> <controller> <port>",
+    },
+    { "usb-list",
+      &main_usblist, 0, 0,
+      "List information about USB devices for a domain",
+      "<Domain>",
+    },
 };
 
 int cmdtable_len = sizeof(cmd_table)/sizeof(struct cmd_spec);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-09-25  2:11 [PATCH V7 0/7] xen pvusb toolstack work Chunyan Liu
                   ` (4 preceding siblings ...)
  2015-09-25  2:11 ` [PATCH V7 5/7] xl: add pvusb commands Chunyan Liu
@ 2015-09-25  2:11 ` Chunyan Liu
  2015-10-06 16:55   ` George Dunlap
  2015-09-25  2:11 ` [PATCH V7 7/7] domcreate: support pvusb in configuration file Chunyan Liu
  6 siblings, 1 reply; 59+ messages in thread
From: Chunyan Liu @ 2015-09-25  2:11 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, wei.liu2, ian.campbell, george.dunlap, Ian.Jackson,
	Chunyan Liu, jfehlig

Add xl usb-assignable-list command to list assignable USB devices.
Assignable USB device means the USB device type is assignable and
it's not assigned to any guest yet.

Signed-off-by: Chunyan Liu <cyliu@suse.com>

---
  Same as "libxl: add libxl_device_usb_assignable_list API" patch,
  this patch could be sqaushed to previous one. Split because of
  some dispute. Could be squashed if acceptable, otherwise could
  be removed.

 tools/libxl/xl.h          |  1 +
 tools/libxl/xl_cmdimpl.c  | 27 +++++++++++++++++++++++++++
 tools/libxl/xl_cmdtable.c |  4 ++++
 3 files changed, 32 insertions(+)

diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h
index 26f6c1e..909d31f 100644
--- a/tools/libxl/xl.h
+++ b/tools/libxl/xl.h
@@ -85,6 +85,7 @@ int main_blockdetach(int argc, char **argv);
 int main_vtpmattach(int argc, char **argv);
 int main_vtpmlist(int argc, char **argv);
 int main_vtpmdetach(int argc, char **argv);
+int main_usbassignable_list(int argc, char **argv);
 int main_usbctrl_attach(int argc, char **argv);
 int main_usbctrl_detach(int argc, char **argv);
 int main_usbattach(int argc, char **argv);
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 6ae9479..66d8f8c 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -3367,6 +3367,33 @@ int main_cd_insert(int argc, char **argv)
     return 0;
 }
 
+static void usb_assignable_list(void)
+{
+    libxl_device_usb *usbs;
+    int num, i;
+
+    usbs = libxl_device_usb_assignable_list(ctx, &num);
+
+    for (i = 0; i < num; i++) {
+        printf("%d.%d\n", usbs[i].u.hostdev.hostbus,
+               usbs[i].u.hostdev.hostaddr);
+    }
+
+    libxl_device_usb_list_free(usbs, num);
+}
+
+int main_usbassignable_list(int argc, char **argv)
+{
+    int opt;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-assignable-list", 0) {
+        /* No options */
+    }
+
+    usb_assignable_list();
+    return 0;
+}
+
 int main_usbctrl_attach(int argc, char **argv)
 {
     uint32_t domid;
diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
index 46f276e..ba51331 100644
--- a/tools/libxl/xl_cmdtable.c
+++ b/tools/libxl/xl_cmdtable.c
@@ -576,6 +576,10 @@ struct cmd_spec cmd_table[] = {
       "List information about USB devices for a domain",
       "<Domain>",
     },
+    { "usb-assignable-list",
+      &main_usbassignable_list, 0, 0,
+      "List all assignable USB devices",
+    },
 };
 
 int cmdtable_len = sizeof(cmd_table)/sizeof(struct cmd_spec);
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH V7 7/7] domcreate: support pvusb in configuration file
  2015-09-25  2:11 [PATCH V7 0/7] xen pvusb toolstack work Chunyan Liu
                   ` (5 preceding siblings ...)
  2015-09-25  2:11 ` [PATCH V7 6/7] xl: add usb-assignable-list command Chunyan Liu
@ 2015-09-25  2:11 ` Chunyan Liu
  2015-10-07 15:06   ` George Dunlap
  6 siblings, 1 reply; 59+ messages in thread
From: Chunyan Liu @ 2015-09-25  2:11 UTC (permalink / raw)
  To: xen-devel
  Cc: jgross, wei.liu2, ian.campbell, george.dunlap, Ian.Jackson,
	Chunyan Liu, jfehlig, Simon Cao

Add code to support pvusb in domain config file. One could specify
usbctrl and usb in domain's configuration file and create domain,
then usb controllers will be created and usb device would be attached
to guest automatically.

One could specify usb controllers and usb devices in config file
like this:
usbctrl=['version=2,ports=4', 'version=1, ports=4', ]
usbdev=['2.1,controller=0,port=1', ]

Signed-off-by: Chunyan Liu <cyliu@suse.com>
Signed-off-by: Simon Cao <caobosimon@gmail.com>

---
 docs/man/xl.cfg.pod.5        |  75 +++++++++++++++++++++++++++++++
 tools/libxl/libxl_create.c   |  73 ++++++++++++++++++++++++++++--
 tools/libxl/libxl_device.c   |   4 ++
 tools/libxl/libxl_internal.h |   8 ++++
 tools/libxl/xl_cmdimpl.c     | 105 ++++++++++++++++++++++++++++++++++++++++++-
 5 files changed, 261 insertions(+), 4 deletions(-)

diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5
index db4a163..355c9a9 100644
--- a/docs/man/xl.cfg.pod.5
+++ b/docs/man/xl.cfg.pod.5
@@ -716,6 +716,81 @@ Note this may be overridden by rdm_policy option in PCI device configuration.
 
 =back
 
+=item B<usbctrl=[ "USBCTRL_SPEC_STRING", "USBCTRL_SPEC_STRING", ... ]>
+
+Specifies the USB controllers created for this guest. Each
+B<USB_SPEC_STRING> has the form C<KEY=VALUE,KEY=VALUE,...> where:
+
+=over 4
+
+=item B<KEY=VALUE>
+
+Possible B<KEY>s are:
+
+=over 4
+
+=item B<type=TYPE>
+
+Specifies the protocol to implement USB controller, could be "pv" (indicates
+PVUSB) or "qemu" (indicates QEMU emulated). Currently only "pv" is supported.
+
+=item B<version=VERSION>
+
+Specifies version of the USB controller, could be 1 (USB1.1) or 2 (USB2.0).
+Default is 2 (USB2.0).
+
+=item B<ports=PORTS>
+
+Specifies port number of the USB controller. Default is 8.
+
+Each USB controller will have an index starting from 0. On the same
+controller, each port will have an index starting from 1.
+
+E.g.
+usbctrl=["version=1,ports=4", "version=2,ports=8",]
+The first controller has:
+controller index = 0, and port 1,2,3,4.
+The second controller has:
+controller index = 1, and port 1,2,3,4,5,6,7,8.
+
+=back
+
+=back
+
+=item B<usbdev=[ "USB_SPEC_STRING", "USB_SPEC_STRING", ... ]>
+
+Specifies the host USB devices to passthrough to this guest. Each
+B<USB_SPEC_STRING> has the form C<bus.addr,KEY=VALUE,KEY=VALUE,...> where:
+
+=over 4
+
+=item B<bus.addr>
+
+Identifies the busnum.devnum of the USB device from the host perspective.
+This is the same scheme as used in the output of C<lsusb> for the device in
+question.
+
+=item B<KEY=VALUE>
+
+Possible B<KEY>s are:
+
+=over 4
+
+=item B<controller=CONTROLLER>
+
+Specifies USB controller index, to which controller the USB device is attached.
+
+=item B<port=PORT>
+
+Specifies USB port index, to which port the USB device is attached. B<port=PORT>
+is valid only when B<controller=CONTROLLER> is specified. Without
+B<controller=CONTROLLER>, it will find the first available USB controller:port
+and use it. If there is no controller at all, it will create one.
+
+=back
+
+=back
+
 =item B<pci=[ "PCI_SPEC_STRING", "PCI_SPEC_STRING", ... ]>
 
 Specifies the host PCI devices to passthrough to this guest. Each B<PCI_SPEC_STRING>
diff --git a/tools/libxl/libxl_create.c b/tools/libxl/libxl_create.c
index f5771da..61fce74 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -729,6 +729,10 @@ static void domcreate_launch_dm(libxl__egc *egc, libxl__multidev *aodevs,
 
 static void domcreate_attach_vtpms(libxl__egc *egc, libxl__multidev *multidev,
                                    int ret);
+static void domcreate_attach_usbctrls(libxl__egc *egc,
+                                      libxl__multidev *multidev, int ret);
+static void domcreate_attach_usbs(libxl__egc *egc, libxl__multidev *multidev,
+                                   int ret);
 static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *aodevs,
                                  int ret);
 static void domcreate_attach_dtdev(libxl__egc *egc,
@@ -1386,13 +1390,13 @@ static void domcreate_attach_vtpms(libxl__egc *egc,
    if (d_config->num_vtpms > 0) {
        /* Attach vtpms */
        libxl__multidev_begin(ao, &dcs->multidev);
-       dcs->multidev.callback = domcreate_attach_pci;
+       dcs->multidev.callback = domcreate_attach_usbctrls;
        libxl__add_vtpms(egc, ao, domid, d_config, &dcs->multidev);
        libxl__multidev_prepared(egc, &dcs->multidev, 0);
        return;
    }
 
-   domcreate_attach_pci(egc, multidev, 0);
+   domcreate_attach_usbctrls(egc, multidev, 0);
    return;
 
 error_out:
@@ -1400,6 +1404,69 @@ error_out:
    domcreate_complete(egc, dcs, ret);
 }
 
+static void domcreate_attach_usbctrls(libxl__egc *egc,
+                                      libxl__multidev *multidev, int ret)
+{
+    libxl__domain_create_state *dcs = CONTAINER_OF(multidev, *dcs, multidev);
+    STATE_AO_GC(dcs->ao);
+    int domid = dcs->guest_domid;
+
+    libxl_domain_config *const d_config = dcs->guest_config;
+
+    if (ret) {
+        LOG(ERROR, "unable to add vtpm devices");
+        goto error_out;
+    }
+
+    if (d_config->num_usbctrls > 0) {
+        /* Attach usbctrls */
+        libxl__multidev_begin(ao, &dcs->multidev);
+        dcs->multidev.callback = domcreate_attach_usbs;
+        libxl__add_usbctrls(egc, ao, domid, d_config, &dcs->multidev);
+        libxl__multidev_prepared(egc, &dcs->multidev, 0);
+        return;
+    }
+
+    domcreate_attach_usbs(egc, multidev, 0);
+    return;
+
+error_out:
+    assert(ret);
+    domcreate_complete(egc, dcs, ret);
+}
+
+
+static void domcreate_attach_usbs(libxl__egc *egc, libxl__multidev *multidev,
+                                int ret)
+{
+    libxl__domain_create_state *dcs = CONTAINER_OF(multidev, *dcs, multidev);
+    STATE_AO_GC(dcs->ao);
+    int domid = dcs->guest_domid;
+
+    libxl_domain_config *const d_config = dcs->guest_config;
+
+    if (ret) {
+        LOG(ERROR, "unable to add usbctrl devices");
+        goto error_out;
+    }
+
+    if (d_config->num_usbs > 0) {
+        /* Attach usbctrls */
+        libxl__multidev_begin(ao, &dcs->multidev);
+        dcs->multidev.callback = domcreate_attach_pci;
+        libxl__add_usbs(egc, ao, domid, d_config, &dcs->multidev);
+        libxl__multidev_prepared(egc, &dcs->multidev, 0);
+        return;
+    }
+
+    domcreate_attach_pci(egc, multidev, 0);
+    return;
+
+error_out:
+    assert(ret);
+    domcreate_complete(egc, dcs, ret);
+}
+
 static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *multidev,
                                  int ret)
 {
@@ -1413,7 +1480,7 @@ static void domcreate_attach_pci(libxl__egc *egc, libxl__multidev *multidev,
     libxl_domain_config *const d_config = dcs->guest_config;
 
     if (ret) {
-        LOG(ERROR, "unable to add vtpm devices");
+        LOG(ERROR, "unable to add usb devices");
         goto error_out;
     }
 
diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
index 935f25b..92d5d10 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -544,6 +544,8 @@ void libxl__multidev_prepared(libxl__egc *egc,
  * libxl__add_disks
  * libxl__add_nics
  * libxl__add_vtpms
+ * libxl__add_usbctrls
+ * libxl__add_usbs
  */
 
 #define DEFINE_DEVICES_ADD(type)                                        \
@@ -563,6 +565,8 @@ void libxl__multidev_prepared(libxl__egc *egc,
 DEFINE_DEVICES_ADD(disk)
 DEFINE_DEVICES_ADD(nic)
 DEFINE_DEVICES_ADD(vtpm)
+DEFINE_DEVICES_ADD(usbctrl)
+DEFINE_DEVICES_ADD(usb)
 
 #undef DEFINE_DEVICES_ADD
 
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index c433a0d..e6ea9a8 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -3296,6 +3296,14 @@ _hidden void libxl__add_vtpms(libxl__egc *egc, libxl__ao *ao, uint32_t domid,
                              libxl_domain_config *d_config,
                              libxl__multidev *multidev);
 
+_hidden void libxl__add_usbctrls(libxl__egc *egc, libxl__ao *ao,
+                                 uint32_t domid, libxl_domain_config *d_config,
+                                 libxl__multidev *multidev);
+
+_hidden void libxl__add_usbs(libxl__egc *egc, libxl__ao *ao,
+                             uint32_t domid, libxl_domain_config *d_config,
+                             libxl__multidev *multidev);
+
 /*----- device model creation -----*/
 
 /* First layer; wraps libxl__spawn_spawn. */
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 66d8f8c..c64e445 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -1253,6 +1253,79 @@ static void parse_vnuma_config(const XLU_Config *config,
     free(vcpu_parsed);
 }
 
+static void parse_usbctrl_config(libxl_device_usbctrl *usbctrl,
+                                 const char *buf)
+{
+    char *buf2 = strdup(buf);
+    char *p, *p2;
+
+    p = strtok(buf2, ",");
+    if (!p)
+        goto out;
+    do {
+        while (*p == ' ')
+            p++;
+        if ((p2 = strchr(p, '=')) == NULL)
+            break;
+        *p2 = '\0';
+        if (!strcmp(p, "type")) {
+            if (!strcmp(p2 + 1, "pv")) {
+                usbctrl->type = LIBXL_USBCTRL_TYPE_PV;
+            } else {
+                fprintf(stderr,
+                        "Unsupported USB controller type '%s'\n",
+                        p2 + 1);
+                exit(1);
+            }
+        } else if (!strcmp(p, "version")){
+            usbctrl->version = atoi(p2 + 1);
+        } else if (!strcmp(p, "ports")){
+            usbctrl->ports = atoi(p2 + 1);
+        } else {
+            fprintf(stderr, "Unknown string `%s' in usb spec\n", p);
+            exit(1);
+        }
+    } while ((p = strtok(NULL, ",")) != NULL);
+
+out:
+    free(buf2);
+}
+
+static void parse_usb_config(libxl_device_usb *usb, const char *buf)
+{
+    char *buf2 = strdup(buf);
+    char *p, *p2;
+
+    p = strtok(buf2, ",");
+    if (!p)
+        goto out;
+    do {
+        while(*p == ' ')
+            ++p;
+        if ((p2 = strchr(p, '=')) == NULL) {
+            char *busaddr = p;
+            p = strchr(busaddr, '.');
+            if (p) {
+                usb->u.hostdev.hostbus = strtoul(busaddr, NULL, 0);
+                usb->u.hostdev.hostaddr = strtoul(p + 1, NULL, 0);
+            }
+            continue;
+        }
+        *p2 = '\0';
+        if (!strcmp(p, "controller")) {
+            usb->ctrl = atoi(p2 + 1);
+        } else if (!strcmp(p, "port")) {
+            usb->port = atoi(p2 + 1);
+        } else {
+            fprintf(stderr, "Unknown string `%s' in usb spec\n", p);
+            exit(1);
+        }
+    } while ((p = strtok(NULL, ",")) != NULL);
+
+out:
+    free(buf2);
+}
+
 static void parse_config_data(const char *config_source,
                               const char *config_data,
                               int config_len,
@@ -1261,7 +1334,8 @@ static void parse_config_data(const char *config_source,
     const char *buf;
     long l, vcpus = 0;
     XLU_Config *config;
-    XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms;
+    XLU_ConfigList *cpus, *vbds, *nics, *pcis, *cvfbs, *cpuids, *vtpms,
+                   *usbctrls, *usbs;
     XLU_ConfigList *channels, *ioports, *irqs, *iomem, *viridian, *dtdevs;
     int num_ioports, num_irqs, num_iomem, num_cpus, num_viridian;
     int pci_power_mgmt = 0;
@@ -2078,6 +2152,35 @@ skip_vfb:
         }
     }
 
+    if (!xlu_cfg_get_list(config, "usbctrl", &usbctrls, 0, 0)) {
+        d_config->num_usbctrls = 0;
+        d_config->usbctrls = NULL;
+        while ((buf = xlu_cfg_get_listitem(usbctrls, d_config->num_usbctrls))
+               != NULL) {
+            libxl_device_usbctrl *usbctrl;
+
+            usbctrl = ARRAY_EXTEND_INIT(d_config->usbctrls,
+                                        d_config->num_usbctrls,
+                                        libxl_device_usbctrl_init);
+
+            parse_usbctrl_config(usbctrl, buf);
+        }
+    }
+
+    if (!xlu_cfg_get_list(config, "usbdev", &usbs, 0, 0)) {
+        d_config->num_usbs = 0;
+        d_config->usbs = NULL;
+        while ((buf = xlu_cfg_get_listitem(usbs, d_config->num_usbs)) != NULL) {
+            libxl_device_usb *usb;
+
+            usb = ARRAY_EXTEND_INIT_NODEVID(d_config->usbs,
+                                            d_config->num_usbs,
+                                            libxl_device_usb_init);
+
+            parse_usb_config(usb, buf);
+        }
+    }
+
     switch (xlu_cfg_get_list(config, "cpuid", &cpuids, 0, 1)) {
     case 0:
         {
-- 
2.1.4

^ permalink raw reply related	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 2/7] libxl_read_file_contents: add new entry to read sysfs file
  2015-09-25  2:11 ` [PATCH V7 2/7] libxl_read_file_contents: add new entry to read sysfs file Chunyan Liu
@ 2015-09-30 11:22   ` George Dunlap
  2015-10-02 13:25   ` Ian Campbell
  1 sibling, 0 replies; 59+ messages in thread
From: George Dunlap @ 2015-09-30 11:22 UTC (permalink / raw)
  To: Chunyan Liu, xen-devel
  Cc: jgross, wei.liu2, ian.campbell, george.dunlap, Ian.Jackson, jfehlig

On 25/09/15 03:11, Chunyan Liu wrote:
> Sysfs file has size=4096 but actual file content is less than that.
> Current libxl_read_file_contents will treat it as error when file size
> and actual file content differs, so reading sysfs file content with
> this function always fails.
> 
> Add a new entry libxl_read_sysfs_file_contents to handle sysfs file
> specially. It would be used in later pvusb work.
> 
> Signed-off-by: Chunyan Liu <cyliu@suse.com>
> Reviewed-by: Wei Liu <wei.liu2@citrix.com>

This seems like it's a generic enough improvement to stand on its own --
would it make sense to check this in regardless, so we can remove it
from the series?

 -George

> ---
> Changes:
>   - check return value after realloc
> 
>  tools/libxl/libxl_internal.h |  2 ++
>  tools/libxl/libxl_utils.c    | 52 ++++++++++++++++++++++++++++++++++----------
>  2 files changed, 43 insertions(+), 11 deletions(-)
> 
> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index 6ff17f9..1a2e483 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -4015,6 +4015,8 @@ void libxl__bitmap_copy_best_effort(libxl__gc *gc, libxl_bitmap *dptr,
>  
>  int libxl__count_physical_sockets(libxl__gc *gc, int *sockets);
>  #endif
> +_hidden int libxl_read_sysfs_file_contents(libxl_ctx *ctx, const char *filename,
> +                                   void **data_r, int *datalen_r);
>  
>  /*
>   * Local variables:
> diff --git a/tools/libxl/libxl_utils.c b/tools/libxl/libxl_utils.c
> index bfc9699..72f8f4f 100644
> --- a/tools/libxl/libxl_utils.c
> +++ b/tools/libxl/libxl_utils.c
> @@ -322,8 +322,10 @@ out:
>      return rc;
>  }
>  
> -int libxl_read_file_contents(libxl_ctx *ctx, const char *filename,
> -                             void **data_r, int *datalen_r) {
> +static int libxl_read_file_contents_core(libxl_ctx *ctx, const char *filename,
> +                                         void **data_r, int *datalen_r,
> +                                         bool tolerate_shrinking_file)
> +{
>      GC_INIT(ctx);
>      FILE *f = 0;
>      uint8_t *data = 0;
> @@ -359,20 +361,35 @@ int libxl_read_file_contents(libxl_ctx *ctx, const char *filename,
>      datalen = stab.st_size;
>  
>      if (stab.st_size && data_r) {
> -        data = malloc(datalen);
> +        data = malloc(datalen + 1);
>          if (!data) goto xe;
>  
> -        rs = fread(data, 1, datalen, f);
> -        if (rs != datalen) {
> -            if (ferror(f))
> +        rs = fread(data, 1, datalen + 1, f);
> +        if (rs > datalen) {
> +            LOG(ERROR, "%s increased size while we were reading it",
> +                filename);
> +            goto xe;
> +        }
> +
> +        if (rs < datalen) {
> +            if (ferror(f)) {
>                  LOGE(ERROR, "failed to read %s", filename);
> -            else if (feof(f))
> -                LOG(ERROR, "%s changed size while we were reading it",
> -		    filename);
> -            else
> +                goto xe;
> +            } else if (feof(f)) {
> +                if (tolerate_shrinking_file) {
> +                    datalen = rs;
> +                } else {
> +                    LOG(ERROR, "%s shrunk size while we were reading it",
> +                        filename);
> +                    goto xe;
> +                }
> +            } else {
>                  abort();
> -            goto xe;
> +            }
>          }
> +
> +        data = realloc(data, datalen);
> +        if (!data) goto xe;
>      }
>  
>      if (fclose(f)) {
> @@ -396,6 +413,19 @@ int libxl_read_file_contents(libxl_ctx *ctx, const char *filename,
>      return e;
>  }
>  
> +int libxl_read_file_contents(libxl_ctx *ctx, const char *filename,
> +                             void **data_r, int *datalen_r)
> +{
> +    return libxl_read_file_contents_core(ctx, filename, data_r, datalen_r, 0);
> +}
> +
> +int libxl_read_sysfs_file_contents(libxl_ctx *ctx, const char *filename,
> +                                   void **data_r, int *datalen_r)
> +{
> +    return libxl_read_file_contents_core(ctx, filename, data_r, datalen_r, 1);
> +}
> +
> +
>  #define READ_WRITE_EXACTLY(rw, zero_is_eof, constdata)                    \
>                                                                            \
>    int libxl_##rw##_exactly(libxl_ctx *ctx, int fd,                 \
> 

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 3/7] libxl: add pvusb API
  2015-09-25  2:11 ` [PATCH V7 3/7] libxl: add pvusb API Chunyan Liu
@ 2015-09-30 17:55   ` George Dunlap
  2015-10-02 13:31     ` Ian Campbell
                       ` (2 more replies)
  2015-10-08 14:41   ` Ian Jackson
  1 sibling, 3 replies; 59+ messages in thread
From: George Dunlap @ 2015-09-30 17:55 UTC (permalink / raw)
  To: Chunyan Liu, xen-devel
  Cc: jgross, wei.liu2, ian.campbell, george.dunlap, Ian.Jackson,
	jfehlig, Simon Cao

On 25/09/15 03:11, Chunyan Liu wrote:
> Add pvusb APIs, including:
>  - attach/detach (create/destroy) virtual usb controller.
>  - attach/detach usb device
>  - list usb controllers and usb devices
>  - get information of usb controller and usb device
>  - some other helper functions
> 
> Signed-off-by: Chunyan Liu <cyliu@suse.com>
> Signed-off-by: Simon Cao <caobosimon@gmail.com>

Hey Chunyan!  This looks pretty close to being ready to check in to me.

There are four basic comments I have.  I'm keen to get this series in so
that we can start doing more collaborative improvement; so I'll give my
comments, and then talk about timing and a plan to get this in as
quikcly as possible at the bottom.


> diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
> index aea4887..1e2c63e 100644
> --- a/tools/libxl/libxl.c
> +++ b/tools/libxl/libxl.c
> @@ -4192,11 +4192,54 @@ DEFINE_DEVICE_REMOVE(vtpm, destroy, 1)
>  
>  /******************************************************************************/
>  
> +/* Macro for defining device remove/destroy functions for usbctrl */
> +/* Following functions are defined:
> + * libxl_device_usbctrl_remove
> + * libxl_device_usbctrl_destroy
> + */
> +
> +#define DEFINE_DEVICE_REMOVE_EXT(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 = LIBXL__DEVICE_ACTION_REMOVE;                    \
> +        aodev->dev = device;                                            \
> +        aodev->callback = device_addrm_aocomplete;                      \
> +        aodev->force = f;                                               \
> +        libxl__initiate_device_##type##_remove(egc, aodev);             \

So this seems to be exactly the same as DEFINE_DEVICE_REMOVE(), except
that you call libxl__initiate_device_usbctrl_remove() here rather than
libxl__initiate_device_remove().

It seems like it might be better to have a separate patch renaming
libxl__initiate_device_remove to libxl__initiate_device_generic_remove
(or something like that), and then add a parameter to the definition
above making it so that the definitions above pass in "generic".

> diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c
> index bee5ed5..935f25b 100644
> --- a/tools/libxl/libxl_device.c
> +++ b/tools/libxl/libxl_device.c
> @@ -676,6 +676,10 @@ void libxl__devices_destroy(libxl__egc *egc, libxl__devices_remove_state *drs)
>                  aodev->action = LIBXL__DEVICE_ACTION_REMOVE;
>                  aodev->dev = dev;
>                  aodev->force = drs->force;
> +                if (dev->backend_kind == LIBXL__DEVICE_KIND_VUSB) {
> +                    libxl__initiate_device_usbctrl_remove(egc, aodev);
> +                    continue;
> +                }
>                  libxl__initiate_device_remove(egc, aodev);

I think this would probably be more clear if you did:

if(dev->backend_kind == LIBXL__DEVICE_KIND_VUSB)
  libxl__initiate_device_usbctl_remove()
else
  libxl__initiate_device_remove()

> @@ -3951,7 +3966,10 @@ static inline void libxl__update_config_vtpm(libxl__gc *gc,
>  #define COMPARE_PCI(a, b) ((a)->func == (b)->func &&    \
>                             (a)->bus == (b)->bus &&      \
>                             (a)->dev == (b)->dev)
> -
> +#define COMPARE_USB(a, b) ((a)->u.hostdev.hostbus == (b)->u.hostdev.hostbus && \
> +                           (a)->u.hostdev.hostaddr == (b)->u.hostdev.hostaddr)

Hmm... COMPARE_USB is used in three places:

1. Used in libxl.c:libxl_retrieve_domain_configuration() to de-duplicate
JSON and xenstore configuration

2. Used in libxl_pvusb.c:libxl__device_usb_add_xentore() to avoid adding
the same device twice

3. Used in libxl_pvusb.c:is_usbdev_in_array() to avoid assigning the
same host device

For #3, we pretty clearly want to be comparing hostbus/hostaddr.  (In
fact, you didn't use the COMPARE_USB macro until I suggested it in v3.)

But for #1 and #2, is that what we want?  Should we be comparing
<ctrl,port> instead?

In fact, after thinking about pvusb backends more, I think I want to
assert that we do want to compare <ctrl,port> instead: <crtl,port> is
guaranteed to be unique for a domain, but it's entirely possible to have
two different devices, from two different backend domains, with the same
bus.addr.

> +int libxl_devid_to_device_usbctrl(libxl_ctx *ctx,
> +                                  uint32_t domid,
> +                                  int devid,
> +                                  libxl_device_usbctrl *usbctrl)
> +{
> +    GC_INIT(ctx);
> +    libxl_device_usbctrl *usbctrls;
> +    int nb = 0;
> +    int i, rc = -1;
> +
> +    usbctrls = libxl_device_usbctrl_list(ctx, domid, &nb);
> +    if (!nb) goto out;
> +
> +    for (i = 0; i < nb; i++) {
> +        if (devid == usbctrls[i].devid) {
> +            *usbctrl = usbctrls[i];

libxl maintainers: Is this kind of copying OK?

The analog functions for vtpm and nic both take very different
approaches; both call libxl_device_[type]_init() and then fill in
individual elements (albeit in different ways).

> +/*
> + * USB add
> + */
> +static int do_usb_add(libxl__gc *gc, uint32_t domid,
> +                      libxl_device_usb *usbdev,
> +                      libxl__ao_device *aodev)
> +{
> +    libxl_ctx *ctx = CTX;
> +    libxl_usbctrlinfo usbctrlinfo;
> +    libxl_device_usbctrl usbctrl;
> +    int rc;
> +
> +    libxl_usbctrlinfo_init(&usbctrlinfo);
> +    usbctrl.devid = usbdev->ctrl;
> +    rc = libxl_device_usbctrl_getinfo(ctx, domid, &usbctrl, &usbctrlinfo);
> +    if (rc)
> +        goto out;
> +
> +    switch (usbctrlinfo.type) {
> +    case LIBXL_USBCTRL_TYPE_DEVICEMODEL:
> +        LOG(ERROR, "Not supported");
> +        break;
> +    case LIBXL_USBCTRL_TYPE_PV:
> +        rc = libxl__device_usb_add_xenstore(gc, domid, usbdev,
> +                                            aodev->update_json);
> +        if (rc) goto out;
> +
> +        rc = usbback_dev_assign(gc, usbdev);

This assumes that the usb controller is dom0; but the interface
explicitly allows pvusb driver domains.

I think it would be enough here to do this check if the usbctrl device
is dom0.  We should then assume that a pvusb driver domain will be
configured with all usb devices assigned to usbback already.

I assume that there's a feedback mechanisms for backends for situations
where the requested device can't be made, right?  For example, if you
have a network driver domain and request a non-existent bridge?  If so,
I think we can let the same mechanism worth for pvusb backends to say "I
don't have that device available".

> +        if (rc) {
> +            libxl__device_usb_remove_xenstore(gc, domid, usbdev);
> +            goto out;
> +        }
> +        break;
> +    default:
> +        rc = ERROR_FAIL;
> +        goto out;
> +    }
> +
> +out:
> +    libxl_usbctrlinfo_dispose(&usbctrlinfo);
> +    return rc;
> +}
> +
> +/* AO operation to add a usb device.
> + *
> + * Generally, it does:
> + * 1) check if the usb device type is assignable
> + * 2) check if the usb device is already assigned to a domain
> + * 3) add 'busid' of the usb device to xenstore contoller/port/.
> + *    (PVUSB driver watches the xenstore changes and will detect that.)
> + * 4) unbind usb device from original driver and bind to usbback.
> + *    If usb device has many interfaces, then:
> + *    - unbind each interface from its original driver and bind to usbback.
> + *    - store the original driver to xenstore for later rebinding when
> + *      detaching the device.
> + */
> +void libxl__device_usb_add(libxl__egc *egc, uint32_t domid,
> +                           libxl_device_usb *usb,
> +                           libxl__ao_device *aodev)
> +{
> +    STATE_AO_GC(aodev->ao);
> +    int rc = ERROR_FAIL;
> +    char *busid = NULL;
> +    libxl_device_usb *assigned;
> +    int num_assigned;
> +
> +    assert(usb->u.hostdev.hostbus > 0 && usb->u.hostdev.hostaddr > 0);
> +
> +    busid = usb_busaddr_to_busid(gc, usb->u.hostdev.hostbus,
> +                                 usb->u.hostdev.hostaddr);
> +    if (!busid) {
> +        LOG(ERROR, "USB device doesn't exist in sysfs");
> +        goto out;
> +    }
> +
> +    if (!is_usb_assignable(gc, usb)) {
> +        LOG(ERROR, "USB device is not assignable.");
> +        goto out;
> +    }

Similar issue with pvusb driver domains: we can't do this check for
driver domains.

I wonder if we should do this check instead down on the
usbback_assign_path().

If we assume that for pvusb driver domains:
1. All assignable devices will be assigned to usbback
2. No controllers will be assigned (since they can't be)
3. pvusb can say "no such device" for unassigned devices
then we can safely ignore the check for pvusb driver domains

> +
> +    /* check usb device is already assigned */
> +    rc = get_assigned_devices(gc, &assigned, &num_assigned);
> +    if (rc) {
> +        LOG(ERROR, "cannot determine if device is assigned,"
> +                   " refusing to continue");
> +        goto out;
> +    }
> +
> +    if (is_usbdev_in_array(assigned, num_assigned, usb)) {
> +        LOG(ERROR, "USB device already attached to a domain");
> +        rc = ERROR_FAIL;
> +        goto out;
> +    }

WRT driver domains: Since we're looking inside xenstore instead of
sysfs, we *can* actually do these checks.

However, the "bus.addr" space is defined by the driver domain kernel,
and is not unique across all driver domains: If we have one usb
controller assigned to domain 0, and another assigned to a driver
domain, two distinct devices are likely to end up with the same bus.addr.

So to be compatible with driver domains, we'd need to have
get_assigned_devices() only get devices with the same backend_domid as
the controller we're checking.

> +int libxl_device_usb_getinfo(libxl_ctx *ctx, uint32_t domid,
> +                             libxl_device_usb *usb,
> +                             libxl_usbinfo *usbinfo)
> +{
> +    GC_INIT(ctx);
> +    char *filename;
> +    char *busid;
> +    void *buf = NULL;
> +    int buflen, rc;
> +
> +    usbinfo->ctrl = usb->ctrl;
> +    usbinfo->port = usb->port;
> +
> +    if (libxl_ctrlport_to_device_usb(ctx, domid,
> +                                     usb->ctrl, usb->port, usb) < 0) {
> +        rc = ERROR_FAIL;
> +        goto out;
> +    }

I suppose technically since usb isn't declared const that we haven't
promised to modify it; but none of the other device_*_getinfo()
functions modify the device struct; I think it would be better to follow
suit and use a local variable to get the information from.

However...

> +
> +    usbinfo->devnum = usb->u.hostdev.hostaddr;
> +    usbinfo->busnum = usb->u.hostdev.hostbus;
> +
> +    busid = usb_busaddr_to_busid(gc, usb->u.hostdev.hostbus,
> +                                 usb->u.hostdev.hostaddr);
> +    if (!busid) {
> +        rc = ERROR_FAIL;
> +        goto out;
> +    }
> +
> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idVendor", busid);
> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
> +        sscanf(buf, "%" SCNx16, &usbinfo->idVendor);
> +
> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idProduct", busid);
> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
> +        sscanf(buf, "%" SCNx16, &usbinfo->idProduct);
> +
> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/manufacturer", busid);
> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, &buflen) &&
> +        buflen > 0) {
> +        /* replace \n to \0 */
> +        if (((char *)buf)[buflen - 1] == '\n')
> +            ((char *)buf)[buflen - 1] = '\0';
> +        usbinfo->manuf = libxl__strdup(NOGC, buf);
> +   }
> +
> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/product", busid);
> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, &buflen) &&
> +        buflen > 0) {
> +        /* replace \n to \0 */
> +        if (((char *)buf)[buflen - 1] == '\n')
> +            ((char *)buf)[buflen - 1] = '\0';
> +        usbinfo->prod = libxl__strdup(NOGC, buf);
> +    }

Basically, starting here, we have information which won't be available
if we're using a pvusb driver domain.

This information is nice-to-have, but I don't think this information is
directly relevant to libxl or xl; the funcitonality to get this
information is available from other libraries like libusb.  I'm inclined
to say that if we want to have pvusb driver domains (and I think we do),
we should just get rid of this information.

> diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
> index 9f6ec00..4844f18 100644
> --- a/tools/libxl/libxl_types.idl
> +++ b/tools/libxl/libxl_types.idl
> @@ -595,6 +595,35 @@ libxl_device_rdm = Struct("device_rdm", [
>      ("policy", libxl_rdm_reserve_policy),
>      ])
>  
> +libxl_usbctrl_type = Enumeration("usbctrl_type", [
> +    (0, "AUTO"),
> +    (1, "PV"),
> +    (2, "DEVICEMODEL"),
> +    ])
> +
> +libxl_usbdev_type = Enumeration("usbdev_type", [
> +    (1, "hostdev"),
> +    ])
> +
> +libxl_device_usbctrl = Struct("device_usbctrl", [
> +    ("type", libxl_usbctrl_type),
> +    ("devid", libxl_devid),
> +    ("version", integer),
> +    ("ports", integer),
> +    ("backend_domid", libxl_domid),
> +    ("backend_domname", string),
> +   ])
> +
> +libxl_device_usb = Struct("device_usb", [
> +    ("ctrl", libxl_devid),
> +    ("port", integer),
> +    ("u", KeyedUnion(None, libxl_usbdev_type, "devtype",
> +           [("hostdev", Struct(None, [
> +                 ("hostbus",   uint8),
> +                 ("hostaddr",  uint8)])),
> +           ])),
> +    ])
> +
>  libxl_device_dtdev = Struct("device_dtdev", [
>      ("path", string),
>      ])
> @@ -627,6 +656,8 @@ libxl_domain_config = Struct("domain_config", [
>      ("pcidevs", Array(libxl_device_pci, "num_pcidevs")),
>      ("rdms", Array(libxl_device_rdm, "num_rdms")),
>      ("dtdevs", Array(libxl_device_dtdev, "num_dtdevs")),
> +    ("usbctrls", Array(libxl_device_usbctrl, "num_usbctrls")),
> +    ("usbs", Array(libxl_device_usb, "num_usbs")),
>      ("vfbs", Array(libxl_device_vfb, "num_vfbs")),
>      ("vkbs", Array(libxl_device_vkb, "num_vkbs")),
>      ("vtpms", Array(libxl_device_vtpm, "num_vtpms")),
> @@ -676,6 +707,32 @@ libxl_vtpminfo = Struct("vtpminfo", [
>      ("uuid", libxl_uuid),
>      ], dir=DIR_OUT)
>  
> +libxl_usbctrlinfo = Struct("usbctrlinfo", [
> +    ("type", libxl_usbctrl_type),
> +    ("devid", libxl_devid),
> +    ("version", integer),
> +    ("ports", integer),
> +    ("backend", string),
> +    ("backend_id", uint32),
> +    ("frontend", string),
> +    ("frontend_id", uint32),
> +    ("state", integer),
> +    ("evtch", integer),
> +    ("ref_urb", integer),
> +    ("ref_conn", integer),
> +    ], dir=DIR_OUT)
> +
> +libxl_usbinfo = Struct("usbinfo", [
> +    ("ctrl", libxl_devid),
> +    ("port", integer),
> +    ("busnum", uint8),
> +    ("devnum", uint8),
> +    ("idVendor", uint16),
> +    ("idProduct", uint16),
> +    ("prod", string),
> +    ("manuf", string),
> +    ], dir=DIR_OUT)

With the exception of the stuff in libxl_usbinfo we can't get if the
backend isn't dom0, the interface looks good to me now.

OK, so I've covered four things:

1. The DEFINE_DEVICE_REMOVE_EXT macro.  I think I'd prefer checking in
things are as it is, and then have a follow-up patch to refactor
everything into a single DEFINE_DEVICE_REMOVE macro as described above.

2. COMPARE_USB.  I think this needs to be fixed; but this should be a
fairly simple change.

3. The conditional in libxl__device_destroy, the struct copy in
libxl_devid_to_device_usbctrl, and the modification of the device in
libxl_device_usb_getinfo are minor adjustments that can be discussed and
fixed.

4. The pvusb driver domain != dom0 comments.  This is somewhat secondary
to your primary goal; but at the moment the code will certainly not
work.  We have a couple of options:
a: Wait until we've fixed the driver domain functionality
b: Check the code in right now, with the driver domain fuctionality
explicitly disabled; that is, it will return an error if
backend_domain!=0.  Get a promise to implement the driver domain
functionality properly for 4.7 (on the threat of removing the feature).
c: Take driver domain support out of the interface for now; send
follow-up patches to implement it properly.
d. Take driver domain support out of the interface and leave it that
way, for simplicity.

I'd probably go with b or c.

Thoughts?

 -George

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 4/7] libxl: add libxl_device_usb_assignable_list API
  2015-09-25  2:11 ` [PATCH V7 4/7] libxl: add libxl_device_usb_assignable_list API Chunyan Liu
@ 2015-10-01 11:32   ` George Dunlap
  0 siblings, 0 replies; 59+ messages in thread
From: George Dunlap @ 2015-10-01 11:32 UTC (permalink / raw)
  To: Chunyan Liu, xen-devel
  Cc: jgross, wei.liu2, ian.campbell, george.dunlap, Ian.Jackson, jfehlig

On 25/09/15 03:11, Chunyan Liu wrote:
> Add API for listing assignable USB devices info.
> Assignable USB device means the USB device type is assignable and
> it's not assigned to any guest yet.
> 
> Signed-off-by: Chunyan Liu <cyliu@suse.com>
> ---
> This could be squashed with previous patch. Split because there is
> some dispute on this. If this is acceptable, could be squashed,
> otherwise could be removed.
> 
>  tools/libxl/libxl.h       |  3 +++
>  tools/libxl/libxl_pvusb.c | 55 +++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 58 insertions(+)
> 
> diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
> index 633bfc1..c41b9de 100644
> --- a/tools/libxl/libxl.h
> +++ b/tools/libxl/libxl.h
> @@ -1450,6 +1450,9 @@ int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid,
>                                   libxl_usbctrlinfo *usbctrlinfo);
>  
>  /* USB Devices */
> +libxl_device_usb *
> +libxl_device_usb_assignable_list(libxl_ctx *ctx, int *num);
> +
>  int libxl_device_usb_add(libxl_ctx *ctx, uint32_t domid, libxl_device_usb *usb,
>                           const libxl_asyncop_how *ao_how)
>                           LIBXL_EXTERNAL_CALLERS_ONLY;
> diff --git a/tools/libxl/libxl_pvusb.c b/tools/libxl/libxl_pvusb.c
> index d4b997f..b683e60 100644
> --- a/tools/libxl/libxl_pvusb.c
> +++ b/tools/libxl/libxl_pvusb.c
> @@ -573,6 +573,61 @@ static bool is_usb_assignable(libxl__gc *gc, libxl_device_usb *usb)
>      return classcode != USBHUB_CLASS_CODE;
>  }
>  
> +libxl_device_usb *
> +libxl_device_usb_assignable_list(libxl_ctx *ctx, int *num)
> +{
> +    GC_INIT(ctx);
> +    libxl_device_usb *usbs = NULL;
> +    libxl_device_usb *assigned;
> +    int num_assigned;
> +    struct dirent *de;
> +    DIR *dir;
> +
> +    *num = 0;
> +
> +    if (get_assigned_devices(gc, &assigned, &num_assigned) < 0) {
> +        LOG(ERROR, "cannot determine if device is assigned");
> +        goto out;
> +    }
> +
> +    if (!(dir = opendir(SYSFS_USB_DEV)))
> +        goto out;
> +
> +    while ((de = readdir(dir))) {
> +        libxl_device_usb *usb;
> +        uint8_t bus = -1, addr = -1;
> +
> +        if (!de->d_name)
> +            continue;
> +
> +        usb_busaddr_from_busid(gc, de->d_name, &bus, &addr);
> +        if (bus < 1 || addr < 1)
> +            continue;
> +
> +        GCNEW(usb);
> +        usb->u.hostdev.hostbus = bus;
> +        usb->u.hostdev.hostaddr = addr;
> +
> +        if (!is_usb_assignable(gc, usb))
> +            continue;
> +
> +        if (is_usbdev_in_array(assigned, num_assigned, usb))
> +            continue;

Why are we allocating a new usb struct every loop, and then never using
it again?  Why not just put it on the stack and re-use it?

Other than that, looks OK.

 -George

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 5/7] xl: add pvusb commands
  2015-09-25  2:11 ` [PATCH V7 5/7] xl: add pvusb commands Chunyan Liu
@ 2015-10-01 17:02   ` George Dunlap
  2015-10-02 13:35     ` Ian Campbell
  2015-10-09  7:15     ` Chun Yan Liu
  0 siblings, 2 replies; 59+ messages in thread
From: George Dunlap @ 2015-10-01 17:02 UTC (permalink / raw)
  To: Chunyan Liu, xen-devel
  Cc: jgross, wei.liu2, ian.campbell, george.dunlap, Ian.Jackson,
	jfehlig, Simon Cao

On 25/09/15 03:11, Chunyan Liu wrote:
> Add pvusb commands: usb-ctrl-attach, usb-ctrl-detach, usb-list,
> usb-attach and usb-detach.
> 
> To attach a usb device to guest through pvusb, one could follow
> following example:
> 
>  #xl usb-ctrl-attach test_vm version=1 num_ports=8

So all the way back in v2 of this series, I suggested making the
arguments for usb-ctrl-attach and usb-attach mirror the format that is
found in the config file[1], at which point you replied "That could be,
I can update".  But you didn't change the interface in v3, so I
suggested it again[2], and there was no argument or discussion about it.

(There was a long back-and-forth with Juergen at that point about
usb-assignable-list, so [2] may have gotten lost in the noise.)

I still think that's the best interface to use.  Do you have reasons to
favor the interface you propose here?

 -George

[1]
marc.info/?i=<CAFLBxZb1N3_9PVvg-yC8dyVaiySZVRA3H2e8496vHNEfvrm6Zg@mail.gmail.com>

[2]
marc.info/?i=<CAFLBxZbJcdFi2cXOvQRncbdV0HBL73d8sjXKry+VaRjvkQtRwA@mail.gmail.com>

> 
>  #xl usb-list test_vm
>  will show the usb controllers and port usage under the domain.
> 
>  #xl usb-attach test_vm 1.6
>  will find the first usable controller:port, and attach usb
>  device whose bus address is 1.6 (busnum is 1, devnum is 6)
>  to it. One could also specify which <controller> and which <port>.
> 
>  #xl usb-detach test_vm 0 1
>  will detach USB device under controller 0 port 1.
> 
>  #xl usb-ctrl-detach test_vm dev_id
>  will destroy the controller with specified dev_id. Dev_id
>  can be traced in usb-list info.
> 
> Signed-off-by: Chunyan Liu <cyliu@suse.com>
> Signed-off-by: Simon Cao <caobosimon@gmail.com>
> ---
>  docs/man/xl.pod.1         |  40 ++++++++
>  tools/libxl/xl.h          |   5 +
>  tools/libxl/xl_cmdimpl.c  | 232 ++++++++++++++++++++++++++++++++++++++++++++++
>  tools/libxl/xl_cmdtable.c |  25 +++++
>  4 files changed, 302 insertions(+)
> 
> diff --git a/docs/man/xl.pod.1 b/docs/man/xl.pod.1
> index f22c3f3..4c92c78 100644
> --- a/docs/man/xl.pod.1
> +++ b/docs/man/xl.pod.1
> @@ -1345,6 +1345,46 @@ List pass-through pci devices for a domain.
>  
>  =back
>  
> +=head1 USB PASS-THROUGH
> +
> +=over 4
> +
> +=item B<usb-ctrl-attach> I<domain-id> I[<type=val>] [I<version=val>] [I<ports=number>]
> +
> +Create a new USB controller for the specified domain.
> +B<type=val> is the usb controller type, currently only support 'pv'.
> +B<version=val> is the usb controller version, could be 1 (USB1.1) or 2 (USB2.0).
> +B<ports=number> is the total ports of the usb controller.
> +By default, it will create a USB2.0 controller with 8 ports.
> +
> +=item B<usb-ctrl-detach> I<domain-id> I<devid>
> +
> +Destroy a USB controller from the specified domain.
> +B<devid> is devid of the USB controller.
> +
> +If B<-f> is specified, B<xl> is going to forcefully remove the device even
> +without guest's collaboration.
> +
> +=item B<usb-attach> I<domain-id> I<bus.addr> [I<controller=devid> [I<port=number>]]
> +
> +Hot-plug a new pass-through USB device to the specified domain.
> +B<bus.addr> is the busnum.devnum of the physical USB device to pass-through.
> +B<controller=devid> B<port=number> is the USB controller:port to hotplug the
> +USB device to. By default, it will find the first available controller:port
> +and use it; if there is no controller, it will create one.
> +
> +=item B<usb-detach> I<domain-id> I<controller=devid> I<port=number>
> +
> +Hot-unplug a previously assigned USB device from a domain.
> +B<controller=devid> and B<port=number> is USB controller:port in guest where the
> +USB device is attached to.
> +
> +=item B<usb-list> I<domain-id>
> +
> +List pass-through usb devices for a domain.
> +
> +=back
> +
>  =head1 TMEM
>  
>  =over 4
> diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h
> index 6c19c0d..26f6c1e 100644
> --- a/tools/libxl/xl.h
> +++ b/tools/libxl/xl.h
> @@ -85,6 +85,11 @@ int main_blockdetach(int argc, char **argv);
>  int main_vtpmattach(int argc, char **argv);
>  int main_vtpmlist(int argc, char **argv);
>  int main_vtpmdetach(int argc, char **argv);
> +int main_usbctrl_attach(int argc, char **argv);
> +int main_usbctrl_detach(int argc, char **argv);
> +int main_usbattach(int argc, char **argv);
> +int main_usbdetach(int argc, char **argv);
> +int main_usblist(int argc, char **argv);
>  int main_uptime(int argc, char **argv);
>  int main_claims(int argc, char **argv);
>  int main_tmem_list(int argc, char **argv);
> diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
> index 2706759..6ae9479 100644
> --- a/tools/libxl/xl_cmdimpl.c
> +++ b/tools/libxl/xl_cmdimpl.c
> @@ -3367,6 +3367,238 @@ int main_cd_insert(int argc, char **argv)
>      return 0;
>  }
>  
> +int main_usbctrl_attach(int argc, char **argv)
> +{
> +    uint32_t domid;
> +    int opt, rc = 1;
> +    char *oparg;
> +    libxl_device_usbctrl usbctrl;
> +
> +    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-ctrl-attach", 1) {
> +        /* No options */
> +    }
> +
> +    domid = find_domain(argv[optind++]);
> +
> +    libxl_device_usbctrl_init(&usbctrl);
> +
> +    while (argc > optind) {
> +        if (MATCH_OPTION("type", argv[optind], oparg)) {
> +            if (!strcmp(oparg, "pv")) {
> +                usbctrl.type = LIBXL_USBCTRL_TYPE_PV;
> +            } else {
> +                fprintf(stderr, "unsupported type `%s'\n", oparg);
> +                goto out;
> +            }
> +        } else if (MATCH_OPTION("version", argv[optind], oparg)) {
> +            usbctrl.version = atoi(oparg);
> +            if (usbctrl.version != 1 && usbctrl.version != 2) {
> +                fprintf(stderr, "unsupported version `%s'\n", oparg);
> +                goto out;
> +            }
> +        } else if (MATCH_OPTION("ports", argv[optind], oparg)) {
> +            usbctrl.ports = atoi(oparg);
> +            if (usbctrl.ports < 1 || usbctrl.ports > 31) {
> +                fprintf(stderr, "unsupported ports `%s'\n", oparg);
> +                goto out;
> +            }
> +        } else {
> +            fprintf(stderr, "unrecognized argument `%s'\n", argv[optind]);
> +            goto out;
> +        }
> +        optind++;
> +    }
> +
> +    rc = libxl_device_usbctrl_add(ctx, domid, &usbctrl, 0);
> +    if (rc)
> +        fprintf(stderr, "libxl_device_usbctrl_add failed.\n");
> +
> +out:
> +    libxl_device_usbctrl_dispose(&usbctrl);
> +    return rc;
> +}
> +
> +int main_usbctrl_detach(int argc, char **argv)
> +{
> +    uint32_t domid;
> +    int opt, devid, rc;
> +    libxl_device_usbctrl usbctrl;
> +
> +    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-ctrl-detach", 2) {
> +        /* No options */
> +    }
> +
> +    domid = find_domain(argv[optind]);
> +    devid = atoi(argv[optind+1]);
> +
> +    libxl_device_usbctrl_init(&usbctrl);
> +    if (libxl_devid_to_device_usbctrl(ctx, domid, devid, &usbctrl)) {
> +        fprintf(stderr, "Unknown device %s.\n", argv[optind+1]);
> +        return 1;
> +    }
> +
> +    rc = libxl_device_usbctrl_remove(ctx, domid, &usbctrl, 0);
> +    if (rc)
> +        fprintf(stderr, "libxl_device_usbctrl_remove failed.\n");
> +
> +    libxl_device_usbctrl_dispose(&usbctrl);
> +    return rc;
> +
> +}
> +
> +int main_usbattach(int argc, char **argv)
> +{
> +    uint32_t domid;
> +    char *devname, *p;
> +    int opt, rc = 1;
> +    char *oparg;
> +    libxl_device_usb usb;
> +
> +    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-attach", 2) {
> +        /* No options */
> +    }
> +
> +    libxl_device_usb_init(&usb);
> +
> +    domid = find_domain(argv[optind++]);
> +    devname = argv[optind++];
> +    p = strchr(devname, '.');
> +    if (p) {
> +        usb.u.hostdev.hostbus = strtoul(devname, NULL, 0);
> +        usb.u.hostdev.hostaddr = strtoul(p + 1, NULL, 0);
> +    }
> +
> +    if (usb.u.hostdev.hostbus < 1 || usb.u.hostdev.hostaddr < 1) {
> +        fprintf(stderr, "Invalid usb device.\n");
> +        goto out;
> +    }
> +
> +    while (argc > optind) {
> +        if (MATCH_OPTION("controller", argv[optind], oparg)) {
> +            usb.ctrl = atoi(oparg);
> +        } else if (MATCH_OPTION("port", argv[optind], oparg)) {
> +            usb.port = atoi(oparg);
> +        } else {
> +            fprintf(stderr, "unrecognized argument `%s'\n", argv[optind]);
> +            goto out;
> +        }
> +        optind++;
> +    }
> +
> +    rc = libxl_device_usb_add(ctx, domid, &usb, 0);
> +    if (rc)
> +        fprintf(stderr, "libxl_device_usb_add failed.\n");
> +
> +out:
> +    libxl_device_usb_dispose(&usb);
> +    return rc;
> +}
> +
> +int main_usbdetach(int argc, char **argv)
> +{
> +    uint32_t domid;
> +    int ctrl, port;
> +    int opt, rc = 1;
> +    libxl_device_usb usb;
> +
> +    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-detach", 3) {
> +        /* No options */
> +    }
> +
> +    domid = find_domain(argv[optind]);
> +    ctrl = atoi(argv[optind+1]);
> +    port = atoi(argv[optind+2]);
> +
> +    if (argc - optind > 3) {
> +        fprintf(stderr, "Invalid arguments.\n");
> +        goto out;
> +    }
> +
> +    libxl_device_usb_init(&usb);
> +    if (libxl_ctrlport_to_device_usb(ctx, domid, ctrl, port, &usb)) {
> +        fprintf(stderr, "Unknown device at controller %d port %d.\n",
> +                ctrl, port);
> +        goto out;
> +    }
> +
> +    rc = libxl_device_usb_remove(ctx, domid, &usb, 0);
> +    if (rc)
> +        fprintf(stderr, "libxl_device_usb_remove failed.\n");
> +
> +out:
> +    libxl_device_usb_dispose(&usb);
> +    return rc;
> +}
> +
> +int main_usblist(int argc, char **argv)
> +{
> +    uint32_t domid;
> +    libxl_device_usbctrl *usbctrls;
> +    libxl_usbctrlinfo usbctrlinfo;
> +    int numctrl, i, j, opt;
> +
> +    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-list", 1) {
> +        /* No options */
> +    }
> +
> +    domid = find_domain(argv[optind++]);
> +
> +    if (argc > optind) {
> +        fprintf(stderr, "Invalid arguments.\n");
> +        exit(-1);
> +    }
> +
> +    usbctrls = libxl_device_usbctrl_list(ctx, domid, &numctrl);
> +    if (!usbctrls) {
> +        return 0;
> +    }
> +
> +    for (i = 0; i < numctrl; ++i) {
> +        printf("%-6s %-6s %-3s %-5s %-7s %-5s %-30s\n",
> +                "Devid", "Type", "BE", "state", "usb-ver", "ports", "BE-path");
> +
> +        libxl_usbctrlinfo_init(&usbctrlinfo);
> +
> +        if (!libxl_device_usbctrl_getinfo(ctx, domid,
> +                                &usbctrls[i], &usbctrlinfo)) {
> +            printf("%-6d %-6s %-3d %-5d %-7d %-5d %-30s\n",
> +                    usbctrlinfo.devid,
> +                    libxl_usbctrl_type_to_string(usbctrlinfo.type),
> +                    usbctrlinfo.backend_id, usbctrlinfo.state,
> +                    usbctrlinfo.version, usbctrlinfo.ports,
> +                    usbctrlinfo.backend);
> +
> +            for (j = 1; j <= usbctrlinfo.ports; j++) {
> +                libxl_device_usb usb;
> +                libxl_usbinfo usbinfo;
> +
> +                libxl_device_usb_init(&usb);
> +                libxl_usbinfo_init(&usbinfo);
> +
> +                printf("  Port %d:", j);
> +
> +                usb.ctrl = usbctrlinfo.devid;
> +                usb.port = j;
> +                if (!libxl_device_usb_getinfo(ctx, domid, &usb, &usbinfo)) {
> +                    printf(" Bus %03x Device %03x: ID %04x:%04x %s %s\n",
> +                            usbinfo.busnum, usbinfo.devnum,
> +                            usbinfo.idVendor, usbinfo.idProduct,
> +                            usbinfo.manuf ?: "", usbinfo.prod ?: "");
> +                } else {
> +                    printf("\n");
> +                }
> +                libxl_usbinfo_dispose(&usbinfo);
> +                libxl_device_usb_dispose(&usb);
> +            }
> +        }
> +
> +        libxl_usbctrlinfo_dispose(&usbctrlinfo);
> +    }
> +
> +    libxl_device_usbctrl_list_free(usbctrls, numctrl);
> +    return 0;
> +}
> +
>  int main_console(int argc, char **argv)
>  {
>      uint32_t domid;
> diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c
> index 0071f12..46f276e 100644
> --- a/tools/libxl/xl_cmdtable.c
> +++ b/tools/libxl/xl_cmdtable.c
> @@ -551,6 +551,31 @@ struct cmd_spec cmd_table[] = {
>      },
>  
>  #endif
> +    { "usb-ctrl-attach",
> +      &main_usbctrl_attach, 0, 1,
> +      "Create a virtual USB controller for a domain",
> +      "<Domain> [type=pv] [version=<version>] [ports=<number>]",
> +    },
> +    { "usb-ctrl-detach",
> +      &main_usbctrl_detach, 0, 1,
> +      "Remove the virtual USB controller specified by <DevId> for a domain",
> +      "<Domain> <DevId>",
> +    },
> +    { "usb-attach",
> +      &main_usbattach, 0, 1,
> +      "Attach a USB device to a domain",
> +      "<Domain> <bus.addr> [controller=<DevId> [port=<port>]]",
> +    },
> +    { "usb-detach",
> +      &main_usbdetach, 0, 1,
> +      "Detach a USB device from a domain",
> +      "<Domain> <controller> <port>",
> +    },
> +    { "usb-list",
> +      &main_usblist, 0, 0,
> +      "List information about USB devices for a domain",
> +      "<Domain>",
> +    },
>  };
>  
>  int cmdtable_len = sizeof(cmd_table)/sizeof(struct cmd_spec);
> 

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 2/7] libxl_read_file_contents: add new entry to read sysfs file
  2015-09-25  2:11 ` [PATCH V7 2/7] libxl_read_file_contents: add new entry to read sysfs file Chunyan Liu
  2015-09-30 11:22   ` George Dunlap
@ 2015-10-02 13:25   ` Ian Campbell
  1 sibling, 0 replies; 59+ messages in thread
From: Ian Campbell @ 2015-10-02 13:25 UTC (permalink / raw)
  To: Chunyan Liu, xen-devel
  Cc: george.dunlap, wei.liu2, jfehlig, Ian.Jackson, jgross

On Fri, 2015-09-25 at 10:11 +0800, Chunyan Liu wrote:
> Sysfs file has size=4096 but actual file content is less than that.
> Current libxl_read_file_contents will treat it as error when file size
> and actual file content differs, so reading sysfs file content with
> this function always fails.
> 
> Add a new entry libxl_read_sysfs_file_contents to handle sysfs file
> specially. It would be used in later pvusb work.
> 
> Signed-off-by: Chunyan Liu <cyliu@suse.com>
> Reviewed-by: Wei Liu <wei.liu2@citrix.com>

I'm afraid I have one issue with this patch, sorry.

> @@ -4015,6 +4015,8 @@ void libxl__bitmap_copy_best_effort(libxl__gc *gc, libxl_bitmap *dptr,
>  
>  int libxl__count_physical_sockets(libxl__gc *gc, int *sockets);
>  #endif
> +_hidden int libxl_read_sysfs_file_contents(libxl_ctx *ctx, const char *filename,
> +                                   void **data_r, int *datalen_r);

As an internal function this should be called libxl__foo (double
underscore) and take a libxl__gc *gc not libxl_ctx *ctx.

This will require some other subtle adjustments which I'll outline below.

diff --git a/tools/libxl/libxl_utils.c b/tools/libxl/libxl_utils.c
> index bfc9699..72f8f4f 100644
> --- a/tools/libxl/libxl_utils.c
> +++ b/tools/libxl/libxl_utils.c
> @@ -322,8 +322,10 @@ out:
>      return rc;
>  }
>  
> -int libxl_read_file_contents(libxl_ctx *ctx, const char *filename,
> -                             void **data_r, int *datalen_r) {
> +static int libxl_read_file_contents_core(libxl_ctx *ctx, const char *filename,

Being static this can now get a shorter name. Perhaps just
read_file_contents_core (or even drop the _core). It should also take a gc
instead of a ctx, since it will be used by both internal and external
facing wrappers.

> +                                         void **data_r, int *datalen_r,
> +                                         bool tolerate_shrinking_file)
> +{
>      GC_INIT(ctx);

Having changed the function to take a gc you will instead want to do this
GC_INIT(ctx) in the libxl_read_file_contents public interface wrapper,
which will then give you the gc to pass here.

You will likewise need to do the GC_FREE in that wrapper too instead of
here.

@@ -396,6 +413,19 @@ int libxl_read_file_contents(libxl_ctx *ctx, const
> char *filename,
>      return e;
>  }
>  
> +int libxl_read_file_contents(libxl_ctx *ctx, const char *filename,
> +                             void **data_r, int *datalen_r)
> +{
> +    return libxl_read_file_contents_core(ctx, filename, data_r,
> datalen_r, 0);

As above this will need the GC_INIT and GC_FREE stuff doing here.

libxl_cpupool_info() looks like a good template to follow.

> +}
> +
> +int libxl_read_sysfs_file_contents(libxl_ctx *ctx, const char *filename,
> +                                   void **data_r, int *datalen_r)
> +{
> +    return libxl_read_file_contents_core(ctx, filename, data_r,
> datalen_r, 1);

While this should take a gc and can just pass it on.

Ian.

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 3/7] libxl: add pvusb API
  2015-09-30 17:55   ` George Dunlap
@ 2015-10-02 13:31     ` Ian Campbell
  2015-10-09  8:12     ` Chun Yan Liu
  2015-10-12  7:19     ` Chun Yan Liu
  2 siblings, 0 replies; 59+ messages in thread
From: Ian Campbell @ 2015-10-02 13:31 UTC (permalink / raw)
  To: George Dunlap, Chunyan Liu, xen-devel
  Cc: jgross, wei.liu2, george.dunlap, Ian.Jackson, jfehlig, Simon Cao

On Wed, 2015-09-30 at 18:55 +0100, George Dunlap wrote:

> > +int libxl_devid_to_device_usbctrl(libxl_ctx *ctx,
> > +                                  uint32_t domid,
> > +                                  int devid,
> > +                                  libxl_device_usbctrl *usbctrl)
> > +{
> > +    GC_INIT(ctx);
> > +    libxl_device_usbctrl *usbctrls;
> > +    int nb = 0;
> > +    int i, rc = -1;
> > +
> > +    usbctrls = libxl_device_usbctrl_list(ctx, domid, &nb);
> > +    if (!nb) goto out;
> > +
> > +    for (i = 0; i < nb; i++) {
> > +        if (devid == usbctrls[i].devid) {
> > +            *usbctrl = usbctrls[i];
> 
> libxl maintainers: Is this kind of copying OK?
> 
> The analog functions for vtpm and nic both take very different
> approaches; both call libxl_device_[type]_init() and then fill in
> individual elements (albeit in different ways).

That depends on the memory lifecycle situation of usbctrls[i] and *usbctrl
vis-a-vis the gc and when they are frred.

Cut out of the context here is a 
+    libxl_device_usbctrl_list_free(usbctrls, nb);

which is going to free any of the pointers in usbctrls[i] which have been
copied to usbctrl. So in this case no it is not ok.

You can't avoid the libxl_device_usbctrl_list_free, since you don't want to
leak all the other elements on the list, so copying seems to be the way to
go.

The IDL should have generated a copy function which can be used (by the
vtpm one too, but it predates the IDL making such things I think).

> 
> > +/*
> > + * USB add
> > + */
> > +static int do_usb_add(libxl__gc *gc, uint32_t domid,
> > +                      libxl_device_usb *usbdev,
> > +                      libxl__ao_device *aodev)
> > +{
> > +    libxl_ctx *ctx = CTX;
> > +    libxl_usbctrlinfo usbctrlinfo;
> > +    libxl_device_usbctrl usbctrl;
> > +    int rc;
> > +
> > +    libxl_usbctrlinfo_init(&usbctrlinfo);
> > +    usbctrl.devid = usbdev->ctrl;
> > +    rc = libxl_device_usbctrl_getinfo(ctx, domid, &usbctrl,
> > &usbctrlinfo);
> > +    if (rc)
> > +        goto out;
> > +
> > +    switch (usbctrlinfo.type) {
> > +    case LIBXL_USBCTRL_TYPE_DEVICEMODEL:
> > +        LOG(ERROR, "Not supported");
> > +        break;
> > +    case LIBXL_USBCTRL_TYPE_PV:
> > +        rc = libxl__device_usb_add_xenstore(gc, domid, usbdev,
> > +                                            aodev->update_json);
> > +        if (rc) goto out;
> > +
> > +        rc = usbback_dev_assign(gc, usbdev);
> 
> This assumes that the usb controller is dom0; but the interface
> explicitly allows pvusb driver domains.
> 
> I think it would be enough here to do this check if the usbctrl device
> is dom0.  We should then assume that a pvusb driver domain will be
> configured with all usb devices assigned to usbback already.
> 
> I assume that there's a feedback mechanisms for backends for situations
> where the requested device can't be made, right?  For example, if you
> have a network driver domain and request a non-existent bridge?  If so,
> I think we can let the same mechanism worth for pvusb backends to say "I
> don't have that device available".

I think the b/e writes an error node in xenstore, which we already pickup
iirc.

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 5/7] xl: add pvusb commands
  2015-10-01 17:02   ` George Dunlap
@ 2015-10-02 13:35     ` Ian Campbell
  2015-10-02 15:17       ` George Dunlap
  2015-10-09  7:15     ` Chun Yan Liu
  1 sibling, 1 reply; 59+ messages in thread
From: Ian Campbell @ 2015-10-02 13:35 UTC (permalink / raw)
  To: George Dunlap, Chunyan Liu, xen-devel
  Cc: jgross, wei.liu2, george.dunlap, Ian.Jackson, jfehlig, Simon Cao

On Thu, 2015-10-01 at 18:02 +0100, George Dunlap wrote:
> On 25/09/15 03:11, Chunyan Liu wrote:
> > Add pvusb commands: usb-ctrl-attach, usb-ctrl-detach, usb-list,
> > usb-attach and usb-detach.
> > 
> > To attach a usb device to guest through pvusb, one could follow
> > following example:
> > 
> >  #xl usb-ctrl-attach test_vm version=1 num_ports=8
> 
> So all the way back in v2 of this series, I suggested making the
> arguments for usb-ctrl-attach and usb-attach mirror the format that is
> found in the config file[1]
> [...]
> [1]
> marc.info/?i=<
> CAFLBxZb1N3_9PVvg-yC8dyVaiySZVRA3H2e8496vHNEfvrm6Zg@mail.gmail.com>

Re: xl usb-ctrl-attach test_vm name=pv-1,type=pv,version=1,ports=8

FWIW I think most of the existing ones allow (but don't require) a slight
difference in the cli version, which is that they allow space spearated
lists as well as command separate, which ends up a bit more natural:

    xl usb-ctrl-attach test_vm name=pv-1 type=pv version=1 ports=8

I also agree that we should try and do something similar here unless there
is a compelling reason we can't.

Ian.

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 5/7] xl: add pvusb commands
  2015-10-02 13:35     ` Ian Campbell
@ 2015-10-02 15:17       ` George Dunlap
  2015-10-02 15:29         ` Ian Campbell
  0 siblings, 1 reply; 59+ messages in thread
From: George Dunlap @ 2015-10-02 15:17 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Jürgen Groß,
	Wei Liu, Ian Jackson, George Dunlap, xen-devel, Jim Fehlig,
	Simon Cao, Chunyan Liu

On Fri, Oct 2, 2015 at 2:35 PM, Ian Campbell <ian.campbell@citrix.com> wrote:
> On Thu, 2015-10-01 at 18:02 +0100, George Dunlap wrote:
>> On 25/09/15 03:11, Chunyan Liu wrote:
>> > Add pvusb commands: usb-ctrl-attach, usb-ctrl-detach, usb-list,
>> > usb-attach and usb-detach.
>> >
>> > To attach a usb device to guest through pvusb, one could follow
>> > following example:
>> >
>> >  #xl usb-ctrl-attach test_vm version=1 num_ports=8
>>
>> So all the way back in v2 of this series, I suggested making the
>> arguments for usb-ctrl-attach and usb-attach mirror the format that is
>> found in the config file[1]
>> [...]
>> [1]
>> marc.info/?i=<
>> CAFLBxZb1N3_9PVvg-yC8dyVaiySZVRA3H2e8496vHNEfvrm6Zg@mail.gmail.com>
>
> Re: xl usb-ctrl-attach test_vm name=pv-1,type=pv,version=1,ports=8
>
> FWIW I think most of the existing ones allow (but don't require) a slight
> difference in the cli version, which is that they allow space spearated
> lists as well as command separate, which ends up a bit more natural:
>
>     xl usb-ctrl-attach test_vm name=pv-1 type=pv version=1 ports=8
>
> I also agree that we should try and do something similar here unless there
> is a compelling reason we can't.

I didn't realize that. +1

 -George

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 5/7] xl: add pvusb commands
  2015-10-02 15:17       ` George Dunlap
@ 2015-10-02 15:29         ` Ian Campbell
  0 siblings, 0 replies; 59+ messages in thread
From: Ian Campbell @ 2015-10-02 15:29 UTC (permalink / raw)
  To: George Dunlap
  Cc: Jürgen Groß,
	Wei Liu, Ian Jackson, George Dunlap, xen-devel, Jim Fehlig,
	Simon Cao, Chunyan Liu

On Fri, 2015-10-02 at 16:17 +0100, George Dunlap wrote:
> On Fri, Oct 2, 2015 at 2:35 PM, Ian Campbell <ian.campbell@citrix.com>
> wrote:
> > On Thu, 2015-10-01 at 18:02 +0100, George Dunlap wrote:
> > > On 25/09/15 03:11, Chunyan Liu wrote:
> > > > Add pvusb commands: usb-ctrl-attach, usb-ctrl-detach, usb-list,
> > > > usb-attach and usb-detach.
> > > > 
> > > > To attach a usb device to guest through pvusb, one could follow
> > > > following example:
> > > > 
> > > >  #xl usb-ctrl-attach test_vm version=1 num_ports=8
> > > 
> > > So all the way back in v2 of this series, I suggested making the
> > > arguments for usb-ctrl-attach and usb-attach mirror the format that
> > > is
> > > found in the config file[1]
> > > [...]
> > > [1]
> > > marc.info/?i=<
> > > CAFLBxZb1N3_9PVvg-yC8dyVaiySZVRA3H2e8496vHNEfvrm6Zg@mail.gmail.com>
> > 
> > Re: xl usb-ctrl-attach test_vm name=pv-1,type=pv,version=1,ports=8
> > 
> > FWIW I think most of the existing ones allow (but don't require) a
> > slight
> > difference in the cli version, which is that they allow space spearated
> > lists as well as command separate, which ends up a bit more natural:
> > 
> >     xl usb-ctrl-attach test_vm name=pv-1 type=pv version=1 ports=8
> > 
[...]

BTW this is generally pretty easy to arrange, You have a helper:
    parse_foo(const char *s, libxl_foo *foo) 
which takes a comma separate list "s" and _incremntally_ updates the object
"foo" which it was given.

Then when parsing the cfg file you call parse_foo on the string and when
parsing the command line you call parse_foo for every argv (with the same
object).

See e.g. parse_nic_config in xl_cmdimpl.c.

Disk does it a bit differently with parse_disk_config and
parse_disk_config_multistring, where the latter effectively incorporates
the loop over argv.

Ian.

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-09-25  2:11 ` [PATCH V7 6/7] xl: add usb-assignable-list command Chunyan Liu
@ 2015-10-06 16:55   ` George Dunlap
  2015-10-07  8:40     ` Ian Campbell
  0 siblings, 1 reply; 59+ messages in thread
From: George Dunlap @ 2015-10-06 16:55 UTC (permalink / raw)
  To: Chunyan Liu, xen-devel
  Cc: jgross, wei.liu2, ian.campbell, george.dunlap, Ian.Jackson, jfehlig

On 25/09/15 03:11, Chunyan Liu wrote:
> Add xl usb-assignable-list command to list assignable USB devices.
> Assignable USB device means the USB device type is assignable and
> it's not assigned to any guest yet.
> 
> Signed-off-by: Chunyan Liu <cyliu@suse.com>
> 
> ---
>   Same as "libxl: add libxl_device_usb_assignable_list API" patch,
>   this patch could be sqaushed to previous one. Split because of
>   some dispute. Could be squashed if acceptable, otherwise could
>   be removed.

I think it's worth pointing out to other reviewers that the
"usb-assignable-list" command introduced here:
1. Has identical behavior to "xm usb-assignable-list", but
2. Has different behavior than "xl pci-assignable-list".

Namely:

xl pci-assignable-list will list PCI devices which have been detached
from their normal driver and have been assigned to pciback (in
preparation for being attached to a domain).

This command will list all USB devices in dom0 that are not assigned to VMs.

Juergen and I had a long back-and-forth about it around v3.  I thought
having slightly different semantics might be confusing, and Juergen
thought the functionality was important to include.  We didn't really
come to a conclusion and none of the tools maintainers expressed an opinion.

I don't feel like arguing about it anymore, so I won't oppose the
naming; but I think whoever gives final approval should at least be
aware of the slight functional difference between {pci,usb}-assignable-list.

Other than that, the patch looks good to me.

 -George

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-06 16:55   ` George Dunlap
@ 2015-10-07  8:40     ` Ian Campbell
  2015-10-07  9:55       ` Juergen Gross
  2015-10-07 10:10       ` George Dunlap
  0 siblings, 2 replies; 59+ messages in thread
From: Ian Campbell @ 2015-10-07  8:40 UTC (permalink / raw)
  To: George Dunlap, Chunyan Liu, xen-devel
  Cc: george.dunlap, wei.liu2, jfehlig, Ian.Jackson, jgross

On Tue, 2015-10-06 at 17:55 +0100, George Dunlap wrote:
> On 25/09/15 03:11, Chunyan Liu wrote:
> > Add xl usb-assignable-list command to list assignable USB devices.
> > Assignable USB device means the USB device type is assignable and
> > it's not assigned to any guest yet.
> > 
> > Signed-off-by: Chunyan Liu <cyliu@suse.com>
> > 
> > ---
> >   Same as "libxl: add libxl_device_usb_assignable_list API" patch,
> >   this patch could be sqaushed to previous one. Split because of
> >   some dispute. Could be squashed if acceptable, otherwise could
> >   be removed.
> 
> I think it's worth pointing out to other reviewers that the
> "usb-assignable-list" command introduced here:
> 1. Has identical behavior to "xm usb-assignable-list", but
> 2. Has different behavior than "xl pci-assignable-list".

OOI how does xl pci-assignable-list compare to xm pci-assignable-list.

> Namely:
> 
> xl pci-assignable-list will list PCI devices which have been detached
> from their normal driver and have been assigned to pciback (in
> preparation for being attached to a domain).
> 
> This command will list all USB devices in dom0 that are not assigned to
> VMs.
> 
> Juergen and I had a long back-and-forth about it around v3.  I thought
> having slightly different semantics might be confusing, and Juergen
> thought the functionality was important to include.  We didn't really
> come to a conclusion and none of the tools maintainers expressed an
> opinion.

TBH I couldn't follow precisely what that discussion was about, so thanks
for your summary. IMHO you both make good points.

However given that xend was now removed 2 releases ago I think the time for
strictly mimicking xm behaviour purely for the sake of that
compatibility/transition has passed.

Obviously if the xm interface was fine we shouldn't deviate from it just to
be contrary, but similarly if the xm interface was bad in some way or
doesn't fit in with the direction xl has taken since the two coexisted then
we shouldn't feel bound to follow xm.

In this case and at this point in time I think I find the argument that xl
subcommands should, where possible, behave similarly to each other more
compelling than they should match their xm counterparts. (maybe if we'd
been aware of it we would have implemented pci-assignable-list differently,
but that ship has sailed).

So IMHO xl usb-assignable-list should behave like pci-assignable-list by
default.

Now, maybe it should also support some sort of --all or --full or --host
option which lists everything, ideally with some indication as to whether
they are attached to usbback or not and using syntax which can just be cut
-and-pasted into a cfg file (without at least one of those it's just a
pointless reimplementation of lsusb).

However I think --all/full/host is an optional extra.

/me wonders if xl ought to adjust it's behaviour in various ways when
called with $0==xm.

/me beats himself with sticks.

Ian.

> 

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07  8:40     ` Ian Campbell
@ 2015-10-07  9:55       ` Juergen Gross
  2015-10-07 10:08         ` Ian Campbell
  2015-10-07 10:10       ` George Dunlap
  1 sibling, 1 reply; 59+ messages in thread
From: Juergen Gross @ 2015-10-07  9:55 UTC (permalink / raw)
  To: Ian Campbell, George Dunlap, Chunyan Liu, xen-devel
  Cc: george.dunlap, wei.liu2, jfehlig, Ian.Jackson

On 10/07/2015 10:40 AM, Ian Campbell wrote:
> On Tue, 2015-10-06 at 17:55 +0100, George Dunlap wrote:
>> On 25/09/15 03:11, Chunyan Liu wrote:
>>> Add xl usb-assignable-list command to list assignable USB devices.
>>> Assignable USB device means the USB device type is assignable and
>>> it's not assigned to any guest yet.
>>>
>>> Signed-off-by: Chunyan Liu <cyliu@suse.com>
>>>
>>> ---
>>>    Same as "libxl: add libxl_device_usb_assignable_list API" patch,
>>>    this patch could be sqaushed to previous one. Split because of
>>>    some dispute. Could be squashed if acceptable, otherwise could
>>>    be removed.
>>
>> I think it's worth pointing out to other reviewers that the
>> "usb-assignable-list" command introduced here:
>> 1. Has identical behavior to "xm usb-assignable-list", but
>> 2. Has different behavior than "xl pci-assignable-list".
>
> OOI how does xl pci-assignable-list compare to xm pci-assignable-list.
>
>> Namely:
>>
>> xl pci-assignable-list will list PCI devices which have been detached
>> from their normal driver and have been assigned to pciback (in
>> preparation for being attached to a domain).

Assigning a PCI device to pciback is a necessary step to be able to
attach it to a domain.

>> This command will list all USB devices in dom0 that are not assigned to
>> VMs.

Attaching a USB device to a domain works by detaching it from it's
normal driver and attaching it to the pvUSB backend. And this backend
is per domain (qemu), so it's not possible to prepare this step by
attaching the device to "the" pvUSB backend.

And just detaching the device from it's driver is no solution either,
as the driver can grab it again at any time, as all drivers are queried
for all unassigned devices when a new USB device shows up.

And you'd need another command to move a USB-device to the assignable
state.

>> Juergen and I had a long back-and-forth about it around v3.  I thought
>> having slightly different semantics might be confusing, and Juergen
>> thought the functionality was important to include.  We didn't really
>> come to a conclusion and none of the tools maintainers expressed an
>> opinion.
>
> TBH I couldn't follow precisely what that discussion was about, so thanks
> for your summary. IMHO you both make good points.
>
> However given that xend was now removed 2 releases ago I think the time for
> strictly mimicking xm behaviour purely for the sake of that
> compatibility/transition has passed.
>
> Obviously if the xm interface was fine we shouldn't deviate from it just to
> be contrary, but similarly if the xm interface was bad in some way or
> doesn't fit in with the direction xl has taken since the two coexisted then
> we shouldn't feel bound to follow xm.
>
> In this case and at this point in time I think I find the argument that xl
> subcommands should, where possible, behave similarly to each other more
> compelling than they should match their xm counterparts. (maybe if we'd
> been aware of it we would have implemented pci-assignable-list differently,
> but that ship has sailed).
>
> So IMHO xl usb-assignable-list should behave like pci-assignable-list by
> default.

As stated above: this will have weird consequences or you need some kind
of placeholder backend just for this functionality. Is this really worth
the effort?


Juergen

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07  9:55       ` Juergen Gross
@ 2015-10-07 10:08         ` Ian Campbell
  0 siblings, 0 replies; 59+ messages in thread
From: Ian Campbell @ 2015-10-07 10:08 UTC (permalink / raw)
  To: Juergen Gross, George Dunlap, Chunyan Liu, xen-devel
  Cc: george.dunlap, wei.liu2, jfehlig, Ian.Jackson

On Wed, 2015-10-07 at 11:55 +0200, Juergen Gross wrote:
> On 10/07/2015 10:40 AM, Ian Campbell wrote:
> > On Tue, 2015-10-06 at 17:55 +0100, George Dunlap wrote:
> > > On 25/09/15 03:11, Chunyan Liu wrote:
> > > > Add xl usb-assignable-list command to list assignable USB devices.
> > > > Assignable USB device means the USB device type is assignable and
> > > > it's not assigned to any guest yet.
> > > > 
> > > > Signed-off-by: Chunyan Liu <cyliu@suse.com>
> > > > 
> > > > ---
> > > >    Same as "libxl: add libxl_device_usb_assignable_list API" patch,
> > > >    this patch could be sqaushed to previous one. Split because of
> > > >    some dispute. Could be squashed if acceptable, otherwise could
> > > >    be removed.
> > > 
> > > I think it's worth pointing out to other reviewers that the
> > > "usb-assignable-list" command introduced here:
> > > 1. Has identical behavior to "xm usb-assignable-list", but
> > > 2. Has different behavior than "xl pci-assignable-list".
> > 
> > OOI how does xl pci-assignable-list compare to xm pci-assignable-list.
> > 
> > > Namely:
> > > 
> > > xl pci-assignable-list will list PCI devices which have been detached
> > > from their normal driver and have been assigned to pciback (in
> > > preparation for being attached to a domain).
> 
> Assigning a PCI device to pciback is a necessary step to be able to
> attach it to a domain.
> 
> > > This command will list all USB devices in dom0 that are not assigned
> > > to
> > > VMs.
> 
> Attaching a USB device to a domain works by detaching it from it's
> normal driver and attaching it to the pvUSB backend. And this backend
> is per domain (qemu), so it's not possible to prepare this step by
> attaching the device to "the" pvUSB backend.

Thanks, this is useful information which wasn't in the summary and which
gives me cause to reconsider.

> [...]
> As stated above: this will have weird consequences or you need some kind
> of placeholder backend just for this functionality. Is this really worth
> the effort?

Right. I don't think we want to invent some sort of usb placeholder backend
just for the sake of having this command work.

So it seems the question is not so much "should xl usb-assignable-list
behave like xl pci-assignable-list or not" but it is rather "what is usb
-assignable-list useful for which isn't covered by lsusb and the xl
commands for listing attached devices".

What are the intended semantics for xl usb-assignable-list wrt devices
which are currently attached to domains?

Ian.

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07  8:40     ` Ian Campbell
  2015-10-07  9:55       ` Juergen Gross
@ 2015-10-07 10:10       ` George Dunlap
  2015-10-07 10:15         ` George Dunlap
                           ` (2 more replies)
  1 sibling, 3 replies; 59+ messages in thread
From: George Dunlap @ 2015-10-07 10:10 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Jürgen Groß,
	Wei Liu, Ian Jackson, George Dunlap, xen-devel, Jim Fehlig,
	Chunyan Liu

On Wed, Oct 7, 2015 at 9:40 AM, Ian Campbell <ian.campbell@citrix.com> wrote:
> On Tue, 2015-10-06 at 17:55 +0100, George Dunlap wrote:
>> On 25/09/15 03:11, Chunyan Liu wrote:
>> > Add xl usb-assignable-list command to list assignable USB devices.
>> > Assignable USB device means the USB device type is assignable and
>> > it's not assigned to any guest yet.
>> >
>> > Signed-off-by: Chunyan Liu <cyliu@suse.com>
>> >
>> > ---
>> >   Same as "libxl: add libxl_device_usb_assignable_list API" patch,
>> >   this patch could be sqaushed to previous one. Split because of
>> >   some dispute. Could be squashed if acceptable, otherwise could
>> >   be removed.
>>
>> I think it's worth pointing out to other reviewers that the
>> "usb-assignable-list" command introduced here:
>> 1. Has identical behavior to "xm usb-assignable-list", but
>> 2. Has different behavior than "xl pci-assignable-list".
>
> OOI how does xl pci-assignable-list compare to xm pci-assignable-list.

xm doesn't have such a command -- more on that below.

>
>> Namely:
>>
>> xl pci-assignable-list will list PCI devices which have been detached
>> from their normal driver and have been assigned to pciback (in
>> preparation for being attached to a domain).
>>
>> This command will list all USB devices in dom0 that are not assigned to
>> VMs.
>>
>> Juergen and I had a long back-and-forth about it around v3.  I thought
>> having slightly different semantics might be confusing, and Juergen
>> thought the functionality was important to include.  We didn't really
>> come to a conclusion and none of the tools maintainers expressed an
>> opinion.
>
> TBH I couldn't follow precisely what that discussion was about, so thanks
> for your summary. IMHO you both make good points.
>
> However given that xend was now removed 2 releases ago I think the time for
> strictly mimicking xm behaviour purely for the sake of that
> compatibility/transition has passed.
>
> Obviously if the xm interface was fine we shouldn't deviate from it just to
> be contrary, but similarly if the xm interface was bad in some way or
> doesn't fit in with the direction xl has taken since the two coexisted then
> we shouldn't feel bound to follow xm.
>
> In this case and at this point in time I think I find the argument that xl
> subcommands should, where possible, behave similarly to each other more
> compelling than they should match their xm counterparts. (maybe if we'd
> been aware of it we would have implemented pci-assignable-list differently,
> but that ship has sailed).
>
> So IMHO xl usb-assignable-list should behave like pci-assignable-list by
> default.

I don't think that's really suitable.

Let me try to add in a little more detail (trying to keep it as
concise as possible).

In both pci and usb, devices in dom0 will begin assigned to the normal
device driver for the device.  In order to assign a device to a guest
via the PV protocol, the device needs to be detached from its normal
driver and assigned to {pci,usb}back.

In USB, this has always been done in one step as part of the
assignment:  when you did "xm usb-attach", xm expected the device to
be assigned to the normal driver; it would then detach it from the
current driver, attach it to usbback, and then assign it to the guest.
The "xl usb-attach" Chunyan has submitted behaves the same way.

In PCI, this has always been done in two steps.  In xm, there was no
way *with xm* to detach the device from the current driver and attach
it to pciback: you had to either set kernel parameters so that the
device was assigned to pciback at boot, or manually frob around with
sysfs nodes.  "xm pci-attach" expected the device to already be
assigned to pciback; it would then assign it to the guest.  "xl
pci-attach" behaves the same way.

To avoid the user having to manually frob around with sysfs nodes, I
made it possible for xl to do it instaed.  But rather than make "xl
pci-attach" do everything, I left it in two steps; and the state of
being attached to pciback but not yet assigned to a VM I called
"assignable".  So for pci devices, you can use "lspci" to find the
device you want, then use "pci-assignable-add" to detach it from the
current driver and attach it to pciback, and then "pci-attach" to
assign it to a VM.  "pci-assignable-list" will give you the pci
devices currently in this "assignable" state.  (I wasn't aware of "xm
usb-assignable-list" when I came up with that command.)

There is also an option, "seize", which will do the whole thing at
once in "pci-attach"; this is off by default.

The reason I left the two-stage thing for pci devices was that I was
afraid that setting "seize=1" by default would be too dangerous: it
would be to easy for a missed keystroke or a typo to bring down the
system.

For USB, there is no "assignable" stage -- "usb-attach" will take it
all the way from being assigned to a driver to being assigned to the
guest.  (You can think of this as pci-attach with "seize=1" always.)
So making "usb-assignable-list" act like "pci-assignable-list" doesn't
actually make any sense.

> Now, maybe it should also support some sort of --all or --full or --host
> option which lists everything, ideally with some indication as to whether
> they are attached to usbback or not and using syntax which can just be cut
> -and-pasted into a cfg file (without at least one of those it's just a
> pointless reimplementation of lsusb).
>
> However I think --all/full/host is an optional extra.

Juergen suggested having "usb-list" have an --all option in the v3
discussion.  If like me you're concerned about confusing people, then
having --all and --host is probably the best option.

Thoughts?

 -George

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 10:10       ` George Dunlap
@ 2015-10-07 10:15         ` George Dunlap
  2015-10-07 10:35         ` Christiane Groß
  2015-10-07 11:09         ` Ian Campbell
  2 siblings, 0 replies; 59+ messages in thread
From: George Dunlap @ 2015-10-07 10:15 UTC (permalink / raw)
  To: George Dunlap, Ian Campbell
  Cc: Jürgen Groß,
	Wei Liu, Ian Jackson, Chunyan Liu, xen-devel, Jim Fehlig

On 07/10/15 11:10, George Dunlap wrote:
> The reason I left the two-stage thing for pci devices was that I was
> afraid that setting "seize=1" by default would be too dangerous: it
> would be to easy for a missed keystroke or a typo to bring down the
> system.

And as I've said before, "present me" isn't sure he really agrees with
"past me" anymore; if I were to implement this again, I think I might
well just make pci-attach behave like usb-attach, and get rid of the
whole "assignable" state altogether.

 -George

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 10:10       ` George Dunlap
  2015-10-07 10:15         ` George Dunlap
@ 2015-10-07 10:35         ` Christiane Groß
  2015-10-07 11:09         ` Ian Campbell
  2 siblings, 0 replies; 59+ messages in thread
From: Christiane Groß @ 2015-10-07 10:35 UTC (permalink / raw)
  To: George Dunlap, Ian Campbell
  Cc: Wei Liu, Ian Jackson, Chunyan Liu, George Dunlap, Jim Fehlig, xen-devel

On 10/07/2015 12:10 PM, George Dunlap wrote:
> On Wed, Oct 7, 2015 at 9:40 AM, Ian Campbell <ian.campbell@citrix.com> wrote:
>> On Tue, 2015-10-06 at 17:55 +0100, George Dunlap wrote:
>>> On 25/09/15 03:11, Chunyan Liu wrote:
>>>> Add xl usb-assignable-list command to list assignable USB devices.
>>>> Assignable USB device means the USB device type is assignable and
>>>> it's not assigned to any guest yet.
>>>>
>>>> Signed-off-by: Chunyan Liu <cyliu@suse.com>
>>>>
>>>> ---
>>>>    Same as "libxl: add libxl_device_usb_assignable_list API" patch,
>>>>    this patch could be sqaushed to previous one. Split because of
>>>>    some dispute. Could be squashed if acceptable, otherwise could
>>>>    be removed.
>>>
>>> I think it's worth pointing out to other reviewers that the
>>> "usb-assignable-list" command introduced here:
>>> 1. Has identical behavior to "xm usb-assignable-list", but
>>> 2. Has different behavior than "xl pci-assignable-list".
>>
>> OOI how does xl pci-assignable-list compare to xm pci-assignable-list.
>
> xm doesn't have such a command -- more on that below.
>
>>
>>> Namely:
>>>
>>> xl pci-assignable-list will list PCI devices which have been detached
>>> from their normal driver and have been assigned to pciback (in
>>> preparation for being attached to a domain).
>>>
>>> This command will list all USB devices in dom0 that are not assigned to
>>> VMs.
>>>
>>> Juergen and I had a long back-and-forth about it around v3.  I thought
>>> having slightly different semantics might be confusing, and Juergen
>>> thought the functionality was important to include.  We didn't really
>>> come to a conclusion and none of the tools maintainers expressed an
>>> opinion.
>>
>> TBH I couldn't follow precisely what that discussion was about, so thanks
>> for your summary. IMHO you both make good points.
>>
>> However given that xend was now removed 2 releases ago I think the time for
>> strictly mimicking xm behaviour purely for the sake of that
>> compatibility/transition has passed.
>>
>> Obviously if the xm interface was fine we shouldn't deviate from it just to
>> be contrary, but similarly if the xm interface was bad in some way or
>> doesn't fit in with the direction xl has taken since the two coexisted then
>> we shouldn't feel bound to follow xm.
>>
>> In this case and at this point in time I think I find the argument that xl
>> subcommands should, where possible, behave similarly to each other more
>> compelling than they should match their xm counterparts. (maybe if we'd
>> been aware of it we would have implemented pci-assignable-list differently,
>> but that ship has sailed).
>>
>> So IMHO xl usb-assignable-list should behave like pci-assignable-list by
>> default.
>
> I don't think that's really suitable.
>
> Let me try to add in a little more detail (trying to keep it as
> concise as possible).
>
> In both pci and usb, devices in dom0 will begin assigned to the normal
> device driver for the device.  In order to assign a device to a guest
> via the PV protocol, the device needs to be detached from its normal
> driver and assigned to {pci,usb}back.
>
> In USB, this has always been done in one step as part of the
> assignment:  when you did "xm usb-attach", xm expected the device to
> be assigned to the normal driver; it would then detach it from the
> current driver, attach it to usbback, and then assign it to the guest.
> The "xl usb-attach" Chunyan has submitted behaves the same way.
>
> In PCI, this has always been done in two steps.  In xm, there was no
> way *with xm* to detach the device from the current driver and attach
> it to pciback: you had to either set kernel parameters so that the
> device was assigned to pciback at boot, or manually frob around with
> sysfs nodes.  "xm pci-attach" expected the device to already be
> assigned to pciback; it would then assign it to the guest.  "xl
> pci-attach" behaves the same way.
>
> To avoid the user having to manually frob around with sysfs nodes, I
> made it possible for xl to do it instaed.  But rather than make "xl
> pci-attach" do everything, I left it in two steps; and the state of
> being attached to pciback but not yet assigned to a VM I called
> "assignable".  So for pci devices, you can use "lspci" to find the
> device you want, then use "pci-assignable-add" to detach it from the
> current driver and attach it to pciback, and then "pci-attach" to
> assign it to a VM.  "pci-assignable-list" will give you the pci
> devices currently in this "assignable" state.  (I wasn't aware of "xm
> usb-assignable-list" when I came up with that command.)
>
> There is also an option, "seize", which will do the whole thing at
> once in "pci-attach"; this is off by default.
>
> The reason I left the two-stage thing for pci devices was that I was
> afraid that setting "seize=1" by default would be too dangerous: it
> would be to easy for a missed keystroke or a typo to bring down the
> system.
>
> For USB, there is no "assignable" stage -- "usb-attach" will take it
> all the way from being assigned to a driver to being assigned to the
> guest.  (You can think of this as pci-attach with "seize=1" always.)
> So making "usb-assignable-list" act like "pci-assignable-list" doesn't
> actually make any sense.
>
>> Now, maybe it should also support some sort of --all or --full or --host
>> option which lists everything, ideally with some indication as to whether
>> they are attached to usbback or not and using syntax which can just be cut
>> -and-pasted into a cfg file (without at least one of those it's just a
>> pointless reimplementation of lsusb).
>>
>> However I think --all/full/host is an optional extra.
>
> Juergen suggested having "usb-list" have an --all option in the v3
> discussion.  If like me you're concerned about confusing people, then
> having --all and --host is probably the best option.
>
> Thoughts?

The main information I'd like to have at my hands is a way to see which
USB devices are available for being attached to a domain. The command
should list the devices in a way that all information related to the
planned use is contained in the output:

- the parameter needed for attaching the device to a domain
- a way to identify the device (e.g. something like the lsusb output)

If this done via an own command or an option of xl usb-list I don't
care.


Juergen

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 10:10       ` George Dunlap
  2015-10-07 10:15         ` George Dunlap
  2015-10-07 10:35         ` Christiane Groß
@ 2015-10-07 11:09         ` Ian Campbell
  2015-10-07 11:20           ` George Dunlap
  2 siblings, 1 reply; 59+ messages in thread
From: Ian Campbell @ 2015-10-07 11:09 UTC (permalink / raw)
  To: George Dunlap
  Cc: Jürgen Groß,
	Wei Liu, Ian Jackson, George Dunlap, xen-devel, Jim Fehlig,
	Chunyan Liu

On Wed, 2015-10-07 at 11:10 +0100, George Dunlap wrote:

> > So IMHO xl usb-assignable-list should behave like pci-assignable-list by
> > default.
> 
> I don't think that's really suitable.

Then I'm terribly confused because I thought that is what you were
initially advocating.

[...]

> For USB, there is no "assignable" stage -- "usb-attach" will take it
> all the way from being assigned to a driver to being assigned to the
> guest.  (You can think of this as pci-attach with "seize=1" always.)
> So making "usb-assignable-list" act like "pci-assignable-list" doesn't
> actually make any sense.

Thanks. Jeurgen has also explained this.

Do you agree that adding a dummy usbback driver just for the purposes of
adding this extra "assignable" state doesn't make sense?

> > Now, maybe it should also support some sort of --all or --full or --host
> > option which lists everything, ideally with some indication as to whether
> > they are attached to usbback or not and using syntax which can just be cut
> > -and-pasted into a cfg file (without at least one of those it's just a
> > pointless reimplementation of lsusb).
> > 
> > However I think --all/full/host is an optional extra.
> 
> Juergen suggested having "usb-list" have an --all option in the v3
> discussion.  If like me you're concerned about confusing people, then
> having --all and --host is probably the best option.
> 
> Thoughts?

If there is no assignable state in usb then I guess I don't really
understand what usb-list-assignable would even be for, so I don't really
understand why anyone is arguing what semantics it should have (my initial
reply was predicated on this state existing and it therefore being useful
to discuss how the command should behave).

Given that doing something with usb-list seems most plausible _if_ we need
some sort of thing like that at all.

What would "usb-list --all" add over and above using lsusb?

I take it that as things stand in patch #5:
    # xl usb-list <vm>
will list the usb devices attached to <vm> and that:
    # xl usb-list
will list the usb devices attached to every vm, is that
correct?

So the idea would then be to add some way of listing the devices not included in "xl usb-list", which are notionally attached to dom0, but via physical USB and not PV usb.

Ian.

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 11:09         ` Ian Campbell
@ 2015-10-07 11:20           ` George Dunlap
  2015-10-07 11:25             ` Juergen Gross
  0 siblings, 1 reply; 59+ messages in thread
From: George Dunlap @ 2015-10-07 11:20 UTC (permalink / raw)
  To: Ian Campbell, George Dunlap
  Cc: Jürgen Groß,
	Wei Liu, Ian Jackson, Chunyan Liu, xen-devel, Jim Fehlig

On 07/10/15 12:09, Ian Campbell wrote:
> On Wed, 2015-10-07 at 11:10 +0100, George Dunlap wrote:
> 
>>> So IMHO xl usb-assignable-list should behave like pci-assignable-list by
>>> default.
>>
>> I don't think that's really suitable.
> 
> Then I'm terribly confused because I thought that is what you were
> initially advocating.

I think in v3 I was trying to come up with a different name
(usb-available-list or something); but my main point was that it
*shouldn't* be named similarly but have different functionality.

As I said, for this am I was ready to just let it slide; I just wanted
to make sure other people knew what was being let slide. :-)

> 
> [...]
> 
>> For USB, there is no "assignable" stage -- "usb-attach" will take it
>> all the way from being assigned to a driver to being assigned to the
>> guest.  (You can think of this as pci-attach with "seize=1" always.)
>> So making "usb-assignable-list" act like "pci-assignable-list" doesn't
>> actually make any sense.
> 
> Thanks. Jeurgen has also explained this.
> 
> Do you agree that adding a dummy usbback driver just for the purposes of
> adding this extra "assignable" state doesn't make sense?

Yes, I agree.

>>> Now, maybe it should also support some sort of --all or --full or --host
>>> option which lists everything, ideally with some indication as to whether
>>> they are attached to usbback or not and using syntax which can just be cut
>>> -and-pasted into a cfg file (without at least one of those it's just a
>>> pointless reimplementation of lsusb).
>>>
>>> However I think --all/full/host is an optional extra.
>>
>> Juergen suggested having "usb-list" have an --all option in the v3
>> discussion.  If like me you're concerned about confusing people, then
>> having --all and --host is probably the best option.
>>
>> Thoughts?
> 
> If there is no assignable state in usb then I guess I don't really
> understand what usb-list-assignable would even be for, so I don't really
> understand why anyone is arguing what semantics it should have (my initial
> reply was predicated on this state existing and it therefore being useful
> to discuss how the command should behave).
> 
> Given that doing something with usb-list seems most plausible _if_ we need
> some sort of thing like that at all.
> 
> What would "usb-list --all" add over and above using lsusb?
> 
> I take it that as things stand in patch #5:
>     # xl usb-list <vm>
> will list the usb devices attached to <vm> and that:
>     # xl usb-list
> will list the usb devices attached to every vm, is that
> correct?
> 
> So the idea would then be to add some way of listing the devices not included in "xl usb-list", which are notionally attached to dom0, but via physical USB and not PV usb.

The "usb-assignable-list" that Chunyan has submitted will give you a
list of all dom0 USB devices that have not yet been assigned to a guest.
 It should be basically equivalent to "lsusb", except that it filters
out devices which have already been assigned to VMs.

In the e-mail you respond to, I was suggesting that

# xl usb-list --all

would show you usb devices attached to every VM, and also USB devices
attached to no VM, and that

# xl usb-list --host

would show you only host usb devices not attached to any VM.

I think it's the second bit if functionality which Juergen is keen be
available in some form or other.

 -George

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 11:20           ` George Dunlap
@ 2015-10-07 11:25             ` Juergen Gross
  2015-10-07 11:32               ` George Dunlap
                                 ` (2 more replies)
  0 siblings, 3 replies; 59+ messages in thread
From: Juergen Gross @ 2015-10-07 11:25 UTC (permalink / raw)
  To: George Dunlap, Ian Campbell, George Dunlap
  Cc: Ian Jackson, Jim Fehlig, Wei Liu, Chunyan Liu, xen-devel

On 10/07/2015 01:20 PM, George Dunlap wrote:
> On 07/10/15 12:09, Ian Campbell wrote:
>> On Wed, 2015-10-07 at 11:10 +0100, George Dunlap wrote:
>>
>>>> So IMHO xl usb-assignable-list should behave like pci-assignable-list by
>>>> default.
>>>
>>> I don't think that's really suitable.
>>
>> Then I'm terribly confused because I thought that is what you were
>> initially advocating.
>
> I think in v3 I was trying to come up with a different name
> (usb-available-list or something); but my main point was that it
> *shouldn't* be named similarly but have different functionality.
>
> As I said, for this am I was ready to just let it slide; I just wanted
> to make sure other people knew what was being let slide. :-)
>
>>
>> [...]
>>
>>> For USB, there is no "assignable" stage -- "usb-attach" will take it
>>> all the way from being assigned to a driver to being assigned to the
>>> guest.  (You can think of this as pci-attach with "seize=1" always.)
>>> So making "usb-assignable-list" act like "pci-assignable-list" doesn't
>>> actually make any sense.
>>
>> Thanks. Jeurgen has also explained this.
>>
>> Do you agree that adding a dummy usbback driver just for the purposes of
>> adding this extra "assignable" state doesn't make sense?
>
> Yes, I agree.
>
>>>> Now, maybe it should also support some sort of --all or --full or --host
>>>> option which lists everything, ideally with some indication as to whether
>>>> they are attached to usbback or not and using syntax which can just be cut
>>>> -and-pasted into a cfg file (without at least one of those it's just a
>>>> pointless reimplementation of lsusb).
>>>>
>>>> However I think --all/full/host is an optional extra.
>>>
>>> Juergen suggested having "usb-list" have an --all option in the v3
>>> discussion.  If like me you're concerned about confusing people, then
>>> having --all and --host is probably the best option.
>>>
>>> Thoughts?
>>
>> If there is no assignable state in usb then I guess I don't really
>> understand what usb-list-assignable would even be for, so I don't really
>> understand why anyone is arguing what semantics it should have (my initial
>> reply was predicated on this state existing and it therefore being useful
>> to discuss how the command should behave).
>>
>> Given that doing something with usb-list seems most plausible _if_ we need
>> some sort of thing like that at all.
>>
>> What would "usb-list --all" add over and above using lsusb?
>>
>> I take it that as things stand in patch #5:
>>      # xl usb-list <vm>
>> will list the usb devices attached to <vm> and that:
>>      # xl usb-list
>> will list the usb devices attached to every vm, is that
>> correct?
>>
>> So the idea would then be to add some way of listing the devices not included in "xl usb-list", which are notionally attached to dom0, but via physical USB and not PV usb.
>
> The "usb-assignable-list" that Chunyan has submitted will give you a
> list of all dom0 USB devices that have not yet been assigned to a guest.
>   It should be basically equivalent to "lsusb", except that it filters
> out devices which have already been assigned to VMs.
>
> In the e-mail you respond to, I was suggesting that
>
> # xl usb-list --all
>
> would show you usb devices attached to every VM, and also USB devices
> attached to no VM, and that
>
> # xl usb-list --host
>
> would show you only host usb devices not attached to any VM.
>
> I think it's the second bit if functionality which Juergen is keen be
> available in some form or other.

Exactly.

BTW: I've explained that in another reply, but my mail client has chosen
to send it via another account - I've no idea how that happened. So now
my wife has some xen-devel history as well. ;-)


Juergen

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 11:25             ` Juergen Gross
@ 2015-10-07 11:32               ` George Dunlap
  2015-10-07 11:37               ` Ian Campbell
  2015-10-07 11:39               ` Ian Campbell
  2 siblings, 0 replies; 59+ messages in thread
From: George Dunlap @ 2015-10-07 11:32 UTC (permalink / raw)
  To: Juergen Gross, Ian Campbell, George Dunlap
  Cc: Ian Jackson, Jim Fehlig, Wei Liu, Chunyan Liu, xen-devel

On 07/10/15 12:25, Juergen Gross wrote:
> On 10/07/2015 01:20 PM, George Dunlap wrote:
>> On 07/10/15 12:09, Ian Campbell wrote:
>>> On Wed, 2015-10-07 at 11:10 +0100, George Dunlap wrote:
>>>
>>>>> So IMHO xl usb-assignable-list should behave like
>>>>> pci-assignable-list by
>>>>> default.
>>>>
>>>> I don't think that's really suitable.
>>>
>>> Then I'm terribly confused because I thought that is what you were
>>> initially advocating.
>>
>> I think in v3 I was trying to come up with a different name
>> (usb-available-list or something); but my main point was that it
>> *shouldn't* be named similarly but have different functionality.
>>
>> As I said, for this am I was ready to just let it slide; I just wanted
>> to make sure other people knew what was being let slide. :-)
>>
>>>
>>> [...]
>>>
>>>> For USB, there is no "assignable" stage -- "usb-attach" will take it
>>>> all the way from being assigned to a driver to being assigned to the
>>>> guest.  (You can think of this as pci-attach with "seize=1" always.)
>>>> So making "usb-assignable-list" act like "pci-assignable-list" doesn't
>>>> actually make any sense.
>>>
>>> Thanks. Jeurgen has also explained this.
>>>
>>> Do you agree that adding a dummy usbback driver just for the purposes of
>>> adding this extra "assignable" state doesn't make sense?
>>
>> Yes, I agree.
>>
>>>>> Now, maybe it should also support some sort of --all or --full or
>>>>> --host
>>>>> option which lists everything, ideally with some indication as to
>>>>> whether
>>>>> they are attached to usbback or not and using syntax which can just
>>>>> be cut
>>>>> -and-pasted into a cfg file (without at least one of those it's just a
>>>>> pointless reimplementation of lsusb).
>>>>>
>>>>> However I think --all/full/host is an optional extra.
>>>>
>>>> Juergen suggested having "usb-list" have an --all option in the v3
>>>> discussion.  If like me you're concerned about confusing people, then
>>>> having --all and --host is probably the best option.
>>>>
>>>> Thoughts?
>>>
>>> If there is no assignable state in usb then I guess I don't really
>>> understand what usb-list-assignable would even be for, so I don't really
>>> understand why anyone is arguing what semantics it should have (my
>>> initial
>>> reply was predicated on this state existing and it therefore being
>>> useful
>>> to discuss how the command should behave).
>>>
>>> Given that doing something with usb-list seems most plausible _if_ we
>>> need
>>> some sort of thing like that at all.
>>>
>>> What would "usb-list --all" add over and above using lsusb?
>>>
>>> I take it that as things stand in patch #5:
>>>      # xl usb-list <vm>
>>> will list the usb devices attached to <vm> and that:
>>>      # xl usb-list
>>> will list the usb devices attached to every vm, is that
>>> correct?
>>>
>>> So the idea would then be to add some way of listing the devices not
>>> included in "xl usb-list", which are notionally attached to dom0, but
>>> via physical USB and not PV usb.
>>
>> The "usb-assignable-list" that Chunyan has submitted will give you a
>> list of all dom0 USB devices that have not yet been assigned to a guest.
>>   It should be basically equivalent to "lsusb", except that it filters
>> out devices which have already been assigned to VMs.
>>
>> In the e-mail you respond to, I was suggesting that
>>
>> # xl usb-list --all
>>
>> would show you usb devices attached to every VM, and also USB devices
>> attached to no VM, and that
>>
>> # xl usb-list --host
>>
>> would show you only host usb devices not attached to any VM.
>>
>> I think it's the second bit if functionality which Juergen is keen be
>> available in some form or other.
> 
> Exactly.
> 
> BTW: I've explained that in another reply, but my mail client has chosen
> to send it via another account - I've no idea how that happened. So now
> my wife has some xen-devel history as well. ;-)

Oh, right -- I wondered where "Christiane" came from.  I just figured it
was an alternate name you used sometimes (like maybe Juergen was your
middle name but the one you normally went by). :-)

 -George

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 11:25             ` Juergen Gross
  2015-10-07 11:32               ` George Dunlap
@ 2015-10-07 11:37               ` Ian Campbell
  2015-10-07 11:39                 ` Juergen Gross
  2015-10-07 11:43                 ` Ian Campbell
  2015-10-07 11:39               ` Ian Campbell
  2 siblings, 2 replies; 59+ messages in thread
From: Ian Campbell @ 2015-10-07 11:37 UTC (permalink / raw)
  To: Juergen Gross, George Dunlap, George Dunlap
  Cc: Ian Jackson, Jim Fehlig, Wei Liu, Chunyan Liu, xen-devel

On Wed, 2015-10-07 at 13:25 +0200, Juergen Gross wrote:

> BTW: I've explained that in another reply, but my mail client has chosen
> to send it via another account - I've no idea how that happened. So now
> my wife has some xen-devel history as well. ;-)

It's stuck in moderation (I suppose) and I think I have rights to cancel it
if you would like to resend as yourself ;-).

Ian.

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 11:37               ` Ian Campbell
@ 2015-10-07 11:39                 ` Juergen Gross
  2015-10-07 11:43                 ` Ian Campbell
  1 sibling, 0 replies; 59+ messages in thread
From: Juergen Gross @ 2015-10-07 11:39 UTC (permalink / raw)
  To: Ian Campbell, George Dunlap, George Dunlap
  Cc: Ian Jackson, Jim Fehlig, Wei Liu, Chunyan Liu, xen-devel

On 10/07/2015 01:37 PM, Ian Campbell wrote:
> On Wed, 2015-10-07 at 13:25 +0200, Juergen Gross wrote:
>
>> BTW: I've explained that in another reply, but my mail client has chosen
>> to send it via another account - I've no idea how that happened. So now
>> my wife has some xen-devel history as well. ;-)
>
> It's stuck in moderation (I suppose) and I think I have rights to cancel it
> if you would like to resend as yourself ;-).

Too late. Otherwise I wouldn't have noticed it.


Juergen

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 11:25             ` Juergen Gross
  2015-10-07 11:32               ` George Dunlap
  2015-10-07 11:37               ` Ian Campbell
@ 2015-10-07 11:39               ` Ian Campbell
  2015-10-07 11:49                 ` Juergen Gross
  2 siblings, 1 reply; 59+ messages in thread
From: Ian Campbell @ 2015-10-07 11:39 UTC (permalink / raw)
  To: Juergen Gross, George Dunlap, George Dunlap
  Cc: Ian Jackson, Jim Fehlig, Wei Liu, Chunyan Liu, xen-devel

On Wed, 2015-10-07 at 13:25 +0200, Juergen Gross wrote:
> > The "usb-assignable-list" that Chunyan has submitted will give you a
> > list of all dom0 USB devices that have not yet been assigned to a guest.
> >   It should be basically equivalent to "lsusb", except that it filters
> > out devices which have already been assigned to VMs.

Right, that does sound like useful enough functionality to justify not just
using lsusb.

> > In the e-mail you respond to, I was suggesting that
> > 
> > # xl usb-list --all
> > 
> > would show you usb devices attached to every VM, and also USB devices
> > attached to no VM, and that

And would "xl usb-list" list all domain attached to every VM but not the
unattached ones?

> > # xl usb-list --host
> > 
> > would show you only host usb devices not attached to any VM.
> > 
> > I think it's the second bit if functionality which Juergen is keen be
> > available in some form or other.
> 
> Exactly.

I'm happy with this proposal too.

Is the distinction between --host and --all important to you? Assuming
unassigned devices are clearly indicated in the --all output (as they
should be).

Ian.

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 11:37               ` Ian Campbell
  2015-10-07 11:39                 ` Juergen Gross
@ 2015-10-07 11:43                 ` Ian Campbell
  1 sibling, 0 replies; 59+ messages in thread
From: Ian Campbell @ 2015-10-07 11:43 UTC (permalink / raw)
  To: Juergen Gross, George Dunlap, George Dunlap
  Cc: Ian Jackson, Jim Fehlig, Wei Liu, Chunyan Liu, xen-devel

On Wed, 2015-10-07 at 12:37 +0100, Ian Campbell wrote:
> On Wed, 2015-10-07 at 13:25 +0200, Juergen Gross wrote:
> 
> > BTW: I've explained that in another reply, but my mail client has
> > chosen
> > to send it via another account - I've no idea how that happened. So now
> > my wife has some xen-devel history as well. ;-)
> 
> It's stuck in moderation (I suppose) and I think I have rights to cancel
> it
> if you would like to resend as yourself ;-).

Scratch that, it's already on the list I just didn't even notice...

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 11:39               ` Ian Campbell
@ 2015-10-07 11:49                 ` Juergen Gross
  2015-10-07 11:55                   ` Ian Campbell
  0 siblings, 1 reply; 59+ messages in thread
From: Juergen Gross @ 2015-10-07 11:49 UTC (permalink / raw)
  To: Ian Campbell, George Dunlap, George Dunlap
  Cc: Ian Jackson, Jim Fehlig, Wei Liu, Chunyan Liu, xen-devel

On 10/07/2015 01:39 PM, Ian Campbell wrote:
> On Wed, 2015-10-07 at 13:25 +0200, Juergen Gross wrote:
>>> The "usb-assignable-list" that Chunyan has submitted will give you a
>>> list of all dom0 USB devices that have not yet been assigned to a guest.
>>>    It should be basically equivalent to "lsusb", except that it filters
>>> out devices which have already been assigned to VMs.
>
> Right, that does sound like useful enough functionality to justify not just
> using lsusb.
>
>>> In the e-mail you respond to, I was suggesting that
>>>
>>> # xl usb-list --all
>>>
>>> would show you usb devices attached to every VM, and also USB devices
>>> attached to no VM, and that
>
> And would "xl usb-list" list all domain attached to every VM but not the
> unattached ones?
>
>>> # xl usb-list --host
>>>
>>> would show you only host usb devices not attached to any VM.
>>>
>>> I think it's the second bit if functionality which Juergen is keen be
>>> available in some form or other.
>>
>> Exactly.
>
> I'm happy with this proposal too.
>
> Is the distinction between --host and --all important to you? Assuming
> unassigned devices are clearly indicated in the --all output (as they
> should be).

Depends on how the output would look like.

In case it either isn't containing VMs without any attached USB device
or the unassigned devices are listed at the end this would be okay. I
just wouldn't want to have to scroll a lot in case of a host with 1000
domains.

BTW: In case you don't have the --host option it would be nice to omit
--all as well and just assume --all when no domain was specified (like
xl list).


Juergen

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 11:49                 ` Juergen Gross
@ 2015-10-07 11:55                   ` Ian Campbell
  2015-10-07 12:05                     ` Juergen Gross
  0 siblings, 1 reply; 59+ messages in thread
From: Ian Campbell @ 2015-10-07 11:55 UTC (permalink / raw)
  To: Juergen Gross, George Dunlap, George Dunlap
  Cc: Ian Jackson, Jim Fehlig, Wei Liu, Chunyan Liu, xen-devel

On Wed, 2015-10-07 at 13:49 +0200, Juergen Gross wrote:
> On 10/07/2015 01:39 PM, Ian Campbell wrote:
> > On Wed, 2015-10-07 at 13:25 +0200, Juergen Gross wrote:
> > > > The "usb-assignable-list" that Chunyan has submitted will give you
> > > > a
> > > > list of all dom0 USB devices that have not yet been assigned to a
> > > > guest.
> > > >    It should be basically equivalent to "lsusb", except that it
> > > > filters
> > > > out devices which have already been assigned to VMs.
> > 
> > Right, that does sound like useful enough functionality to justify not
> > just
> > using lsusb.
> > 
> > > > In the e-mail you respond to, I was suggesting that
> > > > 
> > > > # xl usb-list --all
> > > > 
> > > > would show you usb devices attached to every VM, and also USB
> > > > devices
> > > > attached to no VM, and that
> > 
> > And would "xl usb-list" list all domain attached to every VM but not
> > the
> > unattached ones?
> > 
> > > > # xl usb-list --host
> > > > 
> > > > would show you only host usb devices not attached to any VM.
> > > > 
> > > > I think it's the second bit if functionality which Juergen is keen
> > > > be
> > > > available in some form or other.
> > > 
> > > Exactly.
> > 
> > I'm happy with this proposal too.
> > 
> > Is the distinction between --host and --all important to you? Assuming
> > unassigned devices are clearly indicated in the --all output (as they
> > should be).
> 
> Depends on how the output would look like.
> 
> In case it either isn't containing VMs without any attached USB device
> or the unassigned devices are listed at the end this would be okay. I
> just wouldn't want to have to scroll a lot in case of a host with 1000
> domains.

Makes sense.

> BTW: In case you don't have the --host option it would be nice to omit
> --all as well and just assume --all when no domain was specified (like
> xl list).

I think "xl usb-list" should list the devices attached to all domains, for
sure. I'm ambivalent about whether it also lists unattached devices (in
which case --all is unnecessary) or if --all is required to get those.

Ian.

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 11:55                   ` Ian Campbell
@ 2015-10-07 12:05                     ` Juergen Gross
  2015-10-07 12:51                       ` Ian Campbell
  2015-10-07 13:21                       ` George Dunlap
  0 siblings, 2 replies; 59+ messages in thread
From: Juergen Gross @ 2015-10-07 12:05 UTC (permalink / raw)
  To: Ian Campbell, George Dunlap, George Dunlap
  Cc: Ian Jackson, Jim Fehlig, Wei Liu, Chunyan Liu, xen-devel

On 10/07/2015 01:55 PM, Ian Campbell wrote:
> On Wed, 2015-10-07 at 13:49 +0200, Juergen Gross wrote:
>> On 10/07/2015 01:39 PM, Ian Campbell wrote:
>>> On Wed, 2015-10-07 at 13:25 +0200, Juergen Gross wrote:
>>>>> The "usb-assignable-list" that Chunyan has submitted will give you
>>>>> a
>>>>> list of all dom0 USB devices that have not yet been assigned to a
>>>>> guest.
>>>>>     It should be basically equivalent to "lsusb", except that it
>>>>> filters
>>>>> out devices which have already been assigned to VMs.
>>>
>>> Right, that does sound like useful enough functionality to justify not
>>> just
>>> using lsusb.
>>>
>>>>> In the e-mail you respond to, I was suggesting that
>>>>>
>>>>> # xl usb-list --all
>>>>>
>>>>> would show you usb devices attached to every VM, and also USB
>>>>> devices
>>>>> attached to no VM, and that
>>>
>>> And would "xl usb-list" list all domain attached to every VM but not
>>> the
>>> unattached ones?
>>>
>>>>> # xl usb-list --host
>>>>>
>>>>> would show you only host usb devices not attached to any VM.
>>>>>
>>>>> I think it's the second bit if functionality which Juergen is keen
>>>>> be
>>>>> available in some form or other.
>>>>
>>>> Exactly.
>>>
>>> I'm happy with this proposal too.
>>>
>>> Is the distinction between --host and --all important to you? Assuming
>>> unassigned devices are clearly indicated in the --all output (as they
>>> should be).
>>
>> Depends on how the output would look like.
>>
>> In case it either isn't containing VMs without any attached USB device
>> or the unassigned devices are listed at the end this would be okay. I
>> just wouldn't want to have to scroll a lot in case of a host with 1000
>> domains.
>
> Makes sense.
>
>> BTW: In case you don't have the --host option it would be nice to omit
>> --all as well and just assume --all when no domain was specified (like
>> xl list).
>
> I think "xl usb-list" should list the devices attached to all domains, for
> sure. I'm ambivalent about whether it also lists unattached devices (in
> which case --all is unnecessary) or if --all is required to get those.

I'd go for nuking the --all option. I suppose xl usb-list without
specifying a domain will nearly always be used to see the unassigned
devices and not "uuh, to which domain did I assign device x?".


Juergen

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 12:05                     ` Juergen Gross
@ 2015-10-07 12:51                       ` Ian Campbell
  2015-10-07 13:21                       ` George Dunlap
  1 sibling, 0 replies; 59+ messages in thread
From: Ian Campbell @ 2015-10-07 12:51 UTC (permalink / raw)
  To: Juergen Gross, George Dunlap, George Dunlap
  Cc: Ian Jackson, Jim Fehlig, Wei Liu, Chunyan Liu, xen-devel

On Wed, 2015-10-07 at 14:05 +0200, Juergen Gross wrote:
> On 10/07/2015 01:55 PM, Ian Campbell wrote:
> > On Wed, 2015-10-07 at 13:49 +0200, Juergen Gross wrote:
> > > BTW: In case you don't have the --host option it would be nice to
> > > omit
> > > --all as well and just assume --all when no domain was specified
> > > (like
> > > xl list).
> > 
> > I think "xl usb-list" should list the devices attached to all domains,
> > for
> > sure. I'm ambivalent about whether it also lists unattached devices (in
> > which case --all is unnecessary) or if --all is required to get those.
> 
> I'd go for nuking the --all option. I suppose xl usb-list without
> specifying a domain will nearly always be used to see the unassigned
> devices and not "uuh, to which domain did I assign device x?".

I think that is probably true.

Ian

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 12:05                     ` Juergen Gross
  2015-10-07 12:51                       ` Ian Campbell
@ 2015-10-07 13:21                       ` George Dunlap
  2015-10-07 13:54                         ` Juergen Gross
  1 sibling, 1 reply; 59+ messages in thread
From: George Dunlap @ 2015-10-07 13:21 UTC (permalink / raw)
  To: Juergen Gross, Ian Campbell, George Dunlap
  Cc: Ian Jackson, Jim Fehlig, Wei Liu, Chunyan Liu, xen-devel

On 07/10/15 13:05, Juergen Gross wrote:
> On 10/07/2015 01:55 PM, Ian Campbell wrote:
>> On Wed, 2015-10-07 at 13:49 +0200, Juergen Gross wrote:
>>> On 10/07/2015 01:39 PM, Ian Campbell wrote:
>>>> On Wed, 2015-10-07 at 13:25 +0200, Juergen Gross wrote:
>>>>>> The "usb-assignable-list" that Chunyan has submitted will give you
>>>>>> a
>>>>>> list of all dom0 USB devices that have not yet been assigned to a
>>>>>> guest.
>>>>>>     It should be basically equivalent to "lsusb", except that it
>>>>>> filters
>>>>>> out devices which have already been assigned to VMs.
>>>>
>>>> Right, that does sound like useful enough functionality to justify not
>>>> just
>>>> using lsusb.
>>>>
>>>>>> In the e-mail you respond to, I was suggesting that
>>>>>>
>>>>>> # xl usb-list --all
>>>>>>
>>>>>> would show you usb devices attached to every VM, and also USB
>>>>>> devices
>>>>>> attached to no VM, and that
>>>>
>>>> And would "xl usb-list" list all domain attached to every VM but not
>>>> the
>>>> unattached ones?
>>>>
>>>>>> # xl usb-list --host
>>>>>>
>>>>>> would show you only host usb devices not attached to any VM.
>>>>>>
>>>>>> I think it's the second bit if functionality which Juergen is keen
>>>>>> be
>>>>>> available in some form or other.
>>>>>
>>>>> Exactly.
>>>>
>>>> I'm happy with this proposal too.
>>>>
>>>> Is the distinction between --host and --all important to you? Assuming
>>>> unassigned devices are clearly indicated in the --all output (as they
>>>> should be).
>>>
>>> Depends on how the output would look like.
>>>
>>> In case it either isn't containing VMs without any attached USB device
>>> or the unassigned devices are listed at the end this would be okay. I
>>> just wouldn't want to have to scroll a lot in case of a host with 1000
>>> domains.
>>
>> Makes sense.
>>
>>> BTW: In case you don't have the --host option it would be nice to omit
>>> --all as well and just assume --all when no domain was specified (like
>>> xl list).
>>
>> I think "xl usb-list" should list the devices attached to all domains,
>> for
>> sure. I'm ambivalent about whether it also lists unattached devices (in
>> which case --all is unnecessary) or if --all is required to get those.
> 
> I'd go for nuking the --all option. I suppose xl usb-list without
> specifying a domain will nearly always be used to see the unassigned
> devices and not "uuh, to which domain did I assign device x?".

I don't know -- if you've assigned a device to one particular domain,
then it seems pretty likely that at some point in the future you might
want to say, "Wait, what devices do I have assigned where again?"

I think
* people will expect "xl usb-list" to show all VMs but *not* all
unassigned host devices
* In this sort of a case, doing what people expect is probably more
important than doing what we think is probably more convenient for them.

I'd go for "--all" and "--host", but I think it's not terribly important.

Chunyan, do you have any input / opinions?

 -George

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 13:21                       ` George Dunlap
@ 2015-10-07 13:54                         ` Juergen Gross
  2015-10-07 14:05                           ` Ian Campbell
  2015-10-07 14:10                           ` George Dunlap
  0 siblings, 2 replies; 59+ messages in thread
From: Juergen Gross @ 2015-10-07 13:54 UTC (permalink / raw)
  To: George Dunlap, Ian Campbell, George Dunlap
  Cc: Wei Liu, Jim Fehlig, Ian Jackson, Chunyan Liu, xen-devel

On 10/07/2015 03:21 PM, George Dunlap wrote:
> On 07/10/15 13:05, Juergen Gross wrote:
>> On 10/07/2015 01:55 PM, Ian Campbell wrote:
>>> On Wed, 2015-10-07 at 13:49 +0200, Juergen Gross wrote:
>>>> On 10/07/2015 01:39 PM, Ian Campbell wrote:
>>>>> On Wed, 2015-10-07 at 13:25 +0200, Juergen Gross wrote:
>>>>>>> The "usb-assignable-list" that Chunyan has submitted will give you
>>>>>>> a
>>>>>>> list of all dom0 USB devices that have not yet been assigned to a
>>>>>>> guest.
>>>>>>>      It should be basically equivalent to "lsusb", except that it
>>>>>>> filters
>>>>>>> out devices which have already been assigned to VMs.
>>>>>
>>>>> Right, that does sound like useful enough functionality to justify not
>>>>> just
>>>>> using lsusb.
>>>>>
>>>>>>> In the e-mail you respond to, I was suggesting that
>>>>>>>
>>>>>>> # xl usb-list --all
>>>>>>>
>>>>>>> would show you usb devices attached to every VM, and also USB
>>>>>>> devices
>>>>>>> attached to no VM, and that
>>>>>
>>>>> And would "xl usb-list" list all domain attached to every VM but not
>>>>> the
>>>>> unattached ones?
>>>>>
>>>>>>> # xl usb-list --host
>>>>>>>
>>>>>>> would show you only host usb devices not attached to any VM.
>>>>>>>
>>>>>>> I think it's the second bit if functionality which Juergen is keen
>>>>>>> be
>>>>>>> available in some form or other.
>>>>>>
>>>>>> Exactly.
>>>>>
>>>>> I'm happy with this proposal too.
>>>>>
>>>>> Is the distinction between --host and --all important to you? Assuming
>>>>> unassigned devices are clearly indicated in the --all output (as they
>>>>> should be).
>>>>
>>>> Depends on how the output would look like.
>>>>
>>>> In case it either isn't containing VMs without any attached USB device
>>>> or the unassigned devices are listed at the end this would be okay. I
>>>> just wouldn't want to have to scroll a lot in case of a host with 1000
>>>> domains.
>>>
>>> Makes sense.
>>>
>>>> BTW: In case you don't have the --host option it would be nice to omit
>>>> --all as well and just assume --all when no domain was specified (like
>>>> xl list).
>>>
>>> I think "xl usb-list" should list the devices attached to all domains,
>>> for
>>> sure. I'm ambivalent about whether it also lists unattached devices (in
>>> which case --all is unnecessary) or if --all is required to get those.
>>
>> I'd go for nuking the --all option. I suppose xl usb-list without
>> specifying a domain will nearly always be used to see the unassigned
>> devices and not "uuh, to which domain did I assign device x?".
>
> I don't know -- if you've assigned a device to one particular domain,
> then it seems pretty likely that at some point in the future you might
> want to say, "Wait, what devices do I have assigned where again?"
>
> I think
> * people will expect "xl usb-list" to show all VMs but *not* all
> unassigned host devices
> * In this sort of a case, doing what people expect is probably more
> important than doing what we think is probably more convenient for them.

Hmm, technically all unassigned USB-devices are usable from Dom0. So why
not list them there.

"xl usb-list 0" would be the same then as "xl usb-list --host".
"xl usb-list" would be the same as "xl usb-list --all".

Just a thought - I'm fine with either variant.


Juergen

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 13:54                         ` Juergen Gross
@ 2015-10-07 14:05                           ` Ian Campbell
  2015-10-07 14:26                             ` Juergen Gross
  2015-10-07 14:10                           ` George Dunlap
  1 sibling, 1 reply; 59+ messages in thread
From: Ian Campbell @ 2015-10-07 14:05 UTC (permalink / raw)
  To: Juergen Gross, George Dunlap, George Dunlap
  Cc: Wei Liu, Jim Fehlig, Ian Jackson, Chunyan Liu, xen-devel

On Wed, 2015-10-07 at 15:54 +0200, Juergen Gross wrote:

> Hmm, technically all unassigned USB-devices are usable from Dom0. So why
> not list them there.

I think you'd at least want to distinguish USB devices available to dom0 as
via a PCI host controller from those which are available via pvusb.

This also doesn't quite work when driver domains are in the picture.

> 
> "xl usb-list 0" would be the same then as "xl usb-list --host".
> "xl usb-list" would be the same as "xl usb-list --all".
> 
> Just a thought - I'm fine with either variant.
> 
> 
> Juergen

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 13:54                         ` Juergen Gross
  2015-10-07 14:05                           ` Ian Campbell
@ 2015-10-07 14:10                           ` George Dunlap
  1 sibling, 0 replies; 59+ messages in thread
From: George Dunlap @ 2015-10-07 14:10 UTC (permalink / raw)
  To: Juergen Gross, Ian Campbell, George Dunlap
  Cc: Wei Liu, Jim Fehlig, Ian Jackson, Chunyan Liu, xen-devel

On 07/10/15 14:54, Juergen Gross wrote:
> On 10/07/2015 03:21 PM, George Dunlap wrote:
>> On 07/10/15 13:05, Juergen Gross wrote:
>>> On 10/07/2015 01:55 PM, Ian Campbell wrote:
>>>> On Wed, 2015-10-07 at 13:49 +0200, Juergen Gross wrote:
>>>>> On 10/07/2015 01:39 PM, Ian Campbell wrote:
>>>>>> On Wed, 2015-10-07 at 13:25 +0200, Juergen Gross wrote:
>>>>>>>> The "usb-assignable-list" that Chunyan has submitted will give you
>>>>>>>> a
>>>>>>>> list of all dom0 USB devices that have not yet been assigned to a
>>>>>>>> guest.
>>>>>>>>      It should be basically equivalent to "lsusb", except that it
>>>>>>>> filters
>>>>>>>> out devices which have already been assigned to VMs.
>>>>>>
>>>>>> Right, that does sound like useful enough functionality to justify
>>>>>> not
>>>>>> just
>>>>>> using lsusb.
>>>>>>
>>>>>>>> In the e-mail you respond to, I was suggesting that
>>>>>>>>
>>>>>>>> # xl usb-list --all
>>>>>>>>
>>>>>>>> would show you usb devices attached to every VM, and also USB
>>>>>>>> devices
>>>>>>>> attached to no VM, and that
>>>>>>
>>>>>> And would "xl usb-list" list all domain attached to every VM but not
>>>>>> the
>>>>>> unattached ones?
>>>>>>
>>>>>>>> # xl usb-list --host
>>>>>>>>
>>>>>>>> would show you only host usb devices not attached to any VM.
>>>>>>>>
>>>>>>>> I think it's the second bit if functionality which Juergen is keen
>>>>>>>> be
>>>>>>>> available in some form or other.
>>>>>>>
>>>>>>> Exactly.
>>>>>>
>>>>>> I'm happy with this proposal too.
>>>>>>
>>>>>> Is the distinction between --host and --all important to you?
>>>>>> Assuming
>>>>>> unassigned devices are clearly indicated in the --all output (as they
>>>>>> should be).
>>>>>
>>>>> Depends on how the output would look like.
>>>>>
>>>>> In case it either isn't containing VMs without any attached USB device
>>>>> or the unassigned devices are listed at the end this would be okay. I
>>>>> just wouldn't want to have to scroll a lot in case of a host with 1000
>>>>> domains.
>>>>
>>>> Makes sense.
>>>>
>>>>> BTW: In case you don't have the --host option it would be nice to omit
>>>>> --all as well and just assume --all when no domain was specified (like
>>>>> xl list).
>>>>
>>>> I think "xl usb-list" should list the devices attached to all domains,
>>>> for
>>>> sure. I'm ambivalent about whether it also lists unattached devices (in
>>>> which case --all is unnecessary) or if --all is required to get those.
>>>
>>> I'd go for nuking the --all option. I suppose xl usb-list without
>>> specifying a domain will nearly always be used to see the unassigned
>>> devices and not "uuh, to which domain did I assign device x?".
>>
>> I don't know -- if you've assigned a device to one particular domain,
>> then it seems pretty likely that at some point in the future you might
>> want to say, "Wait, what devices do I have assigned where again?"
>>
>> I think
>> * people will expect "xl usb-list" to show all VMs but *not* all
>> unassigned host devices
>> * In this sort of a case, doing what people expect is probably more
>> important than doing what we think is probably more convenient for them.
> 
> Hmm, technically all unassigned USB-devices are usable from Dom0. So why
> not list them there.
> 
> "xl usb-list 0" would be the same then as "xl usb-list --host".
> "xl usb-list" would be the same as "xl usb-list --all".
> 
> Just a thought - I'm fine with either variant.

Haha -- well, I guess that's one way of looking at it. :-)

dom0 is different from the others, however, in that "xl pci-attach" will
automatically remove it from dom0 and give it to another VM.  If that
was true for all domains, I'd be on board with it.  And of course it
doesn't work for driver domains.

 -George

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 14:05                           ` Ian Campbell
@ 2015-10-07 14:26                             ` Juergen Gross
  2015-10-07 14:35                               ` George Dunlap
  0 siblings, 1 reply; 59+ messages in thread
From: Juergen Gross @ 2015-10-07 14:26 UTC (permalink / raw)
  To: Ian Campbell, George Dunlap
  Cc: Wei Liu, Jim Fehlig, Ian Jackson, Chunyan Liu, xen-devel

On 10/07/2015 04:05 PM, Ian Campbell wrote:
> On Wed, 2015-10-07 at 15:54 +0200, Juergen Gross wrote:
>
>> Hmm, technically all unassigned USB-devices are usable from Dom0. So why
>> not list them there.
>
> I think you'd at least want to distinguish USB devices available to dom0 as
> via a PCI host controller from those which are available via pvusb.

Yeah, the non-pvusb devices should be listed as "assignable" if they
are handled by a driver domain.

> This also doesn't quite work when driver domains are in the picture.

--host does?

TBH: driver domains seem to be a reason to not support the --host
option. So the options are --all or no special option. I'm still
fine with both.

BTW: Do Xen concepts allow to assign a USB-device via pvUSB from a
driver domain to Dom0?


Juergen

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 14:26                             ` Juergen Gross
@ 2015-10-07 14:35                               ` George Dunlap
  2015-10-07 14:47                                 ` Juergen Gross
  0 siblings, 1 reply; 59+ messages in thread
From: George Dunlap @ 2015-10-07 14:35 UTC (permalink / raw)
  To: Juergen Gross
  Cc: Wei Liu, Ian Campbell, Ian Jackson, Chunyan Liu, George Dunlap,
	Jim Fehlig, xen-devel

On Wed, Oct 7, 2015 at 3:26 PM, Juergen Gross <jgross@suse.com> wrote:
> On 10/07/2015 04:05 PM, Ian Campbell wrote:
>>
>> On Wed, 2015-10-07 at 15:54 +0200, Juergen Gross wrote:
>>
>>> Hmm, technically all unassigned USB-devices are usable from Dom0. So why
>>> not list them there.
>>
>>
>> I think you'd at least want to distinguish USB devices available to dom0
>> as
>> via a PCI host controller from those which are available via pvusb.
>
>
> Yeah, the non-pvusb devices should be listed as "assignable" if they
> are handled by a driver domain.
>
>> This also doesn't quite work when driver domains are in the picture.
>
>
> --host does?
>
> TBH: driver domains seem to be a reason to not support the --host
> option. So the options are --all or no special option. I'm still
> fine with both.

I think the idea is that --host doesn't pretend to.  But yes, if we
made it clear which devices were *assigned* to dom0 from another VM,
and which were *available from* dom0 to be assigned, then actually
that could be extended at some point in the future to include devices
available *from* driver domains.

Alternately, perhaps we should just have
# xl usb-available [domain]

Which will tell you the usb devices available to be assigned from that
domain; or all available usb devices from all driver domains.  And of
course for the time being it only works on domain 0, but future
functionality could implement it for driver domains as well.

> BTW: Do Xen concepts allow to assign a USB-device via pvUSB from a
> driver domain to Dom0?

Sure, why not?

 -George

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 14:35                               ` George Dunlap
@ 2015-10-07 14:47                                 ` Juergen Gross
  2015-10-07 15:03                                   ` George Dunlap
  0 siblings, 1 reply; 59+ messages in thread
From: Juergen Gross @ 2015-10-07 14:47 UTC (permalink / raw)
  To: George Dunlap
  Cc: Wei Liu, Ian Campbell, Ian Jackson, George Dunlap, Chunyan Liu,
	Jim Fehlig, xen-devel

On 10/07/2015 04:35 PM, George Dunlap wrote:
> On Wed, Oct 7, 2015 at 3:26 PM, Juergen Gross <jgross@suse.com> wrote:
>> On 10/07/2015 04:05 PM, Ian Campbell wrote:
>>>
>>> On Wed, 2015-10-07 at 15:54 +0200, Juergen Gross wrote:
>>>
>>>> Hmm, technically all unassigned USB-devices are usable from Dom0. So why
>>>> not list them there.
>>>
>>>
>>> I think you'd at least want to distinguish USB devices available to dom0
>>> as
>>> via a PCI host controller from those which are available via pvusb.
>>
>>
>> Yeah, the non-pvusb devices should be listed as "assignable" if they
>> are handled by a driver domain.
>>
>>> This also doesn't quite work when driver domains are in the picture.
>>
>>
>> --host does?
>>
>> TBH: driver domains seem to be a reason to not support the --host
>> option. So the options are --all or no special option. I'm still
>> fine with both.
>
> I think the idea is that --host doesn't pretend to.  But yes, if we
> made it clear which devices were *assigned* to dom0 from another VM,
> and which were *available from* dom0 to be assigned, then actually
> that could be extended at some point in the future to include devices
> available *from* driver domains.
>
> Alternately, perhaps we should just have
> # xl usb-available [domain]

Would work for me.

Wait, wasn't there a similar command suggested? Something like
"xl usb-assignable-list"? ;-)

> Which will tell you the usb devices available to be assigned from that
> domain; or all available usb devices from all driver domains.  And of
> course for the time being it only works on domain 0, but future
> functionality could implement it for driver domains as well.
>
>> BTW: Do Xen concepts allow to assign a USB-device via pvUSB from a
>> driver domain to Dom0?
>
> Sure, why not?

With driver domains the picture is becoming more complicated.

The main question now is: What is the real purpose of "xl usb-list"?
Should it list the devices which are assigned to a domain, or should it
list the devices which are usable by a domain (probably attributed
whether the device is assignable to other domains)?

I think I'll always use the --all option in case this variant will be
chosen.


Juergen

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 14:47                                 ` Juergen Gross
@ 2015-10-07 15:03                                   ` George Dunlap
  2015-10-07 15:13                                     ` Juergen Gross
  0 siblings, 1 reply; 59+ messages in thread
From: George Dunlap @ 2015-10-07 15:03 UTC (permalink / raw)
  To: Juergen Gross, George Dunlap
  Cc: Wei Liu, Ian Campbell, Ian Jackson, Chunyan Liu, xen-devel, Jim Fehlig

On 07/10/15 15:47, Juergen Gross wrote:
> On 10/07/2015 04:35 PM, George Dunlap wrote:
>> On Wed, Oct 7, 2015 at 3:26 PM, Juergen Gross <jgross@suse.com> wrote:
>>> On 10/07/2015 04:05 PM, Ian Campbell wrote:
>>>>
>>>> On Wed, 2015-10-07 at 15:54 +0200, Juergen Gross wrote:
>>>>
>>>>> Hmm, technically all unassigned USB-devices are usable from Dom0.
>>>>> So why
>>>>> not list them there.
>>>>
>>>>
>>>> I think you'd at least want to distinguish USB devices available to
>>>> dom0
>>>> as
>>>> via a PCI host controller from those which are available via pvusb.
>>>
>>>
>>> Yeah, the non-pvusb devices should be listed as "assignable" if they
>>> are handled by a driver domain.
>>>
>>>> This also doesn't quite work when driver domains are in the picture.
>>>
>>>
>>> --host does?
>>>
>>> TBH: driver domains seem to be a reason to not support the --host
>>> option. So the options are --all or no special option. I'm still
>>> fine with both.
>>
>> I think the idea is that --host doesn't pretend to.  But yes, if we
>> made it clear which devices were *assigned* to dom0 from another VM,
>> and which were *available from* dom0 to be assigned, then actually
>> that could be extended at some point in the future to include devices
>> available *from* driver domains.
>>
>> Alternately, perhaps we should just have
>> # xl usb-available [domain]
> 
> Would work for me.
> 
> Wait, wasn't there a similar command suggested? Something like
> "xl usb-assignable-list"? ;-)

Indeed there was!  A very useful command with a very sensible name...
unfortunately one with a very *similar* name to another command but with
different functionality.  And this similarity even confused one of the
tools maintainers, so would almost certainly confuse our users. :-)

>> Which will tell you the usb devices available to be assigned from that
>> domain; or all available usb devices from all driver domains.  And of
>> course for the time being it only works on domain 0, but future
>> functionality could implement it for driver domains as well.
>>
>>> BTW: Do Xen concepts allow to assign a USB-device via pvUSB from a
>>> driver domain to Dom0?
>>
>> Sure, why not?
> 
> With driver domains the picture is becoming more complicated.
> 
> The main question now is: What is the real purpose of "xl usb-list"?
> Should it list the devices which are assigned to a domain, or should it
> list the devices which are usable by a domain (probably attributed
> whether the device is assignable to other domains)?

For *all* of our other -list commands relating to guest devices --
pci-list, disk-list, network-list, vtpm-list, channel-list, tmem-list --
the list command shows the virtual devices *actually assigned to the
VM*.   Based on that, the core information that any user will *expect*
from "usb-list" will be "what usb devices are assigned to this VM".

I'm not opposed to extending usb-list to include extra useful
information; but it should be made clear to the user which information
is the "core expected" information (i.e., what usb devices are assigned
to this VM) and what is "extra" information (i.e., what usb devices are
available to be assigned *from* this VM).

So I think we have 3 options that people don't find objectionable:

1. Add --all and --host options to usb-list. (Or perhaps, --available.)

2. Have usb-list also list "available" devices from driver domains,
clearly marked distinct from devices *assigned to* that driver domain
from another domain, and to begin with only working for dom0.

3. A new command, "usb-available" to list available devices from driver
domains, to begin with only working for dom0.

I think I'd go for #3, but mostly I think we need to decide *something*
so we can move forward.

 -George

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 7/7] domcreate: support pvusb in configuration file
  2015-09-25  2:11 ` [PATCH V7 7/7] domcreate: support pvusb in configuration file Chunyan Liu
@ 2015-10-07 15:06   ` George Dunlap
  0 siblings, 0 replies; 59+ messages in thread
From: George Dunlap @ 2015-10-07 15:06 UTC (permalink / raw)
  To: Chunyan Liu, xen-devel
  Cc: jgross, wei.liu2, ian.campbell, george.dunlap, Ian.Jackson,
	jfehlig, Simon Cao

On 25/09/15 03:11, Chunyan Liu wrote:
> Add code to support pvusb in domain config file. One could specify
> usbctrl and usb in domain's configuration file and create domain,
> then usb controllers will be created and usb device would be attached
> to guest automatically.
> 
> One could specify usb controllers and usb devices in config file
> like this:
> usbctrl=['version=2,ports=4', 'version=1, ports=4', ]
> usbdev=['2.1,controller=0,port=1', ]

I realize you're patterning this after pci, but this syntax assumes that
you're always going to want to pass in a host device, which I think we
don't want to do.  In particular, we want to leave the door open in the
future to different ways of being able to specify a particular device
based on the pci + usb topology which will be invariant over reboots.

So I think all parameters should have a name.

Two questions; first, the name of the parameter specifying hostbus and
hostaddr.

1. "hostspec=", which will automatically use 2.1 for bus.addr, and could
in the future be extended to use 2-1 for bus-port,  xxxx:yyyy for
vendorid:productid, and potentially the udev "pci + usb topology" thing.

2. hostbus=x, hostaddr=y.  This is what qemu and libvirt do.  It also
leaves open the door for adding double-checks or other constraints:
e.g., hostbus=x, hostaddr=y, hostvid=m, hostpid=n would only assign x.y
if vendorid:productid match m:n

I'd go for #2.

We should also have a "type" field, of which one option should be
"hostdev". I think it's probably OK to assume "hostdev" if we have
hostdev-only parameters.

One more comment...

>  /* First layer; wraps libxl__spawn_spawn. */
> diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
> index 66d8f8c..c64e445 100644
> --- a/tools/libxl/xl_cmdimpl.c
> +++ b/tools/libxl/xl_cmdimpl.c
> @@ -1253,6 +1253,79 @@ static void parse_vnuma_config(const XLU_Config *config,
>      free(vcpu_parsed);
>  }
>  
> +static void parse_usbctrl_config(libxl_device_usbctrl *usbctrl,
> +                                 const char *buf)
> +{
> +    char *buf2 = strdup(buf);
> +    char *p, *p2;
> +
> +    p = strtok(buf2, ",");
> +    if (!p)
> +        goto out;
> +    do {
> +        while (*p == ' ')
> +            p++;
> +        if ((p2 = strchr(p, '=')) == NULL)
> +            break;
> +        *p2 = '\0';
> +        if (!strcmp(p, "type")) {
> +            if (!strcmp(p2 + 1, "pv")) {

I'd probably do "*p2='\0'; p2++" so that then later you can just use p2
as a normal string, rather than p2+1 as you do here.

But what I'd *really* do is copy the parse_nic_config() code, and use
MATCH_STRING("type", ...).

And as Ian said, I'd move these parsing functions into the previous
patch, and then use them to parse the command-line arguments (again
modelled after main_networkattach()).

(I'm not confident in the multidev stuff enough to give a proper review.)

 -George

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 6/7] xl: add usb-assignable-list command
  2015-10-07 15:03                                   ` George Dunlap
@ 2015-10-07 15:13                                     ` Juergen Gross
  0 siblings, 0 replies; 59+ messages in thread
From: Juergen Gross @ 2015-10-07 15:13 UTC (permalink / raw)
  To: George Dunlap, George Dunlap
  Cc: Wei Liu, Ian Campbell, Ian Jackson, Chunyan Liu, xen-devel, Jim Fehlig

On 10/07/2015 05:03 PM, George Dunlap wrote:
> On 07/10/15 15:47, Juergen Gross wrote:
>> On 10/07/2015 04:35 PM, George Dunlap wrote:
>>> On Wed, Oct 7, 2015 at 3:26 PM, Juergen Gross <jgross@suse.com> wrote:
>>>> On 10/07/2015 04:05 PM, Ian Campbell wrote:
>>>>>
>>>>> On Wed, 2015-10-07 at 15:54 +0200, Juergen Gross wrote:
>>>>>
>>>>>> Hmm, technically all unassigned USB-devices are usable from Dom0.
>>>>>> So why
>>>>>> not list them there.
>>>>>
>>>>>
>>>>> I think you'd at least want to distinguish USB devices available to
>>>>> dom0
>>>>> as
>>>>> via a PCI host controller from those which are available via pvusb.
>>>>
>>>>
>>>> Yeah, the non-pvusb devices should be listed as "assignable" if they
>>>> are handled by a driver domain.
>>>>
>>>>> This also doesn't quite work when driver domains are in the picture.
>>>>
>>>>
>>>> --host does?
>>>>
>>>> TBH: driver domains seem to be a reason to not support the --host
>>>> option. So the options are --all or no special option. I'm still
>>>> fine with both.
>>>
>>> I think the idea is that --host doesn't pretend to.  But yes, if we
>>> made it clear which devices were *assigned* to dom0 from another VM,
>>> and which were *available from* dom0 to be assigned, then actually
>>> that could be extended at some point in the future to include devices
>>> available *from* driver domains.
>>>
>>> Alternately, perhaps we should just have
>>> # xl usb-available [domain]
>>
>> Would work for me.
>>
>> Wait, wasn't there a similar command suggested? Something like
>> "xl usb-assignable-list"? ;-)
>
> Indeed there was!  A very useful command with a very sensible name...
> unfortunately one with a very *similar* name to another command but with
> different functionality.  And this similarity even confused one of the
> tools maintainers, so would almost certainly confuse our users. :-)
>
>>> Which will tell you the usb devices available to be assigned from that
>>> domain; or all available usb devices from all driver domains.  And of
>>> course for the time being it only works on domain 0, but future
>>> functionality could implement it for driver domains as well.
>>>
>>>> BTW: Do Xen concepts allow to assign a USB-device via pvUSB from a
>>>> driver domain to Dom0?
>>>
>>> Sure, why not?
>>
>> With driver domains the picture is becoming more complicated.
>>
>> The main question now is: What is the real purpose of "xl usb-list"?
>> Should it list the devices which are assigned to a domain, or should it
>> list the devices which are usable by a domain (probably attributed
>> whether the device is assignable to other domains)?
>
> For *all* of our other -list commands relating to guest devices --
> pci-list, disk-list, network-list, vtpm-list, channel-list, tmem-list --
> the list command shows the virtual devices *actually assigned to the
> VM*.   Based on that, the core information that any user will *expect*
> from "usb-list" will be "what usb devices are assigned to this VM".
>
> I'm not opposed to extending usb-list to include extra useful
> information; but it should be made clear to the user which information
> is the "core expected" information (i.e., what usb devices are assigned
> to this VM) and what is "extra" information (i.e., what usb devices are
> available to be assigned *from* this VM).
>
> So I think we have 3 options that people don't find objectionable:
>
> 1. Add --all and --host options to usb-list. (Or perhaps, --available.)
>
> 2. Have usb-list also list "available" devices from driver domains,
> clearly marked distinct from devices *assigned to* that driver domain
> from another domain, and to begin with only working for dom0.
>
> 3. A new command, "usb-available" to list available devices from driver
> domains, to begin with only working for dom0.
>
> I think I'd go for #3, but mostly I think we need to decide *something*
> so we can move forward.

+1 for both. :-)

Juergen

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 3/7] libxl: add pvusb API
  2015-09-25  2:11 ` [PATCH V7 3/7] libxl: add pvusb API Chunyan Liu
  2015-09-30 17:55   ` George Dunlap
@ 2015-10-08 14:41   ` Ian Jackson
  2015-10-08 14:54     ` Ian Campbell
  2015-10-12  7:00     ` Chun Yan Liu
  1 sibling, 2 replies; 59+ messages in thread
From: Ian Jackson @ 2015-10-08 14:41 UTC (permalink / raw)
  To: Chunyan Liu
  Cc: jgross, wei.liu2, ian.campbell, george.dunlap, xen-devel,
	jfehlig, Simon Cao

Chunyan Liu writes ("[PATCH V7 3/7] libxl: add pvusb API"):
> Add pvusb APIs, including:
...

> +/* Utility to read backend xenstore keys */
> +#define READ_BACKEND(tgc, subpath)                                    \
> +            libxl__xs_read(tgc, XBT_NULL, GCSPRINTF("%s/" subpath, be_path))
> +
> +/* Utility to read frontend xenstore keys */
> +#define READ_FRONTEND(tgc, subpath)                                   \
> +            libxl__xs_read(tgc, XBT_NULL, GCSPRINTF("%s/" subpath, fe_path))
> +

Thanks for trying to reduce repetition.  But I think these macros need
to be improved.  I'm am not particularly keen on them in this form,
for a number of reasons.

 * They implicitly rely on variables (be_path and fe_path) being in
   scope but there is no associated doc comment.  That would be OK if
   they were macros defined within a single function and #undef'd
   before the function end.

 * Their functionality is not really usb-specific.  If this is a good
   thing to do they should be in libxl_internal.h.

 * They should use libxl__xs_read_checked.  That means they should
   probably also implicitly assume that rc is in scope, and `goto out'
   on error.  (There are many calls to libxl__xs_read here to which
   the same observation applies.)

 * I think there is no reason for these to take a `tgc' parameter.
   All of the call sites pass exactly `gc'.  If these macros are going
   to make assumptions about what's in their scope, `gc' is a very
   good candidate (which many existing macros rely on).

You can go two routes with this: make much more local macros, and
#undef them.  Or formalise these macros and widen their scope to the
whole of libxl.  I think the latter would probably be best.

Perhaps something like:

/*
 * const char *READ_SUBPATH(const char *febe_path, const char *subpath);
 *
 * Expects in scope:
 *    int rc;
 *    libxl__gc *gc;
 *    out:
 *
 * Reads febe_path/subpath from xenstore.  Does not use a transaction.
 * On xenstore errors, sets rc and does `goto out'.
 * If the path does not exist, returns NULL.
 */
#define READ_SUBPATH(febe_path, subpath) ...

What do you think ?


> +/* AO operation to add a usb controller.
> + *
> + * Generally, it does:
> + * 1) fill in necessary usb controler information with default value
> + * 2) write usb controller frontend/backend info to xenstore, update json
> + *    config file if necessary.
> + * 3) wait for device connection. PVUSB frontend and backend driver will
> + *    probe xenstore paths and build connection between frontend and backend.
> + */
> +void libxl__device_usbctrl_add(libxl__egc *egc, uint32_t domid,
> +                               libxl_device_usbctrl *usbctrl,
> +                               libxl__ao_device *aodev)
> +{
> +    STATE_AO_GC(aodev->ao);
> +    libxl__device *device;
> +    int rc;
> +
> +    rc = libxl__device_usbctrl_setdefault(gc, domid, usbctrl);
> +    if (rc < 0) goto out;
> +
> +    if (usbctrl->devid == -1) {
> +        usbctrl->devid = libxl__device_nextid(gc, domid, "vusb");
> +        if (usbctrl->devid < 0) {
> +            rc = ERROR_FAIL;
> +            goto out;
> +        }
> +    }
> +
> +    if (usbctrl->type != LIBXL_USBCTRL_TYPE_PV) {
> +        LOG(ERROR, "Unsupported USB controller type");
> +        rc = ERROR_FAIL;
> +        goto out;
> +    }
> +
> +    rc = libxl__device_usbctrl_add_xenstore(gc, domid, usbctrl,
> +                                            aodev->update_json);
> +    if (rc) goto out;
> +
> +    GCNEW(device);
> +    rc = libxl__device_from_usbctrl(gc, domid, usbctrl, device);
> +    if (rc) goto out;
> +
> +    aodev->dev = device;
> +    aodev->action = LIBXL__DEVICE_ACTION_ADD;
> +    libxl__wait_device_connection(egc, aodev);
> +    rc = 0;
> +
> +out:
> +    aodev->rc = rc;
> +    if (rc) aodev->callback(egc, aodev);

This is wrong (even though it works with the remaining code as it
stands), I'm afraid.

The right pattern is to `return 0' after
libxl__wait_device_connection, because libxl__wait_device_connection
will always make a callback.

Also the doc comment for this function should make it clear which of
the fields in aodev must be filled in by the caller.  After you do
that you should make sure that the call site obeys the rules.  (This
is not something I have checked right now because the rules aren't
stated.)

Both of these observations apply to the remove path as well.

> +/* AO function to remove a usb controller.
> + *
> + * Generally, it does:
> + * 1) check if the usb controller exists or not
> + * 2) remove all usb devices under controller
> + * 3) remove usb controller information from xenstore
> + */
> +void libxl__initiate_device_usbctrl_remove(libxl__egc *egc,
> +                                           libxl__ao_device *aodev)

What happens if this functionality is running to try to remove the
controller, at the same time as another process is trying to remove a
device from the controller, or (worse) add a device to the
controller ?  Obviously I don't expect 100% successful outcomes, but I
want to know that the severity of the consequences is limited.

> +libxl_device_usbctrl *
> +libxl_device_usbctrl_list(libxl_ctx *ctx, uint32_t domid, int *num)
> +{

This function should return an rc, and the list should come in an out
parameter.

> +    dir = libxl__xs_directory(gc, XBT_NULL, path, &ndirs);

The variables `dir' and `ndirs' should be `entry' and `nentries'.

> +    if (dir && ndirs) {
> +        usbctrls = libxl__zalloc(NOGC, sizeof(*usbctrls) * ndirs);
> +        libxl_device_usbctrl *usbctrl;
> +        libxl_device_usbctrl *end = usbctrls + ndirs;
> +        for (usbctrl = usbctrls; usbctrl < end; usbctrl++, dir++, (*num)++) {

This line would be better wrapped at the semicolons, IMO.

> +            const char *tmp, *be_path;
> +            const char *fe_path = GCSPRINTF("%s/%s", path, *dir);
> +
> +            libxl_device_usbctrl_init(usbctrl);
> +            usbctrl->devid = atoi(*dir);
> +
> +            tmp = READ_FRONTEND(gc, "backend-id");
> +            if (!tmp) goto outerr;
> +            usbctrl->backend_domid = atoi(tmp);
> +
> +            tmp = READ_BACKEND(gc, "usb-ver");
> +            if (!tmp) goto outerr;
> +            usbctrl->version = atoi(tmp);
> +
> +            tmp = READ_BACKEND(gc, "num-ports");
> +            if (!tmp) goto outerr;
> +            usbctrl->ports = atoi(tmp);

There are 4 nearly identical stanzas here.  I think a more
comprehensive would be helpful.  Maybe a global macro READ_SUBPATH_INT
along the lines of my READ_SUBPATH, above, would be useful, and then:

               usbctrl->ports = READ_SUBPATH_INT(be_path, "num-ports");

and there would be no need for any open-coded error handling.

> +int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid,
> +                                libxl_device_usbctrl *usbctrl,
> +                                libxl_usbctrlinfo *usbctrlinfo)
...
> +    tmp = READ_FRONTEND(gc, "backend-id");
> +    usbctrlinfo->backend_id = tmp ? strtoul(tmp, NULL, 10) : -1;

Under what circumstances can these be validly missing ?  I'm not very
happy with the idea of filling in the struct with -1.

> +int libxl_devid_to_device_usbctrl(libxl_ctx *ctx,
> +                                  uint32_t domid,
> +                                  int devid,
> +                                  libxl_device_usbctrl *usbctrl)
> +{
> +    GC_INIT(ctx);
> +    libxl_device_usbctrl *usbctrls;
> +    int nb = 0;
> +    int i, rc = -1;

Initialising rc like this is a bad idea.  Instead, it should be set
explicitly on each error path.  That alllows the compiler to spot
error paths that do not set rc.  Also rc=-1 is not permitted because
rc ought to be a libxl error code.  You probably want ERROR_NOTFOUND.

> +static char *usb_busaddr_to_busid(libxl__gc *gc, int bus, int addr)
> +{
> +        filename = GCSPRINTF(SYSFS_USB_DEV"/%s/devnum", de->d_name);
> +        if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
> +            sscanf(buf, "%d", &devnum);

If the file contents are invalid, devnum will be left uninitialised.
Why using sscanf rather than atoi (if you don't want to check for
unexpected data) or strtoul (if you do) ?  (Same thing later in
usb_busaddr_from_busid.)

> +        if (bus == busnum && addr == devnum) {
> +            busid = libxl__strdup(NOGC, de->d_name);
> +            break;

This allocates non-gc'd memory but (a) this is not documented contrary
to the rules in libxl_internal.h and (b) some of its callers do not
want non-gc'd memory.

> +static void usb_busaddr_from_busid(libxl__gc *gc, char *busid,
> +                                   uint8_t *bus, uint8_t *addr)

Lack of const-correctness: busid should be const char *.

> +    assert(busid);

This is not necessary.  Please drop it.  If it's NULL, we'll crash in
snprintf soon enough.


I think that many of my comments can be generalised to the rest of
this patch.  I think it would be better for me to stop reading now and
await a new version.  (I'm finding it difficult to see the overall
structure of the code, and to remember the things I'm trying to look
out for along with the things I'm trying to disregard because I have
already mentioned them.)

Specifically, can you please make sure to take every one of my
comments above, and treat it as relevant everywhere that it (or an
analagous comment) is applicable in your code.

Thanks,
Ian.

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 3/7] libxl: add pvusb API
  2015-10-08 14:41   ` Ian Jackson
@ 2015-10-08 14:54     ` Ian Campbell
  2015-10-08 15:16       ` Ian Jackson
  2015-10-12  7:00     ` Chun Yan Liu
  1 sibling, 1 reply; 59+ messages in thread
From: Ian Campbell @ 2015-10-08 14:54 UTC (permalink / raw)
  To: Ian Jackson, Chunyan Liu
  Cc: jgross, wei.liu2, george.dunlap, xen-devel, jfehlig, Simon Cao

On Thu, 2015-10-08 at 15:41 +0100, Ian Jackson wrote:

> > +libxl_device_usbctrl *
> > +libxl_device_usbctrl_list(libxl_ctx *ctx, uint32_t domid, int *num)
> > +{
> 
> This function should return an rc, and the list should come in an out
> parameter.

For better of worse libxl.h defines the general form of a device API to
include list looking like this (search for "Querying").

If this were for an actual device I'd be adamant that it should follow that
pattern.

Since this is part of a new "controller" abstraction we do in theory have
the freedom to do things differently, but it seems to me that having
something as basic as the list operation differ for devices vs. controller
would do more harm than good even if the controller interface is strictly
better. IOW I'm willing to be convinced otherwise but right now I'm pretty
sure how it is above is the preferable extension to our API.

> > +            const char *tmp, *be_path;
> > +            const char *fe_path = GCSPRINTF("%s/%s", path, *dir);
> > +
> > +            libxl_device_usbctrl_init(usbctrl);
> > +            usbctrl->devid = atoi(*dir);
> > +
> > +            tmp = READ_FRONTEND(gc, "backend-id");
> > +            if (!tmp) goto outerr;
> > +            usbctrl->backend_domid = atoi(tmp);
> > +
> > +            tmp = READ_BACKEND(gc, "usb-ver");
> > +            if (!tmp) goto outerr;
> > +            usbctrl->version = atoi(tmp);
> > +
> > +            tmp = READ_BACKEND(gc, "num-ports");
> > +            if (!tmp) goto outerr;
> > +            usbctrl->ports = atoi(tmp);
> 
> There are 4 nearly identical stanzas here.  I think a more
> comprehensive would be helpful.  Maybe a global macro READ_SUBPATH_INT
               ^MACRO?

Ian.

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 3/7] libxl: add pvusb API
  2015-10-08 14:54     ` Ian Campbell
@ 2015-10-08 15:16       ` Ian Jackson
  0 siblings, 0 replies; 59+ messages in thread
From: Ian Jackson @ 2015-10-08 15:16 UTC (permalink / raw)
  To: Ian Campbell
  Cc: jgross, wei.liu2, george.dunlap, Chunyan Liu, xen-devel, jfehlig,
	Simon Cao

Ian Campbell writes ("Re: [PATCH V7 3/7] libxl: add pvusb API"):
> Since this is part of a new "controller" abstraction we do in theory have
> the freedom to do things differently, but it seems to me that having
> something as basic as the list operation differ for devices vs. controller
> would do more harm than good even if the controller interface is strictly
> better. IOW I'm willing to be convinced otherwise but right now I'm pretty
> sure how it is above is the preferable extension to our API.

Hrm.  OK, I guess :-/.

> > > +            tmp = READ_BACKEND(gc, "num-ports");
> > > +            if (!tmp) goto outerr;
> > > +            usbctrl->ports = atoi(tmp);
> > 
> > There are 4 nearly identical stanzas here.  I think a more
> > comprehensive would be helpful.  Maybe a global macro READ_SUBPATH_INT
>                ^MACRO?

Yes.

Ian.

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 5/7] xl: add pvusb commands
  2015-10-01 17:02   ` George Dunlap
  2015-10-02 13:35     ` Ian Campbell
@ 2015-10-09  7:15     ` Chun Yan Liu
  1 sibling, 0 replies; 59+ messages in thread
From: Chun Yan Liu @ 2015-10-09  7:15 UTC (permalink / raw)
  To: George Dunlap, xen-devel
  Cc: Juergen Gross, wei.liu2, ian.campbell, george.dunlap,
	Ian.Jackson, Jim Fehlig, Simon Cao



>>> On 10/2/2015 at 01:02 AM, in message <560D6733.4030503@citrix.com>, George
Dunlap <george.dunlap@citrix.com> wrote: 
> On 25/09/15 03:11, Chunyan Liu wrote: 
> > Add pvusb commands: usb-ctrl-attach, usb-ctrl-detach, usb-list, 
> > usb-attach and usb-detach. 
> >  
> > To attach a usb device to guest through pvusb, one could follow 
> > following example: 
> >  
> >  #xl usb-ctrl-attach test_vm version=1 num_ports=8 
>  
> So all the way back in v2 of this series, I suggested making the 
> arguments for usb-ctrl-attach and usb-attach mirror the format that is 
> found in the config file[1], at which point you replied "That could be, 
> I can update".  But you didn't change the interface in v3, so I 
> suggested it again[2], and there was no argument or discussion about it. 
>  
> (There was a long back-and-forth with Juergen at that point about 
> usb-assignable-list, so [2] may have gotten lost in the noise.) 
>  
> I still think that's the best interface to use.  Do you have reasons to 
> favor the interface you propose here?

Sorry for replying late, just back from holiday.

It's my fault not updating it, missing that after a lot of other changes, not
favor this or that. Thanks for reminding again.

- Chunyan

>  
>  -George 
>  
> [1] 
> marc.info/?i=<CAFLBxZb1N3_9PVvg-yC8dyVaiySZVRA3H2e8496vHNEfvrm6Zg@mail.gmail.c 
>om> 
>  
> [2] 
> marc.info/?i=<CAFLBxZbJcdFi2cXOvQRncbdV0HBL73d8sjXKry+VaRjvkQtRwA@mail.gmail. 
> com> 
>  
> >  
> >  #xl usb-list test_vm 
> >  will show the usb controllers and port usage under the domain. 
> >  
> >  #xl usb-attach test_vm 1.6 
> >  will find the first usable controller:port, and attach usb 
> >  device whose bus address is 1.6 (busnum is 1, devnum is 6) 
> >  to it. One could also specify which <controller> and which <port>. 
> >  
> >  #xl usb-detach test_vm 0 1 
> >  will detach USB device under controller 0 port 1. 
> >  
> >  #xl usb-ctrl-detach test_vm dev_id 
> >  will destroy the controller with specified dev_id. Dev_id 
> >  can be traced in usb-list info. 
> >  
> > Signed-off-by: Chunyan Liu <cyliu@suse.com> 
> > Signed-off-by: Simon Cao <caobosimon@gmail.com> 
> > --- 
> >  docs/man/xl.pod.1         |  40 ++++++++ 
> >  tools/libxl/xl.h          |   5 + 
> >  tools/libxl/xl_cmdimpl.c  | 232  
> ++++++++++++++++++++++++++++++++++++++++++++++ 
> >  tools/libxl/xl_cmdtable.c |  25 +++++ 
> >  4 files changed, 302 insertions(+) 
> >  
> > diff --git a/docs/man/xl.pod.1 b/docs/man/xl.pod.1 
> > index f22c3f3..4c92c78 100644 
> > --- a/docs/man/xl.pod.1 
> > +++ b/docs/man/xl.pod.1 
> > @@ -1345,6 +1345,46 @@ List pass-through pci devices for a domain. 
> >   
> >  =back 
> >   
> > +=head1 USB PASS-THROUGH 
> > + 
> > +=over 4 
> > + 
> > +=item B<usb-ctrl-attach> I<domain-id> I[<type=val>] [I<version=val>] [I<ports=number>] 
> > + 
> > +Create a new USB controller for the specified domain. 
> > +B<type=val> is the usb controller type, currently only support 'pv'. 
> > +B<version=val> is the usb controller version, could be 1 (USB1.1) or 2  
> (USB2.0). 
> > +B<ports=number> is the total ports of the usb controller. 
> > +By default, it will create a USB2.0 controller with 8 ports. 
> > + 
> > +=item B<usb-ctrl-detach> I<domain-id> I<devid> 
> > + 
> > +Destroy a USB controller from the specified domain. 
> > +B<devid> is devid of the USB controller. 
> > + 
> > +If B<-f> is specified, B<xl> is going to forcefully remove the device even 
> > +without guest's collaboration. 
> > + 
> > +=item B<usb-attach> I<domain-id> I<bus.addr> [I<controller=devid> [I<port=number>]] 
> > + 
> > +Hot-plug a new pass-through USB device to the specified domain. 
> > +B<bus.addr> is the busnum.devnum of the physical USB device to pass-through. 
> > +B<controller=devid> B<port=number> is the USB controller:port to hotplug the 
> > +USB device to. By default, it will find the first available  
> controller:port 
> > +and use it; if there is no controller, it will create one. 
> > + 
> > +=item B<usb-detach> I<domain-id> I<controller=devid> I<port=number> 
> > + 
> > +Hot-unplug a previously assigned USB device from a domain. 
> > +B<controller=devid> and B<port=number> is USB controller:port in guest where  
> the 
> > +USB device is attached to. 
> > + 
> > +=item B<usb-list> I<domain-id> 
> > + 
> > +List pass-through usb devices for a domain. 
> > + 
> > +=back 
> > + 
> >  =head1 TMEM 
> >   
> >  =over 4 
> > diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h 
> > index 6c19c0d..26f6c1e 100644 
> > --- a/tools/libxl/xl.h 
> > +++ b/tools/libxl/xl.h 
> > @@ -85,6 +85,11 @@ int main_blockdetach(int argc, char **argv); 
> >  int main_vtpmattach(int argc, char **argv); 
> >  int main_vtpmlist(int argc, char **argv); 
> >  int main_vtpmdetach(int argc, char **argv); 
> > +int main_usbctrl_attach(int argc, char **argv); 
> > +int main_usbctrl_detach(int argc, char **argv); 
> > +int main_usbattach(int argc, char **argv); 
> > +int main_usbdetach(int argc, char **argv); 
> > +int main_usblist(int argc, char **argv); 
> >  int main_uptime(int argc, char **argv); 
> >  int main_claims(int argc, char **argv); 
> >  int main_tmem_list(int argc, char **argv); 
> > diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c 
> > index 2706759..6ae9479 100644 
> > --- a/tools/libxl/xl_cmdimpl.c 
> > +++ b/tools/libxl/xl_cmdimpl.c 
> > @@ -3367,6 +3367,238 @@ int main_cd_insert(int argc, char **argv) 
> >      return 0; 
> >  } 
> >   
> > +int main_usbctrl_attach(int argc, char **argv) 
> > +{ 
> > +    uint32_t domid; 
> > +    int opt, rc = 1; 
> > +    char *oparg; 
> > +    libxl_device_usbctrl usbctrl; 
> > + 
> > +    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-ctrl-attach", 1) { 
> > +        /* No options */ 
> > +    } 
> > + 
> > +    domid = find_domain(argv[optind++]); 
> > + 
> > +    libxl_device_usbctrl_init(&usbctrl); 
> > + 
> > +    while (argc > optind) { 
> > +        if (MATCH_OPTION("type", argv[optind], oparg)) { 
> > +            if (!strcmp(oparg, "pv")) { 
> > +                usbctrl.type = LIBXL_USBCTRL_TYPE_PV; 
> > +            } else { 
> > +                fprintf(stderr, "unsupported type `%s'\n", oparg); 
> > +                goto out; 
> > +            } 
> > +        } else if (MATCH_OPTION("version", argv[optind], oparg)) { 
> > +            usbctrl.version = atoi(oparg); 
> > +            if (usbctrl.version != 1 && usbctrl.version != 2) { 
> > +                fprintf(stderr, "unsupported version `%s'\n", oparg); 
> > +                goto out; 
> > +            } 
> > +        } else if (MATCH_OPTION("ports", argv[optind], oparg)) { 
> > +            usbctrl.ports = atoi(oparg); 
> > +            if (usbctrl.ports < 1 || usbctrl.ports > 31) { 
> > +                fprintf(stderr, "unsupported ports `%s'\n", oparg); 
> > +                goto out; 
> > +            } 
> > +        } else { 
> > +            fprintf(stderr, "unrecognized argument `%s'\n", argv[optind]); 
> > +            goto out; 
> > +        } 
> > +        optind++; 
> > +    } 
> > + 
> > +    rc = libxl_device_usbctrl_add(ctx, domid, &usbctrl, 0); 
> > +    if (rc) 
> > +        fprintf(stderr, "libxl_device_usbctrl_add failed.\n"); 
> > + 
> > +out: 
> > +    libxl_device_usbctrl_dispose(&usbctrl); 
> > +    return rc; 
> > +} 
> > + 
> > +int main_usbctrl_detach(int argc, char **argv) 
> > +{ 
> > +    uint32_t domid; 
> > +    int opt, devid, rc; 
> > +    libxl_device_usbctrl usbctrl; 
> > + 
> > +    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-ctrl-detach", 2) { 
> > +        /* No options */ 
> > +    } 
> > + 
> > +    domid = find_domain(argv[optind]); 
> > +    devid = atoi(argv[optind+1]); 
> > + 
> > +    libxl_device_usbctrl_init(&usbctrl); 
> > +    if (libxl_devid_to_device_usbctrl(ctx, domid, devid, &usbctrl)) { 
> > +        fprintf(stderr, "Unknown device %s.\n", argv[optind+1]); 
> > +        return 1; 
> > +    } 
> > + 
> > +    rc = libxl_device_usbctrl_remove(ctx, domid, &usbctrl, 0); 
> > +    if (rc) 
> > +        fprintf(stderr, "libxl_device_usbctrl_remove failed.\n"); 
> > + 
> > +    libxl_device_usbctrl_dispose(&usbctrl); 
> > +    return rc; 
> > + 
> > +} 
> > + 
> > +int main_usbattach(int argc, char **argv) 
> > +{ 
> > +    uint32_t domid; 
> > +    char *devname, *p; 
> > +    int opt, rc = 1; 
> > +    char *oparg; 
> > +    libxl_device_usb usb; 
> > + 
> > +    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-attach", 2) { 
> > +        /* No options */ 
> > +    } 
> > + 
> > +    libxl_device_usb_init(&usb); 
> > + 
> > +    domid = find_domain(argv[optind++]); 
> > +    devname = argv[optind++]; 
> > +    p = strchr(devname, '.'); 
> > +    if (p) { 
> > +        usb.u.hostdev.hostbus = strtoul(devname, NULL, 0); 
> > +        usb.u.hostdev.hostaddr = strtoul(p + 1, NULL, 0); 
> > +    } 
> > + 
> > +    if (usb.u.hostdev.hostbus < 1 || usb.u.hostdev.hostaddr < 1) { 
> > +        fprintf(stderr, "Invalid usb device.\n"); 
> > +        goto out; 
> > +    } 
> > + 
> > +    while (argc > optind) { 
> > +        if (MATCH_OPTION("controller", argv[optind], oparg)) { 
> > +            usb.ctrl = atoi(oparg); 
> > +        } else if (MATCH_OPTION("port", argv[optind], oparg)) { 
> > +            usb.port = atoi(oparg); 
> > +        } else { 
> > +            fprintf(stderr, "unrecognized argument `%s'\n", argv[optind]); 
> > +            goto out; 
> > +        } 
> > +        optind++; 
> > +    } 
> > + 
> > +    rc = libxl_device_usb_add(ctx, domid, &usb, 0); 
> > +    if (rc) 
> > +        fprintf(stderr, "libxl_device_usb_add failed.\n"); 
> > + 
> > +out: 
> > +    libxl_device_usb_dispose(&usb); 
> > +    return rc; 
> > +} 
> > + 
> > +int main_usbdetach(int argc, char **argv) 
> > +{ 
> > +    uint32_t domid; 
> > +    int ctrl, port; 
> > +    int opt, rc = 1; 
> > +    libxl_device_usb usb; 
> > + 
> > +    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-detach", 3) { 
> > +        /* No options */ 
> > +    } 
> > + 
> > +    domid = find_domain(argv[optind]); 
> > +    ctrl = atoi(argv[optind+1]); 
> > +    port = atoi(argv[optind+2]); 
> > + 
> > +    if (argc - optind > 3) { 
> > +        fprintf(stderr, "Invalid arguments.\n"); 
> > +        goto out; 
> > +    } 
> > + 
> > +    libxl_device_usb_init(&usb); 
> > +    if (libxl_ctrlport_to_device_usb(ctx, domid, ctrl, port, &usb)) { 
> > +        fprintf(stderr, "Unknown device at controller %d port %d.\n", 
> > +                ctrl, port); 
> > +        goto out; 
> > +    } 
> > + 
> > +    rc = libxl_device_usb_remove(ctx, domid, &usb, 0); 
> > +    if (rc) 
> > +        fprintf(stderr, "libxl_device_usb_remove failed.\n"); 
> > + 
> > +out: 
> > +    libxl_device_usb_dispose(&usb); 
> > +    return rc; 
> > +} 
> > + 
> > +int main_usblist(int argc, char **argv) 
> > +{ 
> > +    uint32_t domid; 
> > +    libxl_device_usbctrl *usbctrls; 
> > +    libxl_usbctrlinfo usbctrlinfo; 
> > +    int numctrl, i, j, opt; 
> > + 
> > +    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-list", 1) { 
> > +        /* No options */ 
> > +    } 
> > + 
> > +    domid = find_domain(argv[optind++]); 
> > + 
> > +    if (argc > optind) { 
> > +        fprintf(stderr, "Invalid arguments.\n"); 
> > +        exit(-1); 
> > +    } 
> > + 
> > +    usbctrls = libxl_device_usbctrl_list(ctx, domid, &numctrl); 
> > +    if (!usbctrls) { 
> > +        return 0; 
> > +    } 
> > + 
> > +    for (i = 0; i < numctrl; ++i) { 
> > +        printf("%-6s %-6s %-3s %-5s %-7s %-5s %-30s\n", 
> > +                "Devid", "Type", "BE", "state", "usb-ver", "ports",  
> "BE-path"); 
> > + 
> > +        libxl_usbctrlinfo_init(&usbctrlinfo); 
> > + 
> > +        if (!libxl_device_usbctrl_getinfo(ctx, domid, 
> > +                                &usbctrls[i], &usbctrlinfo)) { 
> > +            printf("%-6d %-6s %-3d %-5d %-7d %-5d %-30s\n", 
> > +                    usbctrlinfo.devid, 
> > +                    libxl_usbctrl_type_to_string(usbctrlinfo.type), 
> > +                    usbctrlinfo.backend_id, usbctrlinfo.state, 
> > +                    usbctrlinfo.version, usbctrlinfo.ports, 
> > +                    usbctrlinfo.backend); 
> > + 
> > +            for (j = 1; j <= usbctrlinfo.ports; j++) { 
> > +                libxl_device_usb usb; 
> > +                libxl_usbinfo usbinfo; 
> > + 
> > +                libxl_device_usb_init(&usb); 
> > +                libxl_usbinfo_init(&usbinfo); 
> > + 
> > +                printf("  Port %d:", j); 
> > + 
> > +                usb.ctrl = usbctrlinfo.devid; 
> > +                usb.port = j; 
> > +                if (!libxl_device_usb_getinfo(ctx, domid, &usb, &usbinfo)) { 
> > +                    printf(" Bus %03x Device %03x: ID %04x:%04x %s %s\n", 
> > +                            usbinfo.busnum, usbinfo.devnum, 
> > +                            usbinfo.idVendor, usbinfo.idProduct, 
> > +                            usbinfo.manuf ?: "", usbinfo.prod ?: ""); 
> > +                } else { 
> > +                    printf("\n"); 
> > +                } 
> > +                libxl_usbinfo_dispose(&usbinfo); 
> > +                libxl_device_usb_dispose(&usb); 
> > +            } 
> > +        } 
> > + 
> > +        libxl_usbctrlinfo_dispose(&usbctrlinfo); 
> > +    } 
> > + 
> > +    libxl_device_usbctrl_list_free(usbctrls, numctrl); 
> > +    return 0; 
> > +} 
> > + 
> >  int main_console(int argc, char **argv) 
> >  { 
> >      uint32_t domid; 
> > diff --git a/tools/libxl/xl_cmdtable.c b/tools/libxl/xl_cmdtable.c 
> > index 0071f12..46f276e 100644 
> > --- a/tools/libxl/xl_cmdtable.c 
> > +++ b/tools/libxl/xl_cmdtable.c 
> > @@ -551,6 +551,31 @@ struct cmd_spec cmd_table[] = { 
> >      }, 
> >   
> >  #endif 
> > +    { "usb-ctrl-attach", 
> > +      &main_usbctrl_attach, 0, 1, 
> > +      "Create a virtual USB controller for a domain", 
> > +      "<Domain> [type=pv] [version=<version>] [ports=<number>]", 
> > +    }, 
> > +    { "usb-ctrl-detach", 
> > +      &main_usbctrl_detach, 0, 1, 
> > +      "Remove the virtual USB controller specified by <DevId> for a domain", 
> > +      "<Domain> <DevId>", 
> > +    }, 
> > +    { "usb-attach", 
> > +      &main_usbattach, 0, 1, 
> > +      "Attach a USB device to a domain", 
> > +      "<Domain> <bus.addr> [controller=<DevId> [port=<port>]]", 
> > +    }, 
> > +    { "usb-detach", 
> > +      &main_usbdetach, 0, 1, 
> > +      "Detach a USB device from a domain", 
> > +      "<Domain> <controller> <port>", 
> > +    }, 
> > +    { "usb-list", 
> > +      &main_usblist, 0, 0, 
> > +      "List information about USB devices for a domain", 
> > +      "<Domain>", 
> > +    }, 
> >  }; 
> >   
> >  int cmdtable_len = sizeof(cmd_table)/sizeof(struct cmd_spec); 
> >  
>  
>  
>  

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 3/7] libxl: add pvusb API
  2015-09-30 17:55   ` George Dunlap
  2015-10-02 13:31     ` Ian Campbell
@ 2015-10-09  8:12     ` Chun Yan Liu
  2015-10-12  7:19     ` Chun Yan Liu
  2 siblings, 0 replies; 59+ messages in thread
From: Chun Yan Liu @ 2015-10-09  8:12 UTC (permalink / raw)
  To: George Dunlap, xen-devel
  Cc: Juergen Gross, wei.liu2, ian.campbell, george.dunlap,
	Ian.Jackson, Jim Fehlig, Simon Cao



>>> On 10/1/2015 at 01:55 AM, in message <560C2204.9030707@citrix.com>, George
Dunlap <george.dunlap@citrix.com> wrote: 
> On 25/09/15 03:11, Chunyan Liu wrote: 
> > Add pvusb APIs, including: 
> >  - attach/detach (create/destroy) virtual usb controller. 
> >  - attach/detach usb device 
> >  - list usb controllers and usb devices 
> >  - get information of usb controller and usb device 
> >  - some other helper functions 
> >  
> > Signed-off-by: Chunyan Liu <cyliu@suse.com> 
> > Signed-off-by: Simon Cao <caobosimon@gmail.com> 
>  
> Hey Chunyan!  This looks pretty close to being ready to check in to me. 
>  
> There are four basic comments I have.  I'm keen to get this series in so 
> that we can start doing more collaborative improvement; so I'll give my 
> comments, and then talk about timing and a plan to get this in as 
> quikcly as possible at the bottom. 
>  
>  
> > diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c 
> > index aea4887..1e2c63e 100644 
> > --- a/tools/libxl/libxl.c 
> > +++ b/tools/libxl/libxl.c 
> > @@ -4192,11 +4192,54 @@ DEFINE_DEVICE_REMOVE(vtpm, destroy, 1) 
> >   
> >   
> /**************************************************************************** 
> **/ 
> >   
> > +/* Macro for defining device remove/destroy functions for usbctrl */ 
> > +/* Following functions are defined: 
> > + * libxl_device_usbctrl_remove 
> > + * libxl_device_usbctrl_destroy 
> > + */ 
> > + 
> > +#define DEFINE_DEVICE_REMOVE_EXT(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 = LIBXL__DEVICE_ACTION_REMOVE;                    \ 
> > +        aodev->dev = device;                                            \ 
> > +        aodev->callback = device_addrm_aocomplete;                      \ 
> > +        aodev->force = f;                                               \ 
> > +        libxl__initiate_device_##type##_remove(egc, aodev);             \ 
>  
> So this seems to be exactly the same as DEFINE_DEVICE_REMOVE(), except 
> that you call libxl__initiate_device_usbctrl_remove() here rather than 
> libxl__initiate_device_remove(). 
>  
> It seems like it might be better to have a separate patch renaming 
> libxl__initiate_device_remove to libxl__initiate_device_generic_remove 
> (or something like that), and then add a parameter to the definition 
> above making it so that the definitions above pass in "generic". 
>  
> > diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c 
> > index bee5ed5..935f25b 100644 
> > --- a/tools/libxl/libxl_device.c 
> > +++ b/tools/libxl/libxl_device.c 
> > @@ -676,6 +676,10 @@ void libxl__devices_destroy(libxl__egc *egc,  
> libxl__devices_remove_state *drs) 
> >                  aodev->action = LIBXL__DEVICE_ACTION_REMOVE; 
> >                  aodev->dev = dev; 
> >                  aodev->force = drs->force; 
> > +                if (dev->backend_kind == LIBXL__DEVICE_KIND_VUSB) { 
> > +                    libxl__initiate_device_usbctrl_remove(egc, aodev); 
> > +                    continue; 
> > +                } 
> >                  libxl__initiate_device_remove(egc, aodev); 
>  
> I think this would probably be more clear if you did: 
>  
> if(dev->backend_kind == LIBXL__DEVICE_KIND_VUSB) 
>   libxl__initiate_device_usbctl_remove() 
> else 
>   libxl__initiate_device_remove() 
>  
> > @@ -3951,7 +3966,10 @@ static inline void  
> libxl__update_config_vtpm(libxl__gc *gc, 
> >  #define COMPARE_PCI(a, b) ((a)->func == (b)->func &&    \ 
> >                             (a)->bus == (b)->bus &&      \ 
> >                             (a)->dev == (b)->dev) 
> > - 
> > +#define COMPARE_USB(a, b) ((a)->u.hostdev.hostbus == (b)->u.hostdev.hostbus && \ 
> > +                           (a)->u.hostdev.hostaddr == (b)->u.hostdev.hostaddr) 
>  
> Hmm... COMPARE_USB is used in three places: 
>  
> 1. Used in libxl.c:libxl_retrieve_domain_configuration() to de-duplicate 
> JSON and xenstore configuration 
>  
> 2. Used in libxl_pvusb.c:libxl__device_usb_add_xentore() to avoid adding 
> the same device twice 
>  
> 3. Used in libxl_pvusb.c:is_usbdev_in_array() to avoid assigning the 
> same host device 
>  
> For #3, we pretty clearly want to be comparing hostbus/hostaddr.  (In 
> fact, you didn't use the COMPARE_USB macro until I suggested it in v3.) 
>  
> But for #1 and #2, is that what we want?  Should we be comparing 
> <ctrl,port> instead? 
>  
> In fact, after thinking about pvusb backends more, I think I want to 
> assert that we do want to compare <ctrl,port> instead: <crtl,port> is 
> guaranteed to be unique for a domain, but it's entirely possible to have 
> two different devices, from two different backend domains, with the same 
> bus.addr. 

Considering usb driver domain, <bus.addr> does have problem. I agree
it should compare <ctrl, port>, I'll update the MACRO.
For #3, I won't use COMAPRE_USB macro then but extend codes to compare
bus.addr directly.

>  
> > +int libxl_devid_to_device_usbctrl(libxl_ctx *ctx, 
> > +                                  uint32_t domid, 
> > +                                  int devid, 
> > +                                  libxl_device_usbctrl *usbctrl) 
> > +{ 
> > +    GC_INIT(ctx); 
> > +    libxl_device_usbctrl *usbctrls; 
> > +    int nb = 0; 
> > +    int i, rc = -1; 
> > + 
> > +    usbctrls = libxl_device_usbctrl_list(ctx, domid, &nb); 
> > +    if (!nb) goto out; 
> > + 
> > +    for (i = 0; i < nb; i++) { 
> > +        if (devid == usbctrls[i].devid) { 
> > +            *usbctrl = usbctrls[i]; 
>  
> libxl maintainers: Is this kind of copying OK? 
>  
> The analog functions for vtpm and nic both take very different 
> approaches; both call libxl_device_[type]_init() and then fill in 
> individual elements (albeit in different ways).

As Ian replied, it depends on the free time. To be strict, since
we have libxl_device_usbctrl_list_free() soon 
later, it is not OK. But since in libxl_device_usbctrl struct, except 
for backend_domname, all others are int type, since backend_domname 
won't be called in later work, so it won't be affected after 
libxl_device_usbctrl_list_freei. 
 
Anyway, I'll update to follow vtpm and nic ways to copy individule 
elements.

- Chunyan
~          
>  
> > +/* 
> > + * USB add 
> > + */ 
> > +static int do_usb_add(libxl__gc *gc, uint32_t domid, 
> > +                      libxl_device_usb *usbdev, 
> > +                      libxl__ao_device *aodev) 
> > +{ 
> > +    libxl_ctx *ctx = CTX; 
> > +    libxl_usbctrlinfo usbctrlinfo; 
> > +    libxl_device_usbctrl usbctrl; 
> > +    int rc; 
> > + 
> > +    libxl_usbctrlinfo_init(&usbctrlinfo); 
> > +    usbctrl.devid = usbdev->ctrl; 
> > +    rc = libxl_device_usbctrl_getinfo(ctx, domid, &usbctrl, &usbctrlinfo); 
> > +    if (rc) 
> > +        goto out; 
> > + 
> > +    switch (usbctrlinfo.type) { 
> > +    case LIBXL_USBCTRL_TYPE_DEVICEMODEL: 
> > +        LOG(ERROR, "Not supported"); 
> > +        break; 
> > +    case LIBXL_USBCTRL_TYPE_PV: 
> > +        rc = libxl__device_usb_add_xenstore(gc, domid, usbdev, 
> > +                                            aodev->update_json); 
> > +        if (rc) goto out; 
> > + 
> > +        rc = usbback_dev_assign(gc, usbdev); 
>  
> This assumes that the usb controller is dom0; but the interface 
> explicitly allows pvusb driver domains. 
>  
> I think it would be enough here to do this check if the usbctrl device 
> is dom0.  We should then assume that a pvusb driver domain will be 
> configured with all usb devices assigned to usbback already. 
>  
> I assume that there's a feedback mechanisms for backends for situations 
> where the requested device can't be made, right?  For example, if you 
> have a network driver domain and request a non-existent bridge?  If so, 
> I think we can let the same mechanism worth for pvusb backends to say "I 
> don't have that device available". 
>  
> > +        if (rc) { 
> > +            libxl__device_usb_remove_xenstore(gc, domid, usbdev); 
> > +            goto out; 
> > +        } 
> > +        break; 
> > +    default: 
> > +        rc = ERROR_FAIL; 
> > +        goto out; 
> > +    } 
> > + 
> > +out: 
> > +    libxl_usbctrlinfo_dispose(&usbctrlinfo); 
> > +    return rc; 
> > +} 
> > + 
> > +/* AO operation to add a usb device. 
> > + * 
> > + * Generally, it does: 
> > + * 1) check if the usb device type is assignable 
> > + * 2) check if the usb device is already assigned to a domain 
> > + * 3) add 'busid' of the usb device to xenstore contoller/port/. 
> > + *    (PVUSB driver watches the xenstore changes and will detect that.) 
> > + * 4) unbind usb device from original driver and bind to usbback. 
> > + *    If usb device has many interfaces, then: 
> > + *    - unbind each interface from its original driver and bind to usbback. 
> > + *    - store the original driver to xenstore for later rebinding when 
> > + *      detaching the device. 
> > + */ 
> > +void libxl__device_usb_add(libxl__egc *egc, uint32_t domid, 
> > +                           libxl_device_usb *usb, 
> > +                           libxl__ao_device *aodev) 
> > +{ 
> > +    STATE_AO_GC(aodev->ao); 
> > +    int rc = ERROR_FAIL; 
> > +    char *busid = NULL; 
> > +    libxl_device_usb *assigned; 
> > +    int num_assigned; 
> > + 
> > +    assert(usb->u.hostdev.hostbus > 0 && usb->u.hostdev.hostaddr > 0); 
> > + 
> > +    busid = usb_busaddr_to_busid(gc, usb->u.hostdev.hostbus, 
> > +                                 usb->u.hostdev.hostaddr); 
> > +    if (!busid) { 
> > +        LOG(ERROR, "USB device doesn't exist in sysfs"); 
> > +        goto out; 
> > +    } 
> > + 
> > +    if (!is_usb_assignable(gc, usb)) { 
> > +        LOG(ERROR, "USB device is not assignable."); 
> > +        goto out; 
> > +    } 
>  
> Similar issue with pvusb driver domains: we can't do this check for 
> driver domains. 
>  
> I wonder if we should do this check instead down on the 
> usbback_assign_path(). 
>  
> If we assume that for pvusb driver domains: 
> 1. All assignable devices will be assigned to usbback 
> 2. No controllers will be assigned (since they can't be) 
> 3. pvusb can say "no such device" for unassigned devices 
> then we can safely ignore the check for pvusb driver domains 
>  
> > + 
> > +    /* check usb device is already assigned */ 
> > +    rc = get_assigned_devices(gc, &assigned, &num_assigned); 
> > +    if (rc) { 
> > +        LOG(ERROR, "cannot determine if device is assigned," 
> > +                   " refusing to continue"); 
> > +        goto out; 
> > +    } 
> > + 
> > +    if (is_usbdev_in_array(assigned, num_assigned, usb)) { 
> > +        LOG(ERROR, "USB device already attached to a domain"); 
> > +        rc = ERROR_FAIL; 
> > +        goto out; 
> > +    } 
>  
> WRT driver domains: Since we're looking inside xenstore instead of 
> sysfs, we *can* actually do these checks. 
>  
> However, the "bus.addr" space is defined by the driver domain kernel, 
> and is not unique across all driver domains: If we have one usb 
> controller assigned to domain 0, and another assigned to a driver 
> domain, two distinct devices are likely to end up with the same bus.addr. 
>  
> So to be compatible with driver domains, we'd need to have 
> get_assigned_devices() only get devices with the same backend_domid as 
> the controller we're checking. 
>  
> > +int libxl_device_usb_getinfo(libxl_ctx *ctx, uint32_t domid, 
> > +                             libxl_device_usb *usb, 
> > +                             libxl_usbinfo *usbinfo) 
> > +{ 
> > +    GC_INIT(ctx); 
> > +    char *filename; 
> > +    char *busid; 
> > +    void *buf = NULL; 
> > +    int buflen, rc; 
> > + 
> > +    usbinfo->ctrl = usb->ctrl; 
> > +    usbinfo->port = usb->port; 
> > + 
> > +    if (libxl_ctrlport_to_device_usb(ctx, domid, 
> > +                                     usb->ctrl, usb->port, usb) < 0) { 
> > +        rc = ERROR_FAIL; 
> > +        goto out; 
> > +    } 
>  
> I suppose technically since usb isn't declared const that we haven't 
> promised to modify it; but none of the other device_*_getinfo() 
> functions modify the device struct; I think it would be better to follow 
> suit and use a local variable to get the information from. 
>  
> However... 
>  
> > + 
> > +    usbinfo->devnum = usb->u.hostdev.hostaddr; 
> > +    usbinfo->busnum = usb->u.hostdev.hostbus; 
> > + 
> > +    busid = usb_busaddr_to_busid(gc, usb->u.hostdev.hostbus, 
> > +                                 usb->u.hostdev.hostaddr); 
> > +    if (!busid) { 
> > +        rc = ERROR_FAIL; 
> > +        goto out; 
> > +    } 
> > + 
> > +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idVendor", busid); 
> > +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL)) 
> > +        sscanf(buf, "%" SCNx16, &usbinfo->idVendor); 
> > + 
> > +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idProduct", busid); 
> > +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL)) 
> > +        sscanf(buf, "%" SCNx16, &usbinfo->idProduct); 
> > + 
> > +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/manufacturer", busid); 
> > +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, &buflen) && 
> > +        buflen > 0) { 
> > +        /* replace \n to \0 */ 
> > +        if (((char *)buf)[buflen - 1] == '\n') 
> > +            ((char *)buf)[buflen - 1] = '\0'; 
> > +        usbinfo->manuf = libxl__strdup(NOGC, buf); 
> > +   } 
> > + 
> > +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/product", busid); 
> > +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, &buflen) && 
> > +        buflen > 0) { 
> > +        /* replace \n to \0 */ 
> > +        if (((char *)buf)[buflen - 1] == '\n') 
> > +            ((char *)buf)[buflen - 1] = '\0'; 
> > +        usbinfo->prod = libxl__strdup(NOGC, buf); 
> > +    } 
>  
> Basically, starting here, we have information which won't be available 
> if we're using a pvusb driver domain. 
>  
> This information is nice-to-have, but I don't think this information is 
> directly relevant to libxl or xl; the funcitonality to get this 
> information is available from other libraries like libusb.  I'm inclined 
> to say that if we want to have pvusb driver domains (and I think we do), 
> we should just get rid of this information. 
>  
> > diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl 
> > index 9f6ec00..4844f18 100644 
> > --- a/tools/libxl/libxl_types.idl 
> > +++ b/tools/libxl/libxl_types.idl 
> > @@ -595,6 +595,35 @@ libxl_device_rdm = Struct("device_rdm", [ 
> >      ("policy", libxl_rdm_reserve_policy), 
> >      ]) 
> >   
> > +libxl_usbctrl_type = Enumeration("usbctrl_type", [ 
> > +    (0, "AUTO"), 
> > +    (1, "PV"), 
> > +    (2, "DEVICEMODEL"), 
> > +    ]) 
> > + 
> > +libxl_usbdev_type = Enumeration("usbdev_type", [ 
> > +    (1, "hostdev"), 
> > +    ]) 
> > + 
> > +libxl_device_usbctrl = Struct("device_usbctrl", [ 
> > +    ("type", libxl_usbctrl_type), 
> > +    ("devid", libxl_devid), 
> > +    ("version", integer), 
> > +    ("ports", integer), 
> > +    ("backend_domid", libxl_domid), 
> > +    ("backend_domname", string), 
> > +   ]) 
> > + 
> > +libxl_device_usb = Struct("device_usb", [ 
> > +    ("ctrl", libxl_devid), 
> > +    ("port", integer), 
> > +    ("u", KeyedUnion(None, libxl_usbdev_type, "devtype", 
> > +           [("hostdev", Struct(None, [ 
> > +                 ("hostbus",   uint8), 
> > +                 ("hostaddr",  uint8)])), 
> > +           ])), 
> > +    ]) 
> > + 
> >  libxl_device_dtdev = Struct("device_dtdev", [ 
> >      ("path", string), 
> >      ]) 
> > @@ -627,6 +656,8 @@ libxl_domain_config = Struct("domain_config", [ 
> >      ("pcidevs", Array(libxl_device_pci, "num_pcidevs")), 
> >      ("rdms", Array(libxl_device_rdm, "num_rdms")), 
> >      ("dtdevs", Array(libxl_device_dtdev, "num_dtdevs")), 
> > +    ("usbctrls", Array(libxl_device_usbctrl, "num_usbctrls")), 
> > +    ("usbs", Array(libxl_device_usb, "num_usbs")), 
> >      ("vfbs", Array(libxl_device_vfb, "num_vfbs")), 
> >      ("vkbs", Array(libxl_device_vkb, "num_vkbs")), 
> >      ("vtpms", Array(libxl_device_vtpm, "num_vtpms")), 
> > @@ -676,6 +707,32 @@ libxl_vtpminfo = Struct("vtpminfo", [ 
> >      ("uuid", libxl_uuid), 
> >      ], dir=DIR_OUT) 
> >   
> > +libxl_usbctrlinfo = Struct("usbctrlinfo", [ 
> > +    ("type", libxl_usbctrl_type), 
> > +    ("devid", libxl_devid), 
> > +    ("version", integer), 
> > +    ("ports", integer), 
> > +    ("backend", string), 
> > +    ("backend_id", uint32), 
> > +    ("frontend", string), 
> > +    ("frontend_id", uint32), 
> > +    ("state", integer), 
> > +    ("evtch", integer), 
> > +    ("ref_urb", integer), 
> > +    ("ref_conn", integer), 
> > +    ], dir=DIR_OUT) 
> > + 
> > +libxl_usbinfo = Struct("usbinfo", [ 
> > +    ("ctrl", libxl_devid), 
> > +    ("port", integer), 
> > +    ("busnum", uint8), 
> > +    ("devnum", uint8), 
> > +    ("idVendor", uint16), 
> > +    ("idProduct", uint16), 
> > +    ("prod", string), 
> > +    ("manuf", string), 
> > +    ], dir=DIR_OUT) 
>  
> With the exception of the stuff in libxl_usbinfo we can't get if the 
> backend isn't dom0, the interface looks good to me now. 
>  
> OK, so I've covered four things: 
>  
> 1. The DEFINE_DEVICE_REMOVE_EXT macro.  I think I'd prefer checking in 
> things are as it is, and then have a follow-up patch to refactor 
> everything into a single DEFINE_DEVICE_REMOVE macro as described above. 
>  
> 2. COMPARE_USB.  I think this needs to be fixed; but this should be a 
> fairly simple change. 
>  
> 3. The conditional in libxl__device_destroy, the struct copy in 
> libxl_devid_to_device_usbctrl, and the modification of the device in 
> libxl_device_usb_getinfo are minor adjustments that can be discussed and 
> fixed. 
>  
> 4. The pvusb driver domain != dom0 comments.  This is somewhat secondary 
> to your primary goal; but at the moment the code will certainly not 
> work.  We have a couple of options: 
> a: Wait until we've fixed the driver domain functionality 
> b: Check the code in right now, with the driver domain fuctionality 
> explicitly disabled; that is, it will return an error if 
> backend_domain!=0.  Get a promise to implement the driver domain 
> functionality properly for 4.7 (on the threat of removing the feature). 
> c: Take driver domain support out of the interface for now; send 
> follow-up patches to implement it properly. 
> d. Take driver domain support out of the interface and leave it that 
> way, for simplicity. 
>  
> I'd probably go with b or c. 
>  
> Thoughts? 
>  
>  -George 
>  
>  

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 3/7] libxl: add pvusb API
  2015-10-08 14:41   ` Ian Jackson
  2015-10-08 14:54     ` Ian Campbell
@ 2015-10-12  7:00     ` Chun Yan Liu
  1 sibling, 0 replies; 59+ messages in thread
From: Chun Yan Liu @ 2015-10-12  7:00 UTC (permalink / raw)
  To: Ian Jackson
  Cc: Juergen Gross, wei.liu2, ian.campbell, george.dunlap, xen-devel,
	Jim Fehlig, Simon Cao



>>> On 10/8/2015 at 10:41 PM, in message
<22038.32910.375958.407732@mariner.uk.xensource.com>, Ian Jackson
<Ian.Jackson@eu.citrix.com> wrote: 
> Chunyan Liu writes ("[PATCH V7 3/7] libxl: add pvusb API"): 
> > Add pvusb APIs, including: 
> ... 
>  
> > +/* Utility to read backend xenstore keys */ 
> > +#define READ_BACKEND(tgc, subpath)                                    \ 
> > +            libxl__xs_read(tgc, XBT_NULL, GCSPRINTF("%s/" subpath,  
> be_path)) 
> > + 
> > +/* Utility to read frontend xenstore keys */ 
> > +#define READ_FRONTEND(tgc, subpath)                                   \ 
> > +            libxl__xs_read(tgc, XBT_NULL, GCSPRINTF("%s/" subpath,  
> fe_path)) 
> > + 
>  
> Thanks for trying to reduce repetition.  But I think these macros need 
> to be improved.  I'm am not particularly keen on them in this form, 
> for a number of reasons. 
>  
>  * They implicitly rely on variables (be_path and fe_path) being in 
>    scope but there is no associated doc comment.  That would be OK if 
>    they were macros defined within a single function and #undef'd 
>    before the function end. 
>  
>  * Their functionality is not really usb-specific.  If this is a good 
>    thing to do they should be in libxl_internal.h. 
>  
>  * They should use libxl__xs_read_checked.  That means they should 
>    probably also implicitly assume that rc is in scope, and `goto out' 
>    on error.  (There are many calls to libxl__xs_read here to which 
>    the same observation applies.) 
>  
>  * I think there is no reason for these to take a `tgc' parameter. 
>    All of the call sites pass exactly `gc'.  If these macros are going 
>    to make assumptions about what's in their scope, `gc' is a very 
>    good candidate (which many existing macros rely on). 
>  
> You can go two routes with this: make much more local macros, and 
> #undef them.  Or formalise these macros and widen their scope to the 
> whole of libxl.  I think the latter would probably be best. 

Sorry for replying late, the mail server were exchanged and had some
issues these days.

For the macro, I think maybe it's better to use local macros within function.
The macro itself doesn't do much work but a libxl__xs_read. Local macro
can have more flexibility, like can adding extra 'goto out' or error handling
or other repeated codes to the macro according to specific function.

> 
>
> Perhaps something like: 
>  
> /* 
>  * const char *READ_SUBPATH(const char *febe_path, const char *subpath); 
>  * 
>  * Expects in scope: 
>  *    int rc; 
>  *    libxl__gc *gc; 
>  *    out: 
>  * 
>  * Reads febe_path/subpath from xenstore.  Does not use a transaction. 
>  * On xenstore errors, sets rc and does `goto out'. 
>  * If the path does not exist, returns NULL. 
>  */ 
> #define READ_SUBPATH(febe_path, subpath) ... 
>  
> What do you think ? 
>  
>  
> > +/* AO operation to add a usb controller. 
> > + * 
> > + * Generally, it does: 
> > + * 1) fill in necessary usb controler information with default value 
> > + * 2) write usb controller frontend/backend info to xenstore, update json 
> > + *    config file if necessary. 
> > + * 3) wait for device connection. PVUSB frontend and backend driver will 
> > + *    probe xenstore paths and build connection between frontend and  i
> backend. 
> > + */ 
> > +void libxl__device_usbctrl_add(libxl__egc *egc, uint32_t domid, 
> > +                               libxl_device_usbctrl *usbctrl, 
> > +                               libxl__ao_device *aodev) 
> > +{ 
> > +    STATE_AO_GC(aodev->ao); 
> > +    libxl__device *device; 
> > +    int rc; 
> > + 
> > +    rc = libxl__device_usbctrl_setdefault(gc, domid, usbctrl); 
> > +    if (rc < 0) goto out; 
> > + 
> > +    if (usbctrl->devid == -1) { 
> > +        usbctrl->devid = libxl__device_nextid(gc, domid, "vusb"); 
> > +        if (usbctrl->devid < 0) { 
> > +            rc = ERROR_FAIL; 
> > +            goto out; 
> > +        } 
> > +    } 
> > + 
> > +    if (usbctrl->type != LIBXL_USBCTRL_TYPE_PV) { 
> > +        LOG(ERROR, "Unsupported USB controller type"); 
> > +        rc = ERROR_FAIL; 
> > +        goto out; 
> > +    } 
> > + 
> > +    rc = libxl__device_usbctrl_add_xenstore(gc, domid, usbctrl, 
> > +                                            aodev->update_json); 
> > +    if (rc) goto out; 
> > + 
> > +    GCNEW(device); 
> > +    rc = libxl__device_from_usbctrl(gc, domid, usbctrl, device); 
> > +    if (rc) goto out; 
> > + 
> > +    aodev->dev = device; 
> > +    aodev->action = LIBXL__DEVICE_ACTION_ADD; 
> > +    libxl__wait_device_connection(egc, aodev); 
> > +    rc = 0; 
> > + 
> > +out: 
> > +    aodev->rc = rc; 
> > +    if (rc) aodev->callback(egc, aodev); 
>  
> This is wrong (even though it works with the remaining code as it 
> stands), I'm afraid. 
>  
> The right pattern is to `return 0' after 
> libxl__wait_device_connection, because libxl__wait_device_connection 
> will always make a callback.

It's OK to 'return 0' directly fater libxl__wait_device_connection since we don't
need to do cleanup work. Here the code follows the code format of
libxl__device_disk_add and libxl__device_nic_add, I think it doesn't harm.
 
>  
> Also the doc comment for this function should make it clear which of 
> the fields in aodev must be filled in by the caller.  After you do 
> that you should make sure that the call site obeys the rules.  (This 
> is not something I have checked right now because the rules aren't 
> stated.) 

The libxl__device_usbctrl_add follows the same rule as libxl__device_disk_add
and libxl__device_nic_add, call sites including DEFINE_DEVICE_ADD(usbctrl) and
domcreate time also follow the same rule as disk type and nic type. Do we need
to add doc comment to the parameters of this API separately?

>  
> Both of these observations apply to the remove path as well. 
>  
> > +/* AO function to remove a usb controller. 
> > + * 
> > + * Generally, it does: 
> > + * 1) check if the usb controller exists or not 
> > + * 2) remove all usb devices under controller 
> > + * 3) remove usb controller information from xenstore 
> > + */ 
> > +void libxl__initiate_device_usbctrl_remove(libxl__egc *egc, 
> > +                                           libxl__ao_device *aodev) 
>  
> What happens if this functionality is running to try to remove the 
> controller, at the same time as another process is trying to remove a 
> device from the controller, or (worse) add a device to the 
> controller ?  Obviously I don't expect 100% successful outcomes, but I 
> want to know that the severity of the consequences is limited.

I'm not quite clear about the whole lock mechanism in libxl code. But I think
here the risk is perhaps similar to one process doing domain destroy and at
the same time another process is trying to add a disk device. I didn't add extra
lock in the usbctrl add/remove and usb add/remove (should we??).

So, when one process removing usbctrl, another process is trying to add a device,
one case could be: the latter would fail to write xenstore if the former process
already removes xenstore entries and then report fail, but the former process
could succeed.
or could be: the latter process succeeds to write xenstore and assign usb device
to usbback and report success, but actually user cannot see the device, since
former process will remove everything under the controller soon.

For one process removing usbctrl, another removing usb device, it could be:
the latter one found the usb device doesn't exist any more and report error, but
the former one can succeed. or: the former one lists usb devices under the controller,
and trying to remove one by one; during that process, the latter removes some
usb device; then the former process will fail to remove that usb device again, and
then will report error.
 
>  
> > +libxl_device_usbctrl * 
> > +libxl_device_usbctrl_list(libxl_ctx *ctx, uint32_t domid, int *num) 
> > +{ 
>  
> This function should return an rc, and the list should come in an out 
> is not something I have checked right now because the rules aren't 
> stated.)  
>  
> > +    dir = libxl__xs_directory(gc, XBT_NULL, path, &ndirs); 
>  
> The variables `dir' and `ndirs' should be `entry' and `nentries'. 
>  
> > +    if (dir && ndirs) { 
> > +        usbctrls = libxl__zalloc(NOGC, sizeof(*usbctrls) * ndirs); 
> > +        libxl_device_usbctrl *usbctrl; 
> > +        libxl_device_usbctrl *end = usbctrls + ndirs; 
> > +        for (usbctrl = usbctrls; usbctrl < end; usbctrl++, dir++, (*num)++)  
> { 
>  
> This line would be better wrapped at the semicolons, IMO. 
>  
> > +            const char *tmp, *be_path; 
> > +            const char *fe_path = GCSPRINTF("%s/%s", path, *dir); 
> > + 
> > +            libxl_device_usbctrl_init(usbctrl); 
> > +            usbctrl->devid = atoi(*dir); 
> > + 
> > +            tmp = READ_FRONTEND(gc, "backend-id"); 
> > +            if (!tmp) goto outerr; 
> > +            usbctrl->backend_domid = atoi(tmp); 
> > + 
> > +            tmp = READ_BACKEND(gc, "usb-ver"); 
> > +            if (!tmp) goto outerr; 
> > +            usbctrl->version = atoi(tmp); 
> > + 
> > +            tmp = READ_BACKEND(gc, "num-ports"); 
> > +            if (!tmp) goto outerr; 
> > +            usbctrl->ports = atoi(tmp); 
>  
> There are 4 nearly identical stanzas here.  I think a more 
> comprehensive would be helpful.  Maybe a global macro READ_SUBPATH_INT 
> along the lines of my READ_SUBPATH, above, would be useful, and then: 

Defining local macro within function may be better, can include more repeated codes
into the macro according to need.

>  
>                usbctrl->ports = READ_SUBPATH_INT(be_path, "num-ports"); 
>  
> and there would be no need for any open-coded error handling. 
>  
> > +int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid, 
> > +                                libxl_device_usbctrl *usbctrl, 
> > +                                libxl_usbctrlinfo *usbctrlinfo) 
> ... 
> > +    tmp = READ_FRONTEND(gc, "backend-id"); 
> > +    usbctrlinfo->backend_id = tmp ? strtoul(tmp, NULL, 10) : -1; 
>  
> Under what circumstances can these be validly missing ?  I'm not very 
> happy with the idea of filling in the struct with -1.

In theory that should not happen.
 
>  
> > +int libxl_devid_to_device_usbctrl(libxl_ctx *ctx, 
> > +                                  uint32_t domid, 
> > +                                  int devid, 
> > +                                  libxl_device_usbctrl *usbctrl) 
> > +{ 
> > +    GC_INIT(ctx); 
> > +    libxl_device_usbctrl *usbctrls; 
> > +    int nb = 0; 
> > +    int i, rc = -1; 
>  
> Initialising rc like this is a bad idea.  Instead, it should be set 
> explicitly on each error path.

OK. Take it.
 
> That alllows the compiler to spot 
> error paths that do not set rc.  Also rc=-1 is not permitted because 
> rc ought to be a libxl error code.  You probably want ERROR_NOTFOUND. 
>  
> > +static char *usb_busaddr_to_busid(libxl__gc *gc, int bus, int addr) 
> > +{ 
> > +        filename = GCSPRINTF(SYSFS_USB_DEV"/%s/devnum", de->d_name); 
> > +        if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL)) 
> > +            sscanf(buf, "%d", &devnum); 
>  
> If the file contents are invalid, devnum will be left uninitialised. 
> Why using sscanf rather than atoi (if you don't want to check for 
> unexpected data) or strtoul (if you do) ?  (Same thing later in 
> usb_busaddr_from_busid.) 

No special reason, just to keep consistent to use the same code
everywhere getting sysfs info.

>
> > +        if (bus == busnum && addr == devnum) { 
> > +            busid = libxl__strdup(NOGC, de->d_name); 
> > +            break; 
>  
> This allocates non-gc'd memory but (a) this is not documented contrary 
> to the rules in libxl_internal.h and (b) some of its callers do not 
> want non-gc'd memory. 

I'll have a look and add document if really need non-gc'd memory.

- Chunyan

>  
> > +static void usb_busaddr_from_busid(libxl__gc *gc, char *busid, 
> > +                                   uint8_t *bus, uint8_t *addr) 
>  
> Lack of const-correctness: busid should be const char *. 
>  
> > +    assert(busid); 
>  
> This is not necessary.  Please drop it.  If it's NULL, we'll crash in 
> snprintf soon enough. 
>  
>  
> I think that many of my comments can be generalised to the rest of 
> this patch.  I think it would be better for me to stop reading now and 
> await a new version.  (I'm finding it difficult to see the overall 
> structure of the code, and to remember the things I'm trying to look 
> out for along with the things I'm trying to disregard because I have 
> already mentioned them.) 
>  
> Specifically, can you please make sure to take every one of my 
> comments above, and treat it as relevant everywhere that it (or an 
> analagous comment) is applicable in your code. 
>  
> Thanks, 
> Ian. 
>  
>  

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 3/7] libxl: add pvusb API
  2015-09-30 17:55   ` George Dunlap
  2015-10-02 13:31     ` Ian Campbell
  2015-10-09  8:12     ` Chun Yan Liu
@ 2015-10-12  7:19     ` Chun Yan Liu
  2015-10-12 13:46       ` George Dunlap
  2 siblings, 1 reply; 59+ messages in thread
From: Chun Yan Liu @ 2015-10-12  7:19 UTC (permalink / raw)
  To: George Dunlap, xen-devel
  Cc: Juergen Gross, wei.liu2, ian.campbell, george.dunlap,
	Ian.Jackson, Jim Fehlig, Simon Cao



>>> On 10/1/2015 at 01:55 AM, in message <560C2204.9030707@citrix.com>, George
Dunlap <george.dunlap@citrix.com> wrote: 
> On 25/09/15 03:11, Chunyan Liu wrote: 
> > Add pvusb APIs, including: 
> >  - attach/detach (create/destroy) virtual usb controller. 
> >  - attach/detach usb device 
> >  - list usb controllers and usb devices 
> >  - get information of usb controller and usb device 
> >  - some other helper functions 
> >  
> > Signed-off-by: Chunyan Liu <cyliu@suse.com> 
> > Signed-off-by: Simon Cao <caobosimon@gmail.com> 
>  
> Hey Chunyan!  This looks pretty close to being ready to check in to me. 
>  
> There are four basic comments I have.  I'm keen to get this series in so 
> that we can start doing more collaborative improvement; so I'll give my 
> comments, and then talk about timing and a plan to get this in as 
> quikcly as possible at the bottom. 
>  
>  
> > diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c 
> > index aea4887..1e2c63e 100644 
> > --- a/tools/libxl/libxl.c 
> > +++ b/tools/libxl/libxl.c 
> > @@ -4192,11 +4192,54 @@ DEFINE_DEVICE_REMOVE(vtpm, destroy, 1) 
> >   
> >   
> /**************************************************************************** 
> **/ 
> >   
> > +/* Macro for defining device remove/destroy functions for usbctrl */ 
> > +/* Following functions are defined: 
> > + * libxl_device_usbctrl_remove 
> > + * libxl_device_usbctrl_destroy 
> > + */ 
> > + 
> > +#define DEFINE_DEVICE_REMOVE_EXT(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 = LIBXL__DEVICE_ACTION_REMOVE;                    \ 
> > +        aodev->dev = device;                                            \ 
> > +        aodev->callback = device_addrm_aocomplete;                      \ 
> > +        aodev->force = f;                                               \ 
> > +        libxl__initiate_device_##type##_remove(egc, aodev);             \ 
>  
> So this seems to be exactly the same as DEFINE_DEVICE_REMOVE(), except 
> that you call libxl__initiate_device_usbctrl_remove() here rather than 
> libxl__initiate_device_remove(). 
>  
> It seems like it might be better to have a separate patch renaming 
> libxl__initiate_device_remove to libxl__initiate_device_generic_remove 
> (or something like that), and then add a parameter to the definition 
> above making it so that the definitions above pass in "generic". 
>  
> > diff --git a/tools/libxl/libxl_device.c b/tools/libxl/libxl_device.c 
> > index bee5ed5..935f25b 100644 
> > --- a/tools/libxl/libxl_device.c 
> > +++ b/tools/libxl/libxl_device.c 
> > @@ -676,6 +676,10 @@ void libxl__devices_destroy(libxl__egc *egc,  
> libxl__devices_remove_state *drs) 
> >                  aodev->action = LIBXL__DEVICE_ACTION_REMOVE; 
> >                  aodev->dev = dev; 
> >                  aodev->force = drs->force; 
> > +                if (dev->backend_kind == LIBXL__DEVICE_KIND_VUSB) { 
> > +                    libxl__initiate_device_usbctrl_remove(egc, aodev); 
> > +                    continue; 
> > +                } 
> >                  libxl__initiate_device_remove(egc, aodev); 
>  
> I think this would probably be more clear if you did: 
>  
> if(dev->backend_kind == LIBXL__DEVICE_KIND_VUSB) 
>   libxl__initiate_device_usbctl_remove() 
> else 
>   libxl__initiate_device_remove() 
>  
> > @@ -3951,7 +3966,10 @@ static inline void  
> libxl__update_config_vtpm(libxl__gc *gc, 
> >  #define COMPARE_PCI(a, b) ((a)->func == (b)->func &&    \ 
> >                             (a)->bus == (b)->bus &&      \ 
> >                             (a)->dev == (b)->dev) 
> > - 
> > +#define COMPARE_USB(a, b) ((a)->u.hostdev.hostbus == (b)->u.hostdev.hostbus && \ 
> > +                           (a)->u.hostdev.hostaddr == (b)->u.hostdev.hostaddr) 
>  
> Hmm... COMPARE_USB is used in three places: 
>  
> 1. Used in libxl.c:libxl_retrieve_domain_configuration() to de-duplicate 
> JSON and xenstore configuration 
>  
> 2. Used in libxl_pvusb.c:libxl__device_usb_add_xentore() to avoid adding 
> the same device twice 
>  
> 3. Used in libxl_pvusb.c:is_usbdev_in_array() to avoid assigning the 
> same host device 
>  
> For #3, we pretty clearly want to be comparing hostbus/hostaddr.  (In 
> fact, you didn't use the COMPARE_USB macro until I suggested it in v3.) 
>  
> But for #1 and #2, is that what we want?  Should we be comparing 
> <ctrl,port> instead? 
>  
> In fact, after thinking about pvusb backends more, I think I want to 
> assert that we do want to compare <ctrl,port> instead: <crtl,port> is 
> guaranteed to be unique for a domain, but it's entirely possible to have 
> two different devices, from two different backend domains, with the same 
> bus.addr. 
>  
> > +int libxl_devid_to_device_usbctrl(libxl_ctx *ctx, 
> > +                                  uint32_t domid, 
> > +                                  int devid, 
> > +                                  libxl_device_usbctrl *usbctrl) 
> > +{ 
> > +    GC_INIT(ctx); 
> > +    libxl_device_usbctrl *usbctrls; 
> > +    int nb = 0; 
> > +    int i, rc = -1; 
> > + 
> > +    usbctrls = libxl_device_usbctrl_list(ctx, domid, &nb); 
> > +    if (!nb) goto out; 
> > + 
> > +    for (i = 0; i < nb; i++) { 
> > +        if (devid == usbctrls[i].devid) { 
> > +            *usbctrl = usbctrls[i]; 
>  
> libxl maintainers: Is this kind of copying OK? 
>  
> The analog functions for vtpm and nic both take very different 
> approaches; both call libxl_device_[type]_init() and then fill in 
> individual elements (albeit in different ways). 
>  
> > +/* 
> > + * USB add 
> > + */ 
> > +static int do_usb_add(libxl__gc *gc, uint32_t domid, 
> > +                      libxl_device_usb *usbdev, 
> > +                      libxl__ao_device *aodev) 
> > +{ 
> > +    libxl_ctx *ctx = CTX; 
> > +    libxl_usbctrlinfo usbctrlinfo; 
> > +    libxl_device_usbctrl usbctrl; 
> > +    int rc; 
> > + 
> > +    libxl_usbctrlinfo_init(&usbctrlinfo); 
> > +    usbctrl.devid = usbdev->ctrl; 
> > +    rc = libxl_device_usbctrl_getinfo(ctx, domid, &usbctrl, &usbctrlinfo); 
> > +    if (rc) 
> > +        goto out; 
> > + 
> > +    switch (usbctrlinfo.type) { 
> > +    case LIBXL_USBCTRL_TYPE_DEVICEMODEL: 
> > +        LOG(ERROR, "Not supported"); 
> > +        break; 
> > +    case LIBXL_USBCTRL_TYPE_PV: 
> > +        rc = libxl__device_usb_add_xenstore(gc, domid, usbdev, 
> > +                                            aodev->update_json); 
> > +        if (rc) goto out; 
> > + 
> > +        rc = usbback_dev_assign(gc, usbdev); 
>  
> This assumes that the usb controller is dom0; but the interface 
> explicitly allows pvusb driver domains. 
>  
> I think it would be enough here to do this check if the usbctrl device 
> is dom0.  We should then assume that a pvusb driver domain will be 
> configured with all usb devices assigned to usbback already. 
>  
> I assume that there's a feedback mechanisms for backends for situations 
> where the requested device can't be made, right?  For example, if you 
> have a network driver domain and request a non-existent bridge?  If so, 
> I think we can let the same mechanism worth for pvusb backends to say "I 
> don't have that device available". 
>  
> > +        if (rc) { 
> > +            libxl__device_usb_remove_xenstore(gc, domid, usbdev); 
> > +            goto out; 
> > +        } 
> > +        break; 
> > +    default: 
> > +        rc = ERROR_FAIL; 
> > +        goto out; 
> > +    } 
> > + 
> > +out: 
> > +    libxl_usbctrlinfo_dispose(&usbctrlinfo); 
> > +    return rc; 
> > +} 
> > + 
> > +/* AO operation to add a usb device. 
> > + * 
> > + * Generally, it does: 
> > + * 1) check if the usb device type is assignable 
> > + * 2) check if the usb device is already assigned to a domain 
> > + * 3) add 'busid' of the usb device to xenstore contoller/port/. 
> > + *    (PVUSB driver watches the xenstore changes and will detect that.) 
> > + * 4) unbind usb device from original driver and bind to usbback. 
> > + *    If usb device has many interfaces, then: 
> > + *    - unbind each interface from its original driver and bind to usbback. 
> > + *    - store the original driver to xenstore for later rebinding when 
> > + *      detaching the device. 
> > + */ 
> > +void libxl__device_usb_add(libxl__egc *egc, uint32_t domid, 
> > +                           libxl_device_usb *usb, 
> > +                           libxl__ao_device *aodev) 
> > +{ 
> > +    STATE_AO_GC(aodev->ao); 
> > +    int rc = ERROR_FAIL; 
> > +    char *busid = NULL; 
> > +    libxl_device_usb *assigned; 
> > +    int num_assigned; 
> > + 
> > +    assert(usb->u.hostdev.hostbus > 0 && usb->u.hostdev.hostaddr > 0); 
> > + 
> > +    busid = usb_busaddr_to_busid(gc, usb->u.hostdev.hostbus, 
> > +                                 usb->u.hostdev.hostaddr); 
> > +    if (!busid) { 
> > +        LOG(ERROR, "USB device doesn't exist in sysfs"); 
> > +        goto out; 
> > +    } 
> > + 
> > +    if (!is_usb_assignable(gc, usb)) { 
> > +        LOG(ERROR, "USB device is not assignable."); 
> > +        goto out; 
> > +    } 
>  
> Similar issue with pvusb driver domains: we can't do this check for 
> driver domains. 
>  
> I wonder if we should do this check instead down on the 
> usbback_assign_path(). 
>  
> If we assume that for pvusb driver domains: 
> 1. All assignable devices will be assigned to usbback 
> 2. No controllers will be assigned (since they can't be) 
> 3. pvusb can say "no such device" for unassigned devices 
> then we can safely ignore the check for pvusb driver domains 
>  
> > + 
> > +    /* check usb device is already assigned */ 
> > +    rc = get_assigned_devices(gc, &assigned, &num_assigned); 
> > +    if (rc) { 
> > +        LOG(ERROR, "cannot determine if device is assigned," 
> > +                   " refusing to continue"); 
> > +        goto out; 
> > +    } 
> > + 
> > +    if (is_usbdev_in_array(assigned, num_assigned, usb)) { 
> > +        LOG(ERROR, "USB device already attached to a domain"); 
> > +        rc = ERROR_FAIL; 
> > +        goto out; 
> > +    } 
>  
> WRT driver domains: Since we're looking inside xenstore instead of 
> sysfs, we *can* actually do these checks. 
>  
> However, the "bus.addr" space is defined by the driver domain kernel, 
> and is not unique across all driver domains: If we have one usb 
> controller assigned to domain 0, and another assigned to a driver 
> domain, two distinct devices are likely to end up with the same bus.addr. 
>  
> So to be compatible with driver domains, we'd need to have 
> get_assigned_devices() only get devices with the same backend_domid as 
> the controller we're checking. 
>  
> > +int libxl_device_usb_getinfo(libxl_ctx *ctx, uint32_t domid, 
> > +                             libxl_device_usb *usb, 
> > +                             libxl_usbinfo *usbinfo) 
> > +{ 
> > +    GC_INIT(ctx); 
> > +    char *filename; 
> > +    char *busid; 
> > +    void *buf = NULL; 
> > +    int buflen, rc; 
> > + 
> > +    usbinfo->ctrl = usb->ctrl; 
> > +    usbinfo->port = usb->port; 
> > + 
> > +    if (libxl_ctrlport_to_device_usb(ctx, domid, 
> > +                                     usb->ctrl, usb->port, usb) < 0) { 
> > +        rc = ERROR_FAIL; 
> > +        goto out; 
> > +    } 
>  
> I suppose technically since usb isn't declared const that we haven't 
> promised to modify it; but none of the other device_*_getinfo() 
> functions modify the device struct; I think it would be better to follow 
> suit and use a local variable to get the information from.

Take it.
 
>  
> However... 
>  
> > + 
> > +    usbinfo->devnum = usb->u.hostdev.hostaddr; 
> > +    usbinfo->busnum = usb->u.hostdev.hostbus; 
> > + 
> > +    busid = usb_busaddr_to_busid(gc, usb->u.hostdev.hostbus, 
> > +                                 usb->u.hostdev.hostaddr); 
> > +    if (!busid) { 
> > +        rc = ERROR_FAIL; 
> > +        goto out; 
> > +    } 
> > + 
> > +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idVendor", busid); 
> > +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL)) 
> > +        sscanf(buf, "%" SCNx16, &usbinfo->idVendor); 
> > + 
> > +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idProduct", busid); 
> > +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL)) 
> > +        sscanf(buf, "%" SCNx16, &usbinfo->idProduct); 
> > + 
> > +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/manufacturer", busid); 
> > +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, &buflen) && 
> > +        buflen > 0) { 
> > +        /* replace \n to \0 */ 
> > +        if (((char *)buf)[buflen - 1] == '\n') 
> > +            ((char *)buf)[buflen - 1] = '\0'; 
> > +        usbinfo->manuf = libxl__strdup(NOGC, buf); 
> > +   } 
> > + 
> > +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/product", busid); 
> > +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, &buflen) && 
> > +        buflen > 0) { 
> > +        /* replace \n to \0 */ 
> > +        if (((char *)buf)[buflen - 1] == '\n') 
> > +            ((char *)buf)[buflen - 1] = '\0'; 
> > +        usbinfo->prod = libxl__strdup(NOGC, buf); 
> > +    } 
>  
> Basically, starting here, we have information which won't be available 
> if we're using a pvusb driver domain. 
>  
> This information is nice-to-have, but I don't think this information is 
> directly relevant to libxl or xl; the funcitonality to get this 
> information is available from other libraries like libusb.  I'm inclined 
> to say that if we want to have pvusb driver domains (and I think we do), 
> we should just get rid of this information.

For command 'xl usb-list', those information should be reported to user.
Do you mean we could call libusb to get thoes information directly in
xl toolstack and get rid of this function?

I think we can keep the function, since every other device type has the
function XXX_getinfo. But here we could check backend_domid, for
backend=dom0, doing above work; for backend!=dom0 (e.g. pvusb
driver domain, no matter how, it should also be able to let users getting
those information. Can add code  in future.)
 
>  
> > diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl 
> > index 9f6ec00..4844f18 100644 
> > --- a/tools/libxl/libxl_types.idl 
> > +++ b/tools/libxl/libxl_types.idl 
> > @@ -595,6 +595,35 @@ libxl_device_rdm = Struct("device_rdm", [ 
> >      ("policy", libxl_rdm_reserve_policy), 
> >      ]) 
> >   
> > +libxl_usbctrl_type = Enumeration("usbctrl_type", [ 
> > +    (0, "AUTO"), 
> > +    (1, "PV"), 
> > +    (2, "DEVICEMODEL"), 
> > +    ]) 
> > + 
> > +libxl_usbdev_type = Enumeration("usbdev_type", [ 
> > +    (1, "hostdev"), 
> > +    ]) 
> > + 
> > +libxl_device_usbctrl = Struct("device_usbctrl", [ 
> > +    ("type", libxl_usbctrl_type), 
> > +    ("devid", libxl_devid), 
> > +    ("version", integer), 
> > +    ("ports", integer), 
> > +    ("backend_domid", libxl_domid), 
> > +    ("backend_domname", string), 
> > +   ]) 
> > + 
> > +libxl_device_usb = Struct("device_usb", [ 
> > +    ("ctrl", libxl_devid), 
> > +    ("port", integer), 
> > +    ("u", KeyedUnion(None, libxl_usbdev_type, "devtype", 
> > +           [("hostdev", Struct(None, [ 
> > +                 ("hostbus",   uint8), 
> > +                 ("hostaddr",  uint8)])), 
> > +           ])), 
> > +    ]) 
> > + 
> >  libxl_device_dtdev = Struct("device_dtdev", [ 
> >      ("path", string), 
> >      ]) 
> > @@ -627,6 +656,8 @@ libxl_domain_config = Struct("domain_config", [ 
> >      ("pcidevs", Array(libxl_device_pci, "num_pcidevs")), 
> >      ("rdms", Array(libxl_device_rdm, "num_rdms")), 
> >      ("dtdevs", Array(libxl_device_dtdev, "num_dtdevs")), 
> > +    ("usbctrls", Array(libxl_device_usbctrl, "num_usbctrls")), 
> > +    ("usbs", Array(libxl_device_usb, "num_usbs")), 
> >      ("vfbs", Array(libxl_device_vfb, "num_vfbs")), 
> >      ("vkbs", Array(libxl_device_vkb, "num_vkbs")), 
> >      ("vtpms", Array(libxl_device_vtpm, "num_vtpms")), 
> > @@ -676,6 +707,32 @@ libxl_vtpminfo = Struct("vtpminfo", [ 
> >      ("uuid", libxl_uuid), 
> >      ], dir=DIR_OUT) 
> >   
> > +libxl_usbctrlinfo = Struct("usbctrlinfo", [ 
> > +    ("type", libxl_usbctrl_type), 
> > +    ("devid", libxl_devid), 
> > +    ("version", integer), 
> > +    ("ports", integer), 
> > +    ("backend", string), 
> > +    ("backend_id", uint32), 
> > +    ("frontend", string), 
> > +    ("frontend_id", uint32), 
> > +    ("state", integer), 
> > +    ("evtch", integer), 
> > +    ("ref_urb", integer), 
> > +    ("ref_conn", integer), 
> > +    ], dir=DIR_OUT) 
> > + 
> > +libxl_usbinfo = Struct("usbinfo", [ 
> > +    ("ctrl", libxl_devid), 
> > +    ("port", integer), 
> > +    ("busnum", uint8), 
> > +    ("devnum", uint8), 
> > +    ("idVendor", uint16), 
> > +    ("idProduct", uint16), 
> > +    ("prod", string), 
> > +    ("manuf", string), 
> > +    ], dir=DIR_OUT) 
>  
> With the exception of the stuff in libxl_usbinfo we can't get if the 
> backend isn't dom0, the interface looks good to me now. 
>  
> OK, so I've covered four things: 
>  
> 1. The DEFINE_DEVICE_REMOVE_EXT macro.  I think I'd prefer checking in 
> things are as it is, and then have a follow-up patch to refactor 
> everything into a single DEFINE_DEVICE_REMOVE macro as described above. 
>  
> 2. COMPARE_USB.  I think this needs to be fixed; but this should be a 
> fairly simple change. 
>  
> 3. The conditional in libxl__device_destroy, the struct copy in 
> libxl_devid_to_device_usbctrl, and the modification of the device in 
> libxl_device_usb_getinfo are minor adjustments that can be discussed and 
> fixed. 
>  
> 4. The pvusb driver domain != dom0 comments.  This is somewhat secondary 
> to your primary goal; but at the moment the code will certainly not 
> work.  We have a couple of options: 
> a: Wait until we've fixed the driver domain functionality 
> b: Check the code in right now, with the driver domain fuctionality 
> explicitly disabled; that is, it will return an error if 
> backend_domain!=0.  Get a promise to implement the driver domain 
> functionality properly for 4.7 (on the threat of removing the feature).

I'll check the codes and add backend_domain check in related functions.

Thanks,
Chunyan  
 
> c: Take driver domain support out of the interface for now; send 
> follow-up patches to implement it properly. 
> d. Take driver domain support out of the interface and leave it that 
> way, for simplicity. 
>  
> I'd probably go with b or c. 
>  
> Thoughts? 
>  
>  -George 
>  
>  

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 3/7] libxl: add pvusb API
  2015-10-12  7:19     ` Chun Yan Liu
@ 2015-10-12 13:46       ` George Dunlap
  2015-10-13  1:46         ` Chun Yan Liu
  0 siblings, 1 reply; 59+ messages in thread
From: George Dunlap @ 2015-10-12 13:46 UTC (permalink / raw)
  To: Chun Yan Liu, xen-devel
  Cc: Juergen Gross, wei.liu2, ian.campbell, george.dunlap,
	Ian.Jackson, Jim Fehlig, Simon Cao

On 12/10/15 08:19, Chun Yan Liu wrote:
>>> + 
>>> +    usbinfo->devnum = usb->u.hostdev.hostaddr; 
>>> +    usbinfo->busnum = usb->u.hostdev.hostbus; 
>>> + 
>>> +    busid = usb_busaddr_to_busid(gc, usb->u.hostdev.hostbus, 
>>> +                                 usb->u.hostdev.hostaddr); 
>>> +    if (!busid) { 
>>> +        rc = ERROR_FAIL; 
>>> +        goto out; 
>>> +    } 
>>> + 
>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idVendor", busid); 
>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL)) 
>>> +        sscanf(buf, "%" SCNx16, &usbinfo->idVendor); 
>>> + 
>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idProduct", busid); 
>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL)) 
>>> +        sscanf(buf, "%" SCNx16, &usbinfo->idProduct); 
>>> + 
>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/manufacturer", busid); 
>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, &buflen) && 
>>> +        buflen > 0) { 
>>> +        /* replace \n to \0 */ 
>>> +        if (((char *)buf)[buflen - 1] == '\n') 
>>> +            ((char *)buf)[buflen - 1] = '\0'; 
>>> +        usbinfo->manuf = libxl__strdup(NOGC, buf); 
>>> +   } 
>>> + 
>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/product", busid); 
>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, &buflen) && 
>>> +        buflen > 0) { 
>>> +        /* replace \n to \0 */ 
>>> +        if (((char *)buf)[buflen - 1] == '\n') 
>>> +            ((char *)buf)[buflen - 1] = '\0'; 
>>> +        usbinfo->prod = libxl__strdup(NOGC, buf); 
>>> +    } 
>>  
>> Basically, starting here, we have information which won't be available 
>> if we're using a pvusb driver domain. 
>>  
>> This information is nice-to-have, but I don't think this information is 
>> directly relevant to libxl or xl; the funcitonality to get this 
>> information is available from other libraries like libusb.  I'm inclined 
>> to say that if we want to have pvusb driver domains (and I think we do), 
>> we should just get rid of this information.
> 
> For command 'xl usb-list', those information should be reported to user.
> Do you mean we could call libusb to get thoes information directly in
> xl toolstack and get rid of this function?
> 
> I think we can keep the function, since every other device type has the
> function XXX_getinfo. But here we could check backend_domid, for
> backend=dom0, doing above work; for backend!=dom0 (e.g. pvusb
> driver domain, no matter how, it should also be able to let users getting
> those information. Can add code  in future.)

Does xl need that information?  Can't the user get that information from
lsusb?

In any case, I can see why it would be *useful* to have in xl.  But
about having it in libxl, I think this question sort of goes along with
the question about the next patch -- whether libxl should be in the
business of providing general information about the USB devices it's
handling, or whether it should limit itself to doing what is absolutely
necessary to talk to usbback.

There's a part of me that sees the point of it: it's not actually that
much extra code (at least for Linux), and it makes it easy to add some
very useful features to xl.

On the other hand, it's not portable to other OSes.  At the moment of
course pvusb isn't portable either, but once we have qemu USB (providing
either emulated or PV usb) then I *think* most of the other
functionality will Just Work on any platform that can compile qemu
(incl. FreeBSD, NetBSD, &c), won't it?  The code you're introducing here
would have to be re-implented for those platforms, and for every new
platform that wanted to include this functionality, wouldn't it?

The libusb interface does look a bit clunky; it would certainly be more
convenient for developers to use the interface you've provided here.

 -George

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 3/7] libxl: add pvusb API
  2015-10-12 13:46       ` George Dunlap
@ 2015-10-13  1:46         ` Chun Yan Liu
  2015-10-13 13:15           ` George Dunlap
  0 siblings, 1 reply; 59+ messages in thread
From: Chun Yan Liu @ 2015-10-13  1:46 UTC (permalink / raw)
  To: George Dunlap, Chun Yan Liu, xen-devel
  Cc: Juergen Gross, wei.liu2, ian.campbell, george.dunlap,
	Ian.Jackson, Jim Fehlig, Simon Cao



On 10/12/2015 09:46 PM, George Dunlap wrote:
> On 12/10/15 08:19, Chun Yan Liu wrote:
>>>> +
>>>> +    usbinfo->devnum = usb->u.hostdev.hostaddr;
>>>> +    usbinfo->busnum = usb->u.hostdev.hostbus;
>>>> +
>>>> +    busid = usb_busaddr_to_busid(gc, usb->u.hostdev.hostbus,
>>>> +                                 usb->u.hostdev.hostaddr);
>>>> +    if (!busid) {
>>>> +        rc = ERROR_FAIL;
>>>> +        goto out;
>>>> +    }
>>>> +
>>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idVendor", busid);
>>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
>>>> +        sscanf(buf, "%" SCNx16, &usbinfo->idVendor);
>>>> +
>>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idProduct", busid);
>>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
>>>> +        sscanf(buf, "%" SCNx16, &usbinfo->idProduct);
>>>> +
>>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/manufacturer", busid);
>>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, &buflen) &&
>>>> +        buflen > 0) {
>>>> +        /* replace \n to \0 */
>>>> +        if (((char *)buf)[buflen - 1] == '\n')
>>>> +            ((char *)buf)[buflen - 1] = '\0';
>>>> +        usbinfo->manuf = libxl__strdup(NOGC, buf);
>>>> +   }
>>>> +
>>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/product", busid);
>>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, &buflen) &&
>>>> +        buflen > 0) {
>>>> +        /* replace \n to \0 */
>>>> +        if (((char *)buf)[buflen - 1] == '\n')
>>>> +            ((char *)buf)[buflen - 1] = '\0';
>>>> +        usbinfo->prod = libxl__strdup(NOGC, buf);
>>>> +    }
>>>   
>>> Basically, starting here, we have information which won't be available
>>> if we're using a pvusb driver domain.
>>>   
>>> This information is nice-to-have, but I don't think this information is
>>> directly relevant to libxl or xl; the funcitonality to get this
>>> information is available from other libraries like libusb.  I'm inclined
>>> to say that if we want to have pvusb driver domains (and I think we do),
>>> we should just get rid of this information.
>> For command 'xl usb-list', those information should be reported to user.
>> Do you mean we could call libusb to get thoes information directly in
>> xl toolstack and get rid of this function?
>>
>> I think we can keep the function, since every other device type has the
>> function XXX_getinfo. But here we could check backend_domid, for
>> backend=dom0, doing above work; for backend!=dom0 (e.g. pvusb
>> driver domain, no matter how, it should also be able to let users getting
>> those information. Can add code  in future.)
> Does xl need that information?  Can't the user get that information from
> lsusb?
>
> In any case, I can see why it would be *useful* to have in xl.  But
> about having it in libxl, I think this question sort of goes along with
> the question about the next patch -- whether libxl should be in the
> business of providing general information about the USB devices it's
> handling, or whether it should limit itself to doing what is absolutely
> necessary to talk to usbback.
>
> There's a part of me that sees the point of it: it's not actually that
> much extra code (at least for Linux), and it makes it easy to add some
> very useful features to xl.
>
> On the other hand, it's not portable to other OSes.  At the moment of
> course pvusb isn't portable either, but once we have qemu USB (providing
> either emulated or PV usb) then I *think* most of the other
> functionality will Just Work on any platform that can compile qemu
> (incl. FreeBSD, NetBSD, &c), won't it?  The code you're introducing here
> would have to be re-implented for those platforms, and for every new
> platform that wanted to include this functionality, wouldn't it?
So, about the portability problem, I think it's back to: do need to
update code to call libusb instead of reading sysfs now? Except
for this function, still have places reading sysfs to get hostbus,
hostaddr, vendorId, deviceId. Those are not portable for other
platform.

And about getting rid of the function, currently it's only needed in
'xl usb-list' and 'xl usb-assignable-list', if not providing general
information, yes, we can remove it.

-Chunyan

>
> The libusb interface does look a bit clunky; it would certainly be more
> convenient for developers to use the interface you've provided here.
>
>   -George
>

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 3/7] libxl: add pvusb API
  2015-10-13  1:46         ` Chun Yan Liu
@ 2015-10-13 13:15           ` George Dunlap
  2015-10-13 13:19             ` George Dunlap
                               ` (2 more replies)
  0 siblings, 3 replies; 59+ messages in thread
From: George Dunlap @ 2015-10-13 13:15 UTC (permalink / raw)
  To: Chun Yan Liu, Chun Yan Liu, xen-devel
  Cc: Juergen Gross, wei.liu2, ian.campbell, george.dunlap,
	Ian.Jackson, Jim Fehlig, Simon Cao

On 13/10/15 02:46, Chun Yan Liu wrote:
> 
> 
> On 10/12/2015 09:46 PM, George Dunlap wrote:
>> On 12/10/15 08:19, Chun Yan Liu wrote:
>>>>> +
>>>>> +    usbinfo->devnum = usb->u.hostdev.hostaddr;
>>>>> +    usbinfo->busnum = usb->u.hostdev.hostbus;
>>>>> +
>>>>> +    busid = usb_busaddr_to_busid(gc, usb->u.hostdev.hostbus,
>>>>> +                                 usb->u.hostdev.hostaddr);
>>>>> +    if (!busid) {
>>>>> +        rc = ERROR_FAIL;
>>>>> +        goto out;
>>>>> +    }
>>>>> +
>>>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idVendor", busid);
>>>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
>>>>> +        sscanf(buf, "%" SCNx16, &usbinfo->idVendor);
>>>>> +
>>>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idProduct", busid);
>>>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
>>>>> +        sscanf(buf, "%" SCNx16, &usbinfo->idProduct);
>>>>> +
>>>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/manufacturer", busid);
>>>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf,
>>>>> &buflen) &&
>>>>> +        buflen > 0) {
>>>>> +        /* replace \n to \0 */
>>>>> +        if (((char *)buf)[buflen - 1] == '\n')
>>>>> +            ((char *)buf)[buflen - 1] = '\0';
>>>>> +        usbinfo->manuf = libxl__strdup(NOGC, buf);
>>>>> +   }
>>>>> +
>>>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/product", busid);
>>>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf,
>>>>> &buflen) &&
>>>>> +        buflen > 0) {
>>>>> +        /* replace \n to \0 */
>>>>> +        if (((char *)buf)[buflen - 1] == '\n')
>>>>> +            ((char *)buf)[buflen - 1] = '\0';
>>>>> +        usbinfo->prod = libxl__strdup(NOGC, buf);
>>>>> +    }
>>>>   Basically, starting here, we have information which won't be
>>>> available
>>>> if we're using a pvusb driver domain.
>>>>   This information is nice-to-have, but I don't think this
>>>> information is
>>>> directly relevant to libxl or xl; the funcitonality to get this
>>>> information is available from other libraries like libusb.  I'm
>>>> inclined
>>>> to say that if we want to have pvusb driver domains (and I think we
>>>> do),
>>>> we should just get rid of this information.
>>> For command 'xl usb-list', those information should be reported to user.
>>> Do you mean we could call libusb to get thoes information directly in
>>> xl toolstack and get rid of this function?
>>>
>>> I think we can keep the function, since every other device type has the
>>> function XXX_getinfo. But here we could check backend_domid, for
>>> backend=dom0, doing above work; for backend!=dom0 (e.g. pvusb
>>> driver domain, no matter how, it should also be able to let users
>>> getting
>>> those information. Can add code  in future.)
>> Does xl need that information?  Can't the user get that information from
>> lsusb?
>>
>> In any case, I can see why it would be *useful* to have in xl.  But
>> about having it in libxl, I think this question sort of goes along with
>> the question about the next patch -- whether libxl should be in the
>> business of providing general information about the USB devices it's
>> handling, or whether it should limit itself to doing what is absolutely
>> necessary to talk to usbback.
>>
>> There's a part of me that sees the point of it: it's not actually that
>> much extra code (at least for Linux), and it makes it easy to add some
>> very useful features to xl.
>>
>> On the other hand, it's not portable to other OSes.  At the moment of
>> course pvusb isn't portable either, but once we have qemu USB (providing
>> either emulated or PV usb) then I *think* most of the other
>> functionality will Just Work on any platform that can compile qemu
>> (incl. FreeBSD, NetBSD, &c), won't it?  The code you're introducing here
>> would have to be re-implented for those platforms, and for every new
>> platform that wanted to include this functionality, wouldn't it?
> So, about the portability problem, I think it's back to: do need to
> update code to call libusb instead of reading sysfs now? Except
> for this function, still have places reading sysfs to get hostbus,
> hostaddr, vendorId, deviceId. Those are not portable for other
> platform.

I realize I didn't give you very clear guidance; I guess I was hoping to
get an opinion from the tools maintainers.  Or perhaps, I was hoping to
let them be the "bad guys" and say, "You can't have this feature in
libxl", so I wouldn't have to. :-)

In the absence of guidance to the contrary, I suggest that patch series
should focus on getting the core pvusb functionality in, without the
extra usb-querying bits.  Then we can discuss a further series which
either adds the usb querying functionality to libxl, or implement it in
xl using libusb.

 -George

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 3/7] libxl: add pvusb API
  2015-10-13 13:15           ` George Dunlap
@ 2015-10-13 13:19             ` George Dunlap
  2015-10-13 13:30             ` Ian Campbell
  2015-10-14  2:29             ` Chun Yan Liu
  2 siblings, 0 replies; 59+ messages in thread
From: George Dunlap @ 2015-10-13 13:19 UTC (permalink / raw)
  To: Chun Yan Liu, Chun Yan Liu, xen-devel
  Cc: Juergen Gross, wei.liu2, ian.campbell, george.dunlap,
	Ian.Jackson, Jim Fehlig, Simon Cao

On 13/10/15 14:15, George Dunlap wrote:
> On 13/10/15 02:46, Chun Yan Liu wrote:
>>
>>
>> On 10/12/2015 09:46 PM, George Dunlap wrote:
>>> On 12/10/15 08:19, Chun Yan Liu wrote:
>>>>>> +
>>>>>> +    usbinfo->devnum = usb->u.hostdev.hostaddr;
>>>>>> +    usbinfo->busnum = usb->u.hostdev.hostbus;
>>>>>> +
>>>>>> +    busid = usb_busaddr_to_busid(gc, usb->u.hostdev.hostbus,
>>>>>> +                                 usb->u.hostdev.hostaddr);
>>>>>> +    if (!busid) {
>>>>>> +        rc = ERROR_FAIL;
>>>>>> +        goto out;
>>>>>> +    }
>>>>>> +
>>>>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idVendor", busid);
>>>>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
>>>>>> +        sscanf(buf, "%" SCNx16, &usbinfo->idVendor);
>>>>>> +
>>>>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idProduct", busid);
>>>>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
>>>>>> +        sscanf(buf, "%" SCNx16, &usbinfo->idProduct);
>>>>>> +
>>>>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/manufacturer", busid);
>>>>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf,
>>>>>> &buflen) &&
>>>>>> +        buflen > 0) {
>>>>>> +        /* replace \n to \0 */
>>>>>> +        if (((char *)buf)[buflen - 1] == '\n')
>>>>>> +            ((char *)buf)[buflen - 1] = '\0';
>>>>>> +        usbinfo->manuf = libxl__strdup(NOGC, buf);
>>>>>> +   }
>>>>>> +
>>>>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/product", busid);
>>>>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf,
>>>>>> &buflen) &&
>>>>>> +        buflen > 0) {
>>>>>> +        /* replace \n to \0 */
>>>>>> +        if (((char *)buf)[buflen - 1] == '\n')
>>>>>> +            ((char *)buf)[buflen - 1] = '\0';
>>>>>> +        usbinfo->prod = libxl__strdup(NOGC, buf);
>>>>>> +    }
>>>>>   Basically, starting here, we have information which won't be
>>>>> available
>>>>> if we're using a pvusb driver domain.
>>>>>   This information is nice-to-have, but I don't think this
>>>>> information is
>>>>> directly relevant to libxl or xl; the funcitonality to get this
>>>>> information is available from other libraries like libusb.  I'm
>>>>> inclined
>>>>> to say that if we want to have pvusb driver domains (and I think we
>>>>> do),
>>>>> we should just get rid of this information.
>>>> For command 'xl usb-list', those information should be reported to user.
>>>> Do you mean we could call libusb to get thoes information directly in
>>>> xl toolstack and get rid of this function?
>>>>
>>>> I think we can keep the function, since every other device type has the
>>>> function XXX_getinfo. But here we could check backend_domid, for
>>>> backend=dom0, doing above work; for backend!=dom0 (e.g. pvusb
>>>> driver domain, no matter how, it should also be able to let users
>>>> getting
>>>> those information. Can add code  in future.)
>>> Does xl need that information?  Can't the user get that information from
>>> lsusb?
>>>
>>> In any case, I can see why it would be *useful* to have in xl.  But
>>> about having it in libxl, I think this question sort of goes along with
>>> the question about the next patch -- whether libxl should be in the
>>> business of providing general information about the USB devices it's
>>> handling, or whether it should limit itself to doing what is absolutely
>>> necessary to talk to usbback.
>>>
>>> There's a part of me that sees the point of it: it's not actually that
>>> much extra code (at least for Linux), and it makes it easy to add some
>>> very useful features to xl.
>>>
>>> On the other hand, it's not portable to other OSes.  At the moment of
>>> course pvusb isn't portable either, but once we have qemu USB (providing
>>> either emulated or PV usb) then I *think* most of the other
>>> functionality will Just Work on any platform that can compile qemu
>>> (incl. FreeBSD, NetBSD, &c), won't it?  The code you're introducing here
>>> would have to be re-implented for those platforms, and for every new
>>> platform that wanted to include this functionality, wouldn't it?
>> So, about the portability problem, I think it's back to: do need to
>> update code to call libusb instead of reading sysfs now? Except
>> for this function, still have places reading sysfs to get hostbus,
>> hostaddr, vendorId, deviceId. Those are not portable for other
>> platform.
> 
> I realize I didn't give you very clear guidance; I guess I was hoping to
> get an opinion from the tools maintainers.  Or perhaps, I was hoping to
> let them be the "bad guys" and say, "You can't have this feature in
> libxl", so I wouldn't have to. :-)
> 
> In the absence of guidance to the contrary, I suggest that patch series
> should focus on getting the core pvusb functionality in, without the
> extra usb-querying bits.  Then we can discuss a further series which
> either adds the usb querying functionality to libxl, or implement it in
> xl using libusb.

Just to be clear: Reading sysfs to actually implement the core pvusb
protocol is fine, because at the moment there *is* only a Linux backend.
 You should be able to get the core pvusb functionality in without
resorting to libusb.  It's just the additional usb information that we
may want to use libusb for, to avoid having to duplicate that for other
platforms once we have qemu-usb enabled.

 -George

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 3/7] libxl: add pvusb API
  2015-10-13 13:15           ` George Dunlap
  2015-10-13 13:19             ` George Dunlap
@ 2015-10-13 13:30             ` Ian Campbell
  2015-10-14  2:29             ` Chun Yan Liu
  2 siblings, 0 replies; 59+ messages in thread
From: Ian Campbell @ 2015-10-13 13:30 UTC (permalink / raw)
  To: George Dunlap, Chun Yan Liu, Chun Yan Liu, xen-devel
  Cc: Juergen Gross, wei.liu2, george.dunlap, Ian.Jackson, Jim Fehlig,
	Simon Cao

On Tue, 2015-10-13 at 14:15 +0100, George Dunlap wrote:
> In the absence of guidance to the contrary, I suggest that patch series
> should focus on getting the core pvusb functionality in, without the
> extra usb-querying bits.  Then we can discuss a further series which
> either adds the usb querying functionality to libxl, or implement it in
> xl using libusb.

That would seem sensible to me. Lets get the (hopefully) uncontroversial
core functionality done and then worry about any extras etc, since they
seem to be preventing us from making forward progress at the moment.

Ian.

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH V7 3/7] libxl: add pvusb API
  2015-10-13 13:15           ` George Dunlap
  2015-10-13 13:19             ` George Dunlap
  2015-10-13 13:30             ` Ian Campbell
@ 2015-10-14  2:29             ` Chun Yan Liu
  2 siblings, 0 replies; 59+ messages in thread
From: Chun Yan Liu @ 2015-10-14  2:29 UTC (permalink / raw)
  To: George Dunlap, Chun Yan Liu, xen-devel
  Cc: Juergen Gross, wei.liu2, ian.campbell, george.dunlap,
	Ian.Jackson, Jim Fehlig, Simon Cao



On 10/13/2015 09:15 PM, George Dunlap wrote:
> On 13/10/15 02:46, Chun Yan Liu wrote:
>>
>> On 10/12/2015 09:46 PM, George Dunlap wrote:
>>> On 12/10/15 08:19, Chun Yan Liu wrote:
>>>>>> +
>>>>>> +    usbinfo->devnum = usb->u.hostdev.hostaddr;
>>>>>> +    usbinfo->busnum = usb->u.hostdev.hostbus;
>>>>>> +
>>>>>> +    busid = usb_busaddr_to_busid(gc, usb->u.hostdev.hostbus,
>>>>>> +                                 usb->u.hostdev.hostaddr);
>>>>>> +    if (!busid) {
>>>>>> +        rc = ERROR_FAIL;
>>>>>> +        goto out;
>>>>>> +    }
>>>>>> +
>>>>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idVendor", busid);
>>>>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
>>>>>> +        sscanf(buf, "%" SCNx16, &usbinfo->idVendor);
>>>>>> +
>>>>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idProduct", busid);
>>>>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
>>>>>> +        sscanf(buf, "%" SCNx16, &usbinfo->idProduct);
>>>>>> +
>>>>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/manufacturer", busid);
>>>>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf,
>>>>>> &buflen) &&
>>>>>> +        buflen > 0) {
>>>>>> +        /* replace \n to \0 */
>>>>>> +        if (((char *)buf)[buflen - 1] == '\n')
>>>>>> +            ((char *)buf)[buflen - 1] = '\0';
>>>>>> +        usbinfo->manuf = libxl__strdup(NOGC, buf);
>>>>>> +   }
>>>>>> +
>>>>>> +    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/product", busid);
>>>>>> +    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf,
>>>>>> &buflen) &&
>>>>>> +        buflen > 0) {
>>>>>> +        /* replace \n to \0 */
>>>>>> +        if (((char *)buf)[buflen - 1] == '\n')
>>>>>> +            ((char *)buf)[buflen - 1] = '\0';
>>>>>> +        usbinfo->prod = libxl__strdup(NOGC, buf);
>>>>>> +    }
>>>>>    Basically, starting here, we have information which won't be
>>>>> available
>>>>> if we're using a pvusb driver domain.
>>>>>    This information is nice-to-have, but I don't think this
>>>>> information is
>>>>> directly relevant to libxl or xl; the funcitonality to get this
>>>>> information is available from other libraries like libusb.  I'm
>>>>> inclined
>>>>> to say that if we want to have pvusb driver domains (and I think we
>>>>> do),
>>>>> we should just get rid of this information.
>>>> For command 'xl usb-list', those information should be reported to user.
>>>> Do you mean we could call libusb to get thoes information directly in
>>>> xl toolstack and get rid of this function?
>>>>
>>>> I think we can keep the function, since every other device type has the
>>>> function XXX_getinfo. But here we could check backend_domid, for
>>>> backend=dom0, doing above work; for backend!=dom0 (e.g. pvusb
>>>> driver domain, no matter how, it should also be able to let users
>>>> getting
>>>> those information. Can add code  in future.)
>>> Does xl need that information?  Can't the user get that information from
>>> lsusb?
>>>
>>> In any case, I can see why it would be *useful* to have in xl.  But
>>> about having it in libxl, I think this question sort of goes along with
>>> the question about the next patch -- whether libxl should be in the
>>> business of providing general information about the USB devices it's
>>> handling, or whether it should limit itself to doing what is absolutely
>>> necessary to talk to usbback.
>>>
>>> There's a part of me that sees the point of it: it's not actually that
>>> much extra code (at least for Linux), and it makes it easy to add some
>>> very useful features to xl.
>>>
>>> On the other hand, it's not portable to other OSes.  At the moment of
>>> course pvusb isn't portable either, but once we have qemu USB (providing
>>> either emulated or PV usb) then I *think* most of the other
>>> functionality will Just Work on any platform that can compile qemu
>>> (incl. FreeBSD, NetBSD, &c), won't it?  The code you're introducing here
>>> would have to be re-implented for those platforms, and for every new
>>> platform that wanted to include this functionality, wouldn't it?
>> So, about the portability problem, I think it's back to: do need to
>> update code to call libusb instead of reading sysfs now? Except
>> for this function, still have places reading sysfs to get hostbus,
>> hostaddr, vendorId, deviceId. Those are not portable for other
>> platform.
> I realize I didn't give you very clear guidance; I guess I was hoping to
> get an opinion from the tools maintainers.  Or perhaps, I was hoping to
> let them be the "bad guys" and say, "You can't have this feature in
> libxl", so I wouldn't have to. :-)
>
> In the absence of guidance to the contrary, I suggest that patch series
> should focus on getting the core pvusb functionality in, without the
> extra usb-querying bits.  Then we can discuss a further series which
> either adds the usb querying functionality to libxl, or implement it in
> xl using libusb.
OK. Got it. Thanks.

-Chunyan

>
>   -George
>

^ permalink raw reply	[flat|nested] 59+ messages in thread

end of thread, other threads:[~2015-10-14  2:29 UTC | newest]

Thread overview: 59+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-25  2:11 [PATCH V7 0/7] xen pvusb toolstack work Chunyan Liu
2015-09-25  2:11 ` [PATCH V7 1/7] libxl: export some functions for pvusb use Chunyan Liu
2015-09-25  2:11 ` [PATCH V7 2/7] libxl_read_file_contents: add new entry to read sysfs file Chunyan Liu
2015-09-30 11:22   ` George Dunlap
2015-10-02 13:25   ` Ian Campbell
2015-09-25  2:11 ` [PATCH V7 3/7] libxl: add pvusb API Chunyan Liu
2015-09-30 17:55   ` George Dunlap
2015-10-02 13:31     ` Ian Campbell
2015-10-09  8:12     ` Chun Yan Liu
2015-10-12  7:19     ` Chun Yan Liu
2015-10-12 13:46       ` George Dunlap
2015-10-13  1:46         ` Chun Yan Liu
2015-10-13 13:15           ` George Dunlap
2015-10-13 13:19             ` George Dunlap
2015-10-13 13:30             ` Ian Campbell
2015-10-14  2:29             ` Chun Yan Liu
2015-10-08 14:41   ` Ian Jackson
2015-10-08 14:54     ` Ian Campbell
2015-10-08 15:16       ` Ian Jackson
2015-10-12  7:00     ` Chun Yan Liu
2015-09-25  2:11 ` [PATCH V7 4/7] libxl: add libxl_device_usb_assignable_list API Chunyan Liu
2015-10-01 11:32   ` George Dunlap
2015-09-25  2:11 ` [PATCH V7 5/7] xl: add pvusb commands Chunyan Liu
2015-10-01 17:02   ` George Dunlap
2015-10-02 13:35     ` Ian Campbell
2015-10-02 15:17       ` George Dunlap
2015-10-02 15:29         ` Ian Campbell
2015-10-09  7:15     ` Chun Yan Liu
2015-09-25  2:11 ` [PATCH V7 6/7] xl: add usb-assignable-list command Chunyan Liu
2015-10-06 16:55   ` George Dunlap
2015-10-07  8:40     ` Ian Campbell
2015-10-07  9:55       ` Juergen Gross
2015-10-07 10:08         ` Ian Campbell
2015-10-07 10:10       ` George Dunlap
2015-10-07 10:15         ` George Dunlap
2015-10-07 10:35         ` Christiane Groß
2015-10-07 11:09         ` Ian Campbell
2015-10-07 11:20           ` George Dunlap
2015-10-07 11:25             ` Juergen Gross
2015-10-07 11:32               ` George Dunlap
2015-10-07 11:37               ` Ian Campbell
2015-10-07 11:39                 ` Juergen Gross
2015-10-07 11:43                 ` Ian Campbell
2015-10-07 11:39               ` Ian Campbell
2015-10-07 11:49                 ` Juergen Gross
2015-10-07 11:55                   ` Ian Campbell
2015-10-07 12:05                     ` Juergen Gross
2015-10-07 12:51                       ` Ian Campbell
2015-10-07 13:21                       ` George Dunlap
2015-10-07 13:54                         ` Juergen Gross
2015-10-07 14:05                           ` Ian Campbell
2015-10-07 14:26                             ` Juergen Gross
2015-10-07 14:35                               ` George Dunlap
2015-10-07 14:47                                 ` Juergen Gross
2015-10-07 15:03                                   ` George Dunlap
2015-10-07 15:13                                     ` Juergen Gross
2015-10-07 14:10                           ` George Dunlap
2015-09-25  2:11 ` [PATCH V7 7/7] domcreate: support pvusb in configuration file Chunyan Liu
2015-10-07 15:06   ` George Dunlap

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.