xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH V4 0/7] xen pvusb toolstack work
@ 2015-06-10  3:20 Chunyan Liu
  2015-06-10  3:20 ` [PATCH V4 1/7] libxl: export some functions for pvusb use Chunyan Liu
                   ` (6 more replies)
  0 siblings, 7 replies; 88+ messages in thread
From: Chunyan Liu @ 2015-06-10  3:20 UTC (permalink / raw)
  To: xen-devel; +Cc: george.dunlap, wei.liu2, Ian.Jackson, ian.campbell, Chunyan Liu

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 v3:
* add new entry for reading sysfs file contents to get usb device info.
* merge pv|qemu protocol in earlier patches, instead of refacotring in
  a separate patch, with minimum code to handle that.
* change libxl_device_usbctrl_add to be async, consistent with
  usbctrl_remove. Using MACROs as possible, adjusting related codes.
* use libxl_* helpers as possible, instead of calloc, realloc, strdup, etc.
* correct update_json related processing.
* other fixes addring V3 comments

V3 is here:
http://lists.xen.org/archives/html/xen-devel/2015-04/msg02114.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

For better understanding, a summary about pvusb is posted in following.

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).

Additionally, for easy use of PVUSB, you need support in the toolstack
to get the two sides to talk to each other.

2. Specifying a host USB device

QEMU hmp 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 Hub could not be assigned to guest.

3. PVUSB toolstack

* Specify USB device in xl config file

You can just specify usb devices, like:
usb=['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', ]
usb=['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.

To be compatible with QEMU emulated USB, this interface could be
extended to:
usb=['1.6, type=pv|qemu',]
type=pv means attaching the USB device in pvusb way; type=qemu means
attaching USB device in QEMU emulated way.

* 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.

To be compatible with QEMU emulated USB, these interfaces could be
extended to:
xl usb-attach domain 1.6 type=pv|qemu
xl usb-detach domain 1.6 type=pv|qemu
QEMU emulated USB won't handle USB controller create/delete through
xl, so usb-ctrl-attach|detach operations are currently pvusb only.

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.


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                    |   38 +
 docs/misc/pvusb.txt                  |  243 +++++++
 tools/libxl/Makefile                 |    2 +-
 tools/libxl/libxl.c                  |   12 +-
 tools/libxl/libxl.h                  |   68 ++
 tools/libxl/libxl_create.c           |   73 +-
 tools/libxl/libxl_device.c           |    2 +
 tools/libxl/libxl_internal.h         |   25 +-
 tools/libxl/libxl_osdeps.h           |   13 +
 tools/libxl/libxl_pvusb.c            | 1295 ++++++++++++++++++++++++++++++++++
 tools/libxl/libxl_types.idl          |   52 ++
 tools/libxl/libxl_types_internal.idl |    1 +
 tools/libxl/libxl_utils.c            |   40 +-
 tools/libxl/libxl_utils.h            |    2 +
 tools/libxl/xl.h                     |    6 +
 tools/libxl/xl_cmdimpl.c             |  387 +++++++++-
 tools/libxl/xl_cmdtable.c            |   29 +
 18 files changed, 2350 insertions(+), 13 deletions(-)
 create mode 100644 docs/misc/pvusb.txt
 create mode 100644 tools/libxl/libxl_pvusb.c

-- 
2.1.4

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

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

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

diff --git a/tools/libxl/libxl.c b/tools/libxl/libxl.c
index 9117b01..bd4daea 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1963,7 +1963,7 @@ out:
 /******************************************************************************/
 
 /* generic callback for devices that only need to set ao_complete */
-static void device_addrm_aocomplete(libxl__egc *egc, libxl__ao_device *aodev)
+void device_addrm_aocomplete(libxl__egc *egc, libxl__ao_device *aodev)
 {
     STATE_AO_GC(aodev->ao);
 
@@ -1986,7 +1986,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;
@@ -2005,7 +2005,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 bb3a5c7..ef7aa1d 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -1083,6 +1083,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:
@@ -2225,6 +2228,8 @@ struct libxl__ao_device {
 
 /* Starts preparing to add/remove a bunch of devices. */
 _hidden void libxl__multidev_begin(libxl__ao *ao, libxl__multidev*);
+/* generic callback for devices that only need to set ao_complete */
+_hidden void device_addrm_aocomplete(libxl__egc *egc, libxl__ao_device *aodev);
 
 /* Prepares to add/remove one of many devices.
  * Calls libxl__prepare_ao_device on libxl__ao_device argument provided and
-- 
2.1.4

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

* [PATCH V4 2/7] libxl_read_file_contents: add new entry to read sysfs file
  2015-06-10  3:20 [PATCH V4 0/7] xen pvusb toolstack work Chunyan Liu
  2015-06-10  3:20 ` [PATCH V4 1/7] libxl: export some functions for pvusb use Chunyan Liu
@ 2015-06-10  3:20 ` Chunyan Liu
  2015-06-11 16:16   ` Ian Jackson
  2015-06-10  3:20 ` [PATCH V4 3/7] libxl: add pvusb API Chunyan Liu
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 88+ messages in thread
From: Chunyan Liu @ 2015-06-10  3:20 UTC (permalink / raw)
  To: xen-devel; +Cc: george.dunlap, wei.liu2, Ian.Jackson, ian.campbell, Chunyan Liu

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>

---
Changes:
  - instead of hacking lixbl_read_file_contents for sysfs file, add
    a new entry libxl_read_sysfs_file_contents to do the work.

 tools/libxl/libxl_utils.c | 24 ++++++++++++++++++++----
 tools/libxl/libxl_utils.h |  2 ++
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/tools/libxl/libxl_utils.c b/tools/libxl/libxl_utils.c
index f6be2d7..d0d56c2 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 is_sysfs_file)
+{
     GC_INIT(ctx);
     FILE *f = 0;
     uint8_t *data = 0;
@@ -360,15 +362,16 @@ int libxl_read_file_contents(libxl_ctx *ctx, const char *filename,
 
     if (stab.st_size && data_r) {
         data = malloc(datalen);
+        memset(data, 0, datalen);
         if (!data) goto xe;
 
         rs = fread(data, 1, datalen, f);
-        if (rs != datalen) {
+        if (rs != datalen && !(feof(f) && is_sysfs_file)) {
             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);
+                   filename);
             else
                 abort();
             goto xe;
@@ -396,6 +399,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,                 \
diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h
index 1c1761d..7639662 100644
--- a/tools/libxl/libxl_utils.h
+++ b/tools/libxl/libxl_utils.h
@@ -38,6 +38,8 @@ int libxl_is_stubdom(libxl_ctx *ctx, uint32_t domid, uint32_t *target_domid);
 int libxl_create_logfile(libxl_ctx *ctx, const char *name, char **full_name);
 int libxl_string_to_backend(libxl_ctx *ctx, char *s, libxl_disk_backend *backend);
 
+int libxl_read_sysfs_file_contents(libxl_ctx *ctx, const char *filename,
+                                   void **data_r, int *datalen_r);
 int libxl_read_file_contents(libxl_ctx *ctx, const char *filename,
                              void **data_r, int *datalen_r);
   /* Reads the contents of the plain file filename into a mallocd
-- 
2.1.4

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

* [PATCH V4 3/7] libxl: add pvusb API
  2015-06-10  3:20 [PATCH V4 0/7] xen pvusb toolstack work Chunyan Liu
  2015-06-10  3:20 ` [PATCH V4 1/7] libxl: export some functions for pvusb use Chunyan Liu
  2015-06-10  3:20 ` [PATCH V4 2/7] libxl_read_file_contents: add new entry to read sysfs file Chunyan Liu
@ 2015-06-10  3:20 ` Chunyan Liu
  2015-06-11 15:00   ` Juergen Gross
                     ` (3 more replies)
  2015-06-10  3:20 ` [PATCH V4 4/7] libxl: add libxl_device_usb_assignable_list API Chunyan Liu
                   ` (3 subsequent siblings)
  6 siblings, 4 replies; 88+ messages in thread
From: Chunyan Liu @ 2015-06-10  3:20 UTC (permalink / raw)
  To: xen-devel
  Cc: wei.liu2, ian.campbell, george.dunlap, Ian.Jackson, Chunyan Liu,
	Simon Cao

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

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

---
changes:
  - make libxl_device_usbctrl_add async, to be consistent with
    libxl_device_usbctrl_remove, using MACROs DEFINE_DEVICE_ADD
    and DEFINE_DEVICES_ADD, adjusting related codes.
  - correct update_json related processing.
  - use libxl__* helper functions instead of calloc, realloc
    and strdup, etc. whereever possible.
  - merge protocol definition pv|qemu in this patch
  - treat it as warning at rebind failure instead of error in usb_remove
  - add documentation docs/misc/pvusb.txt to describe pvusb
    details (toolstack design, libxl design, xenstore info, etc.)
  - other fixes addring Wei and George's comments

 docs/misc/pvusb.txt                  |  243 +++++++
 tools/libxl/Makefile                 |    2 +-
 tools/libxl/libxl.c                  |    6 +
 tools/libxl/libxl.h                  |   65 ++
 tools/libxl/libxl_internal.h         |   16 +-
 tools/libxl/libxl_osdeps.h           |   13 +
 tools/libxl/libxl_pvusb.c            | 1249 ++++++++++++++++++++++++++++++++++
 tools/libxl/libxl_types.idl          |   52 ++
 tools/libxl/libxl_types_internal.idl |    1 +
 tools/libxl/libxl_utils.c            |   16 +
 10 files changed, 1661 insertions(+), 2 deletions(-)
 create mode 100644 docs/misc/pvusb.txt
 create mode 100644 tools/libxl/libxl_pvusb.c

diff --git a/docs/misc/pvusb.txt b/docs/misc/pvusb.txt
new file mode 100644
index 0000000..4cdf965
--- /dev/null
+++ b/docs/misc/pvusb.txt
@@ -0,0 +1,243 @@
+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).
+
+Additionally, for easy use of PVUSB, you need support in the toolstack
+to get the two sides to talk to each other.
+
+2. Specifying a host USB device
+
+QEMU hmp 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 Hub could 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.
diff --git a/tools/libxl/Makefile b/tools/libxl/Makefile
index cc9c152..b820105 100644
--- a/tools/libxl/Makefile
+++ b/tools/libxl/Makefile
@@ -95,7 +95,7 @@ LIBXL_OBJS = flexarray.o libxl.o libxl_create.o libxl_dm.o libxl_pci.o \
 			libxl_internal.o libxl_utils.o libxl_uuid.o \
 			libxl_json.o libxl_aoutils.o libxl_numa.o libxl_vnuma.o \
 			libxl_save_callout.o _libxl_save_msgs_callout.o \
-			libxl_qmp.o libxl_event.o libxl_fork.o $(LIBXL_OBJS-y)
+			libxl_qmp.o libxl_event.o libxl_fork.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 bd4daea..f9331f4 100644
--- a/tools/libxl/libxl.c
+++ b/tools/libxl/libxl.c
@@ -1611,6 +1611,8 @@ void libxl__destroy_domid(libxl__egc *egc, libxl__destroy_domid_state *dis)
 
     if (libxl__device_pci_destroy_all(gc, domid) < 0)
         LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "pci shutdown failed for domid %d", domid);
+    if (libxl__device_usb_destroy_all(gc, domid) < 0)
+        LIBXL__LOG(ctx, LIBXL__LOG_ERROR, "usb shutdown failed for domid %d", domid);
     rc = xc_domain_pause(ctx->xch, domid);
     if (rc < 0) {
         LIBXL__LOG_ERRNOVAL(ctx, LIBXL__LOG_ERROR, rc, "xc_domain_pause failed for %d", domid);
@@ -6760,6 +6762,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 0a7913b..d192300 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -123,6 +123,23 @@
 #define LIBXL_HAVE_DOMAIN_NODEAFFINITY 1
 
 /*
+ * LIBXL_HAVE_PVUSB indicates the functions for doing hot-plug of
+ * USB devices through pvusb.
+ *
+ * With this functionality, 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 either 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 either 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.
+ *
+ */
+#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
@@ -1269,6 +1286,54 @@ 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 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)
+                                LIBXL_EXTERNAL_CALLERS_ONLY;
+
+/* 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);
+
+libxl_device_usb *
+libxl_device_usb_list_per_usbctrl(libxl_ctx *ctx, uint32_t domid,
+                                  int usbctrl, int *num);
+
+void libxl_device_usb_list_free(libxl_device_usb* list, int nr);
+
+int libxl_device_usb_getinfo(libxl_ctx *ctx, libxl_device_usb *usb,
+                             libxl_usbinfo *usbinfo)
+                             LIBXL_EXTERNAL_CALLERS_ONLY;
 /* 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_internal.h b/tools/libxl/libxl_internal.h
index ef7aa1d..89a9f07 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -2439,6 +2439,18 @@ _hidden void libxl__device_vtpm_add(libxl__egc *egc, uint32_t domid,
                                    libxl_device_vtpm *vtpm,
                                    libxl__ao_device *aodev);
 
+/* AO operation to connect a PVUSB controller.
+ * Adding a PVUSB controller will add a 'vusb' device entry in xenstore,
+ * and will wait for device connection.
+ */
+_hidden void libxl__device_usbctrl_add(libxl__egc *egc, uint32_t domid,
+                               libxl_device_usbctrl *usbctrl,
+                               libxl__ao_device *aodev);
+_hidden int libxl__device_usb_add(libxl__gc *gc, uint32_t domid,
+                                  libxl_device_usb *usb,
+                                  bool update_json);
+_hidden int libxl__device_usb_destroy_all(libxl__gc *gc, uint32_t domid);
+
 /* Internal function to connect a vkb device */
 _hidden int libxl__device_vkb_add(libxl__gc *gc, uint32_t domid,
                                   libxl_device_vkb *vkb);
@@ -3646,7 +3658,9 @@ 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) (!strcmp((a)->busid, (b)->busid))
+#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 08eaf0c..55caf71 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,12 +42,21 @@
 #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"
 #include <libutil.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..a6e1aa1
--- /dev/null
+++ b/tools/libxl/libxl_pvusb.c
@@ -0,0 +1,1249 @@
+/*
+ * 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"
+
+#define USBBACK_INFO_PATH "/libxl/usbback"
+
+#define USBHUB_CLASS_CODE 0x09
+
+static int libxl__device_usbctrl_setdefault(libxl__gc *gc, uint32_t domid,
+                                            libxl_device_usbctrl *usbctrl)
+{
+    int rc;
+
+    if (!usbctrl->version)
+        usbctrl->version = 2;
+
+    if (!usbctrl->ports)
+        usbctrl->ports = 8;
+
+    if (usbctrl->protocol == LIBXL_USB_PROTOCOL_AUTO)
+        usbctrl->protocol = LIBXL_USB_PROTOCOL_PV;
+
+    rc = libxl__resolve_domid(gc, usbctrl->backend_domname,
+                              &usbctrl->backend_domid);
+    return rc;
+}
+
+static 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;
+}
+
+void libxl__device_usbctrl_add(libxl__egc *egc, uint32_t domid,
+                               libxl_device_usbctrl *usbctrl,
+                               libxl__ao_device *aodev)
+{
+    STATE_AO_GC(aodev->ao);
+    flexarray_t *front;
+    flexarray_t *back;
+    libxl__device *device;
+    xs_transaction_t t = XBT_NULL;
+    char *path;
+    int i, rc;
+    libxl_domain_config d_config;
+    libxl_device_usbctrl usbctrl_saved;
+    libxl__domain_userdata_lock *lock = NULL;
+
+    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;
+        }
+    }
+
+    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_usb_protocol_to_string(usbctrl->protocol));
+    flexarray_append_pair(back, "usb-ver", GCSPRINTF("%d", usbctrl->version));
+    flexarray_append_pair(back, "num-ports", GCSPRINTF("%d", usbctrl->ports));
+    flexarray_append_pair(front, "backend-id",
+                          GCSPRINTF("%d", usbctrl->backend_domid));
+    flexarray_append_pair(front, "state", "1");
+
+    if (aodev->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 (aodev->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);
+
+        path = GCSPRINTF("%s/port", libxl__device_backend_path(gc, device));
+        libxl__xs_mkdir(gc, t, path, NULL, 0);
+        for (i = 0; i < usbctrl->ports; i++) {
+            rc = libxl__xs_write_checked(gc, t,
+                                         GCSPRINTF("%s/%d", path, i + 1), "");
+            if (rc) goto out;
+        }
+
+        rc = libxl__xs_transaction_commit(gc, &t);
+        if (!rc) break;
+        if (rc < 0) goto out;
+    }
+
+    aodev->dev = device;
+    aodev->action = LIBXL__DEVICE_ACTION_ADD;
+    libxl__wait_device_connection(egc, aodev);
+
+    rc = 0;
+
+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);
+    aodev->rc = rc;
+    if (rc) aodev->callback(egc, aodev);
+    return;
+}
+
+static int libxl_device_usbctrl_add_common(libxl_ctx *ctx,
+                                           uint32_t domid,
+                                           libxl_device_usbctrl *usbctrl,
+                                           const libxl_asyncop_how *ao_how,
+                                           bool update_json)
+{
+    AO_CREATE(ctx, domid, ao_how);
+    libxl__ao_device *aodev;
+
+    GCNEW(aodev);
+    libxl__prepare_ao_device(ao, aodev);
+    aodev->action = LIBXL__DEVICE_ACTION_ADD;
+    aodev->callback = device_addrm_aocomplete;
+    aodev->update_json = update_json;
+    libxl__device_usbctrl_add(egc, domid, usbctrl, aodev);
+
+    return AO_INPROGRESS;
+}
+
+int libxl_device_usbctrl_add(libxl_ctx *ctx, uint32_t domid,
+                             libxl_device_usbctrl *usbctrl,
+                             const libxl_asyncop_how *ao_how)
+{
+    return libxl_device_usbctrl_add_common(ctx, domid, usbctrl, ao_how, 1);
+}
+
+static int
+libxl__device_usb_list_per_usbctrl(libxl__gc *gc, uint32_t domid, int usbctrl,
+                                   libxl_device_usb **usbs, int *num);
+
+static int
+do_usb_remove(libxl__gc *gc, uint32_t domid, libxl_device_usb *usb);
+
+static int
+libxl_device_usbctrl_remove_common(libxl_ctx *ctx, uint32_t domid,
+                                   libxl_device_usbctrl *usbctrl,
+                                   const libxl_asyncop_how *ao_how,
+                                   int force)
+{
+    AO_CREATE(ctx, domid, ao_how);
+    libxl__device *device;
+    libxl__ao_device *aodev;
+    libxl_device_usbctrl *usbctrls = NULL;
+    libxl_device_usbctrl *usbctrl_find = NULL;
+    int numctrl = 0;
+    libxl_device_usb *usbs = NULL;
+    int numusb = 0;
+    int i, rc;
+
+    usbctrls = libxl_device_usbctrl_list(ctx, domid, &numctrl);
+    if (!numctrl) {
+        LOG(ERROR, "No USB controller exists in this domain");
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    for (i = 0; i < numctrl; i++) {
+        if (usbctrl->devid == usbctrls[i].devid) {
+            usbctrl_find = usbctrls + i;
+            break;
+        }
+    }
+
+    if (!usbctrl_find) {
+        LOG(ERROR, "USB controller %d is not attached to this domain",
+            usbctrl->devid);
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    GCNEW(device);
+    libxl__device_from_usbctrl(gc, domid, usbctrl_find, device);
+
+    /* Remove usb devices first */
+    rc  = libxl__device_usb_list_per_usbctrl(gc, domid, usbctrl->devid,
+                                             &usbs, &numusb);
+    if (rc) goto out;
+
+    for (i = 0; i < numusb; i++) {
+        if (do_usb_remove(gc, domid, &usbs[i])) {
+            LOG(ERROR, "do_usb_remove failed");
+            rc = ERROR_FAIL;
+            goto out;
+        }
+    }
+
+    /* Remove usbctrl */
+    GCNEW(aodev);
+    libxl__prepare_ao_device(ao, aodev);
+    aodev->action = LIBXL__DEVICE_ACTION_REMOVE;
+    aodev->dev = device;
+    aodev->callback = device_addrm_aocomplete;
+    aodev->force = force;
+    libxl__initiate_device_remove(egc, aodev);
+
+out:
+    libxl_device_usbctrl_list_free(usbctrls, numctrl);
+    libxl_device_usb_list_free(usbs, numusb);
+    if (rc) return AO_ABORT(rc);
+    return AO_INPROGRESS;
+}
+
+int libxl_device_usbctrl_remove(libxl_ctx *ctx, uint32_t domid,
+                                libxl_device_usbctrl *usbctrl,
+                                const libxl_asyncop_how *ao_how)
+{
+    return libxl_device_usbctrl_remove_common(ctx, domid, usbctrl, ao_how, 0);
+}
+
+int libxl_device_usbctrl_destroy(libxl_ctx *ctx, uint32_t domid,
+                                 libxl_device_usbctrl *usbctrl,
+                                 const libxl_asyncop_how *ao_how)
+{
+    return libxl_device_usbctrl_remove_common(ctx, domid, usbctrl, ao_how, 1);
+}
+
+libxl_device_usbctrl *
+libxl_device_usbctrl_list(libxl_ctx *ctx, uint32_t domid, int *num)
+{
+    GC_INIT(ctx);
+    libxl_device_usbctrl *usbctrls = NULL;
+    char *fe_path = NULL;
+    char **dir = NULL;
+    unsigned int ndirs = 0;
+
+    *num = 0;
+
+    fe_path = GCSPRINTF("%s/device/vusb",
+                        libxl__xs_get_dompath(gc, domid));
+    dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
+
+    if (dir && ndirs) {
+        usbctrls = malloc(sizeof(*usbctrls) * ndirs);
+        libxl_device_usbctrl* usbctrl;
+        libxl_device_usbctrl* end = usbctrls + ndirs;
+        for (usbctrl = usbctrls; usbctrl < end; usbctrl++, dir++, (*num)++) {
+            char *tmp;
+            const char *be_path = libxl__xs_read(gc, XBT_NULL,
+                                    GCSPRINTF("%s/%s/backend", fe_path, *dir));
+
+            libxl_device_usbctrl_init(usbctrl);
+            usbctrl->devid = atoi(*dir);
+
+            tmp = libxl__xs_read(gc, XBT_NULL,
+                                 GCSPRINTF("%s/%s/backend-id", fe_path, *dir));
+            if (!tmp) goto outerr;
+            usbctrl->backend_domid = atoi(tmp);
+
+            tmp = libxl__xs_read(gc, XBT_NULL,
+                                 GCSPRINTF("%s/usb-ver", be_path));
+            if (!tmp) goto outerr;
+            usbctrl->version = atoi(tmp);
+
+            tmp = libxl__xs_read(gc, XBT_NULL,
+                                 GCSPRINTF("%s/num-ports", be_path));
+            if (!tmp) goto outerr;
+            usbctrl->ports = atoi(tmp);
+
+            tmp = libxl__xs_read(gc, XBT_NULL,
+                                 GCSPRINTF("%s/type", be_path));
+            if (!tmp ||
+                libxl_usb_protocol_from_string(tmp, &usbctrl->protocol))
+                goto outerr;
+        }
+    }
+
+    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, *usbctrlpath;
+    char *val;
+    int rc = 0;
+
+    usbctrlinfo->devid = usbctrl->devid;
+    usbctrlinfo->ports = usbctrl->ports;
+    usbctrlinfo->version = usbctrl->version;
+    usbctrlinfo->protocol = usbctrl->protocol;
+
+    dompath = libxl__xs_get_dompath(gc, domid);
+    usbctrlpath = GCSPRINTF("%s/device/vusb/%d", dompath, usbctrlinfo->devid);
+    val = libxl__xs_read(gc, XBT_NULL,
+                         GCSPRINTF("%s/backend", usbctrlpath));
+    usbctrlinfo->backend = libxl__strdup(NOGC, val);
+    if (!usbctrlinfo->backend) {
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    val = libxl__xs_read(gc, XBT_NULL,
+                         GCSPRINTF("%s/backend-id", usbctrlpath));
+    usbctrlinfo->backend_id = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+                         GCSPRINTF("%s/state", usbctrlpath));
+    usbctrlinfo->state = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+                         GCSPRINTF("%s/event-channel", usbctrlpath));
+    usbctrlinfo->evtch = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+                         GCSPRINTF("%s/urb-ring-ref", usbctrlpath));
+    usbctrlinfo->ref_urb = val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+                         GCSPRINTF("%s/conn-ring-ref", usbctrlpath));
+    usbctrlinfo->ref_conn= val ? strtoul(val, NULL, 10) : -1;
+
+    val = libxl__xs_read(gc, XBT_NULL,
+                         GCSPRINTF("%s/frontend", usbctrlinfo->backend));
+    usbctrlinfo->frontend = libxl__strdup(NOGC, val);
+
+    val = libxl__xs_read(gc, XBT_NULL,
+                         GCSPRINTF("%s/frontend-id", usbctrlinfo->backend));
+    usbctrlinfo->frontend_id = val ? strtoul(val, NULL, 10) : -1;
+
+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, "%x", &devnum);
+
+        filename = GCSPRINTF(SYSFS_USB_DEV"/%s/busnum", de->d_name);
+        if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
+            sscanf(buf, "%x", &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,
+                                   int *bus, int *addr)
+{
+    libxl_ctx *ctx = CTX;
+    char *filename;
+    void *buf;
+
+    assert(busid);
+
+    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/devnum", busid);
+    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
+        sscanf(buf, "%x", bus);
+
+    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/busnum", busid);
+    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
+        sscanf(buf, "%x", addr);
+}
+
+static int
+libxl__device_usb_assigned_list(libxl__gc *gc,
+                                libxl_device_usb **list, int *num)
+{
+    char **domlist;
+    unsigned int nd = 0, i, j;
+    char *be_path;
+    libxl_device_usb *usb;
+
+    *list = NULL;
+    *num = 0;
+
+    domlist = libxl__xs_directory(gc, XBT_NULL, "/local/domain", &nd);
+    be_path = GCSPRINTF("/local/domain/%d/backend/vusb", LIBXL_TOOLSTACK_DOMID);
+    for (i = 0; i < nd; i++) {
+        char *path, *num_ports, **ctrl_list;
+        unsigned int nc = 0;
+        path = GCSPRINTF("%s/%s", be_path, domlist[i]);
+        ctrl_list = libxl__xs_directory(gc, XBT_NULL, path , &nc);
+
+        for (j = 0; j < nc; j++) {
+            path = GCSPRINTF("%s/%s/%s/num-ports", be_path,
+                             domlist[i], ctrl_list[j]);
+            num_ports = libxl__xs_read(gc, XBT_NULL, path);
+            if (num_ports) {
+                int nport = atoi(num_ports), k;
+                char *devpath, *busid;
+
+                for (k = 0; k < nport; k++) {
+                    devpath = GCSPRINTF("%s/%s/%s/port/%u", be_path,
+                                        domlist[i], ctrl_list[j], k + 1);
+                    busid = libxl__xs_read(gc, XBT_NULL, devpath);
+                    /* If there are 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->busid = libxl__strdup(gc, busid);
+                        usb_busaddr_from_busid(gc, usb->busid,
+                                               &usb->hostbus, &usb->hostaddr);
+                        (*num)++;
+                    }
+                }
+            }
+        }
+    }
+
+    return 0;
+}
+
+static bool is_usb_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 */
+static bool is_usb_assigned(libxl__gc *gc, libxl_device_usb *usb)
+{
+    libxl_device_usb *usbs;
+    int rc, num;
+
+    rc = libxl__device_usb_assigned_list(gc, &usbs, &num);
+    if (rc) {
+        LOG(ERROR, "Fail to get assigned usb list");
+        return true;
+    }
+
+    return is_usb_in_array(usbs, num, usb);
+}
+
+/* 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;
+
+    assert(usb->busid);
+
+    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/bDeviceClass", usb->busid);
+    if (libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
+        return false;
+
+    sscanf(buf, "%x", &classcode);
+    return classcode != USBHUB_CLASS_CODE;
+}
+
+/* get usb devices under certain usb controller */
+static int
+libxl__device_usb_list_per_usbctrl(libxl__gc *gc, uint32_t domid, int usbctrl,
+                                   libxl_device_usb **usbs, int *num)
+{
+    char *be_path, *num_devs;
+    int n, i;
+
+    *usbs = NULL;
+    *num = 0;
+
+    be_path = GCSPRINTF("%s/backend/vusb/%d/%d",
+                        libxl__xs_get_dompath(gc, LIBXL_TOOLSTACK_DOMID),
+                        domid, usbctrl);
+    num_devs = libxl__xs_read(gc, XBT_NULL,
+                              GCSPRINTF("%s/num-ports", be_path));
+    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->busid = libxl__strdup(NOGC, busid);
+            usb_busaddr_from_busid(gc, usb->busid,
+                                   &usb->hostbus, &usb->hostaddr);
+            (*num)++;
+        }
+    }
+
+    return 0;
+}
+
+/* get all usb devices of the domain */
+static libxl_device_usb *
+libxl__device_usb_list(libxl__gc *gc, uint32_t domid, int *num)
+{
+    char **usbctrls;
+    unsigned int nd = 0, i, j;
+    char *be_path;
+    int rc;
+    libxl_device_usb *usbs = NULL;
+
+    *num = 0;
+
+    be_path = GCSPRINTF("/local/domain/%d/backend/vusb/%d",
+                        LIBXL_TOOLSTACK_DOMID, domid);
+    usbctrls = libxl__xs_directory(gc, XBT_NULL, be_path, &nd);
+
+    for (i = 0; i < nd; i++) {
+        int nc = 0;
+        libxl_device_usb *tmp = NULL;
+        rc = libxl__device_usb_list_per_usbctrl(gc, domid,
+                                                atoi(usbctrls[i]), &tmp, &nc);
+        if (!nc) continue;
+
+        usbs = libxl__realloc(NOGC, usbs, sizeof(*usbs) * (*num + nc));
+        for (j = 0; j < nc; j++) {
+            usbs[*num] = tmp[j];
+            usbs[*num].busid = libxl__strdup(NOGC, tmp[j].busid);
+            (*num)++;
+        }
+        libxl_device_usb_list_free(tmp, nc);
+    }
+    return usbs;
+}
+
+libxl_device_usb *
+libxl_device_usb_list(libxl_ctx *ctx, uint32_t domid, int *num)
+{
+    GC_INIT(ctx);
+    libxl_device_usb *usbs = NULL;
+
+    usbs = libxl__device_usb_list(gc, domid, num);
+
+    GC_FREE;
+    return usbs;
+}
+
+libxl_device_usb *
+libxl_device_usb_list_per_usbctrl(libxl_ctx *ctx, uint32_t domid,
+                                  int usbctrl, int *num)
+{
+    GC_INIT(ctx);
+    libxl_device_usb *usbs = NULL;
+
+    libxl__device_usb_list_per_usbctrl(gc, domid, usbctrl, &usbs, num);
+
+    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;
+    char *be_path, *tmp;
+
+    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++) {
+            be_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, be_path);
+            if (tmp && !strcmp(tmp, "")) {
+                usb->ctrl = usbctrls[i].devid;
+                usb->port = j + 1;
+                rc = 0;
+                break;
+            }
+        }
+    }
+
+out:
+    libxl_device_usbctrl_list_free(usbctrls, numctrl);
+    return rc;
+}
+
+static int libxl__device_usb_setdefault(libxl__gc *gc, uint32_t domid,
+                                        libxl_device_usb *usb,
+                                        bool update_json)
+{
+    char *be_path, *tmp;
+
+    if (usb->ctrl == -1) {
+        int ret = libxl__device_usb_set_default_usbctrl(gc, domid, usb);
+        /* If no existing ctrl to host this usb device, setup a new one */
+        if (ret) {
+            libxl_device_usbctrl usbctrl;
+            libxl_device_usbctrl_init(&usbctrl);
+            if (libxl_device_usbctrl_add_common(CTX, domid, &usbctrl,
+                                                0, update_json)) {
+                LOG(ERROR, "Failed to create usb controller");
+                return ERROR_INVAL;
+            }
+            usb->ctrl = usbctrl.devid;
+            usb->port = 1;
+            libxl_device_usbctrl_dispose(&usbctrl);
+        }
+    }
+
+    be_path = GCSPRINTF("%s/backend/vusb/%d/%d/port/%d",
+                        libxl__xs_get_dompath(gc, LIBXL_TOOLSTACK_DOMID),
+                        domid, usb->ctrl, usb->port);
+    tmp = libxl__xs_read(gc, XBT_NULL, be_path);
+    if (!tmp || strcmp(tmp, "")) {
+        LOG(ERROR, "The controller port isn't available");
+        return ERROR_INVAL;
+    }
+
+    return 0;
+}
+
+static int libxl__device_usb_add_xenstore(libxl__gc *gc, uint32_t domid,
+                                          libxl_device_usb *usb,
+                                          bool update_json)
+{
+    char *be_path;
+    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);
+
+    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, usb->busid)) {
+            rc = ERROR_FAIL;
+            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;
+    int rc = 0;
+
+    *intfs = NULL;
+    *num = 0;
+
+    buf = GCSPRINTF("%s:", usb->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;
+}
+
+/* Cann't write '.' or ':' into Xenstore as key. So, change '.' to '_',
+ * change ':' to '-'.
+ */
+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 the usb device, then check each interface, unbind from usbback
+ * driver and rebind to 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 *usb_encode = NULL;
+
+    if (usb_get_all_interfaces(gc, usb, &intfs, &num) < 0)
+        return ERROR_FAIL;
+
+    usb_encode = usb_interface_xenstore_encode(usb->busid);
+
+    for (i = 0; i < num; i++) {
+        char *intf = intfs[i];
+        char *drvpath = NULL;
+
+        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 the 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 *usb_encode = NULL;
+
+    if (usb_get_all_interfaces(gc, usb, &intfs, &num) < 0)
+        return ERROR_FAIL;
+
+    usb_encode = usb_interface_xenstore_encode(usb->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;
+}
+
+int libxl__device_usb_add(libxl__gc *gc, uint32_t domid,
+                          libxl_device_usb *usb,
+                          bool update_json)
+{
+    int rc;
+
+    assert(usb->busid || (usb->hostbus > 0 && usb->hostaddr > 0));
+
+    if (!usb->busid) {
+        usb->busid = usb_busaddr_to_busid(gc, usb->hostbus, usb->hostaddr);
+        if (!usb->busid) {
+            LOG(ERROR, "USB device doesn't exist in sysfs");
+            return ERROR_INVAL;
+        }
+    }
+
+    if (!is_usb_assignable(gc, usb)) {
+        LOG(ERROR, "USB device is not assignable.");
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    /* check usb device is already assigned */
+    if (is_usb_assigned(gc, usb)) {
+        LOG(ERROR, "USB device is already attached to a domain.");
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    rc = libxl__device_usb_setdefault(gc, domid, usb, update_json);
+    if (rc) goto out;
+
+    rc = libxl__device_usb_add_xenstore(gc, domid, usb, update_json);
+    if (rc) goto out;
+
+    rc = usbback_dev_assign(gc, usb);
+    if (rc)
+        libxl__device_usb_remove_xenstore(gc, domid, usb);
+
+out:
+    return rc;
+}
+
+int libxl_device_usb_add(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_add(gc, domid, usb, 1);
+    libxl__ao_complete(egc, ao, rc);
+    return AO_INPROGRESS;
+}
+
+static int do_usb_remove(libxl__gc *gc, uint32_t domid,
+                         libxl_device_usb *usb)
+{
+    if (libxl__device_usb_remove_xenstore(gc, domid, usb))
+        return -1;
+
+    usbback_dev_unassign(gc, usb);
+
+    return 0;
+}
+
+static int libxl__device_usb_remove(libxl__gc *gc, uint32_t domid,
+                                    libxl_device_usb *usb)
+{
+    libxl_device_usb *usbs = NULL;
+    libxl_device_usb *usb_find = NULL;
+    int i, num = 0, rc;
+
+    assert(usb->busid || (usb->hostbus > 0 && usb->hostaddr > 0));
+
+    if (!usb->busid) {
+        usb->busid = usb_busaddr_to_busid(gc, usb->hostbus, usb->hostaddr);
+        if (!usb->busid) {
+            LOG(ERROR, "USB device doesn't exist in sysfs");
+            return ERROR_INVAL;
+        }
+    }
+
+    usbs = libxl__device_usb_list(gc, domid, &num);
+    if (!usbs) {
+       LOG(ERROR, "No USB device attached to this domain");
+       return ERROR_FAIL;
+    }
+
+    for (i = 0; i < num; i++) {
+        if (COMPARE_USB(usb, &usbs[i])) {
+            usb_find = usbs + i;
+            break;
+        }
+    }
+
+    /* doesn't find the usb device in domain's usb device list*/
+    if (!usb_find) {
+        LOG(ERROR, "USB device %x.%x is not attached to this domain",
+            usb->hostbus, usb->hostaddr);
+        rc = ERROR_FAIL;
+        goto out;
+    }
+
+    rc = do_usb_remove(gc, domid, usb_find);
+
+out:
+    libxl_device_usb_list_free(usbs, num);
+    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__device_usb_destroy_all(libxl__gc *gc, uint32_t domid)
+{
+    libxl_ctx *ctx = CTX;
+    libxl_device_usbctrl *usbctrls = NULL;
+    int i, num = 0, rc = 0;
+
+    usbctrls = libxl_device_usbctrl_list(ctx, domid, &num);
+    if (!usbctrls)
+        return 0;
+
+    for (i = 0; i < num; i++) {
+        /* Force remove on shutdown since, on HVM, qemu will not always
+         * respond to SCI interrupt because the guest kernel has shut
+         * down the devices by the time we even get here!
+         */
+        if (libxl_device_usbctrl_remove_common(ctx, domid,
+                                               usbctrls + i, 0, 1) < 0) {
+            rc = ERROR_FAIL;
+            goto out;
+        }
+    }
+
+out:
+    libxl_device_usbctrl_list_free(usbctrls, num);
+    return rc;
+}
+
+int libxl_device_usb_getinfo(libxl_ctx *ctx, libxl_device_usb *usb,
+                             libxl_usbinfo *usbinfo)
+{
+    GC_INIT(ctx);
+    char *filename;
+    void *buf = NULL;
+
+    usbinfo->ctrl = usb->ctrl;
+    usbinfo->port = usb->port;
+
+    if (usb->busid)
+        usbinfo->busid = libxl__strdup(NOGC, usb->busid);
+    else if (usb->hostbus > 0 && usb->hostaddr > 0)
+        usbinfo->busid = usb_busaddr_to_busid(gc, usb->hostbus, usb->hostaddr);
+
+    assert(usbinfo->busid);
+
+    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/devnum", usbinfo->busid);
+    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
+        sscanf(buf, "%x", &usbinfo->devnum);
+
+    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/busnum", usbinfo->busid);
+    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
+        sscanf(buf, "%x", &usbinfo->busnum);
+
+    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idVendor", usbinfo->busid);
+    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
+        sscanf(buf, "%x", &usbinfo->idVendor);
+
+    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/idProduct", usbinfo->busid);
+    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL))
+        sscanf(buf, "%x", &usbinfo->idProduct);
+
+    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/manufacturer", usbinfo->busid);
+    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL)) {
+        /* replace \n to \0 */
+        usbinfo->manuf = libxl__strdup(NOGC, buf);
+        if (usbinfo->manuf && strlen(usbinfo->manuf) > 0 &&
+            usbinfo->manuf[strlen(usbinfo->manuf) - 1] == '\n')
+            usbinfo->manuf[strlen(usbinfo->manuf) - 1] = '\0';
+    }
+
+    filename = GCSPRINTF(SYSFS_USB_DEV"/%s/product", usbinfo->busid);
+    if (!libxl_read_sysfs_file_contents(ctx, filename, &buf, NULL)) {
+       /* replace \n to \0 */
+       usbinfo->prod = libxl__strdup(NOGC, buf);
+       if (usbinfo->prod && strlen(usbinfo->prod) > 0 &&
+           usbinfo->prod[strlen(usbinfo->prod) - 1] == '\n')
+           usbinfo->prod[strlen(usbinfo->prod) - 1] = '\0';
+    }
+
+    GC_FREE;
+    return 0;
+}
+/*
+ * 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 23f27d4..4561e1b 100644
--- a/tools/libxl/libxl_types.idl
+++ b/tools/libxl/libxl_types.idl
@@ -541,6 +541,29 @@ libxl_device_pci = Struct("device_pci", [
     ("seize", bool),
     ])
 
+libxl_usb_protocol = Enumeration("usb_protocol", [
+    (0, "AUTO"),
+    (1, "PV"),
+    (2, "QEMU"),
+    ])
+
+libxl_device_usbctrl = Struct("device_usbctrl", [
+    ("protocol", libxl_usb_protocol),
+    ("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),
+    ("busid", string),
+    ("hostbus",   integer),
+    ("hostaddr",  integer),
+    ])
+
 libxl_device_dtdev = Struct("device_dtdev", [
     ("path", string),
     ])
@@ -572,6 +595,8 @@ libxl_domain_config = Struct("domain_config", [
     ("nics", Array(libxl_device_nic, "num_nics")),
     ("pcidevs", Array(libxl_device_pci, "num_pcidevs")),
     ("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")),
@@ -620,6 +645,33 @@ libxl_vtpminfo = Struct("vtpminfo", [
     ("uuid", libxl_uuid),
     ], dir=DIR_OUT)
 
+libxl_usbctrlinfo = Struct("usbctrlinfo", [
+    ("protocol", libxl_usb_protocol),
+    ("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),
+    ("busid", string),
+    ("busnum", integer),
+    ("devnum", integer),
+    ("idVendor", integer),
+    ("idProduct", integer),
+    ("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 d0d56c2..aca4bb9 100644
--- a/tools/libxl/libxl_utils.c
+++ b/tools/libxl/libxl_utils.c
@@ -1182,6 +1182,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
-- 
2.1.4

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

* [PATCH V4 4/7] libxl: add libxl_device_usb_assignable_list API
  2015-06-10  3:20 [PATCH V4 0/7] xen pvusb toolstack work Chunyan Liu
                   ` (2 preceding siblings ...)
  2015-06-10  3:20 ` [PATCH V4 3/7] libxl: add pvusb API Chunyan Liu
@ 2015-06-10  3:20 ` Chunyan Liu
  2015-06-10  3:20 ` [PATCH V4 5/7] xl: add pvusb commands Chunyan Liu
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 88+ messages in thread
From: Chunyan Liu @ 2015-06-10  3:20 UTC (permalink / raw)
  To: xen-devel; +Cc: george.dunlap, wei.liu2, Ian.Jackson, ian.campbell, Chunyan Liu

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 | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 49 insertions(+)

diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index d192300..b65a096 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -1314,6 +1314,9 @@ int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid,
                                 LIBXL_EXTERNAL_CALLERS_ONLY;
 
 /* 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 a6e1aa1..739a16d 100644
--- a/tools/libxl/libxl_pvusb.c
+++ b/tools/libxl/libxl_pvusb.c
@@ -555,6 +555,52 @@ 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 (libxl__device_usb_assigned_list(gc, &assigned, &num_assigned) < 0)
+        goto out;
+
+    if (!(dir = opendir(SYSFS_USB_DEV)))
+        goto out;
+
+    while ((de = readdir(dir))) {
+        libxl_device_usb usb;
+
+        if (!de->d_name)
+            continue;
+
+        usb.busid = de->d_name;
+        if (!is_usb_assignable(gc, &usb))
+            continue;
+
+        if (is_usb_in_array(assigned, num_assigned, &usb))
+            continue;
+
+        usbs = libxl__realloc(NOGC, usbs, sizeof(*usbs) * (*num + 1));
+        libxl_device_usb_init(usbs + *num);
+        usbs[*num].busid = libxl__strdup(NOGC, de->d_name);
+        usb_busaddr_from_busid(gc, usbs[*num].busid,
+                               &(usbs[*num].hostbus), &(usbs[*num].hostaddr));
+        (*num)++;
+    }
+
+    closedir(dir);
+
+out:
+    GC_FREE;
+    return usbs;
+}
+
 /* get usb devices under certain usb controller */
 static int
 libxl__device_usb_list_per_usbctrl(libxl__gc *gc, uint32_t domid, int usbctrl,
-- 
2.1.4

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

* [PATCH V4 5/7] xl: add pvusb commands
  2015-06-10  3:20 [PATCH V4 0/7] xen pvusb toolstack work Chunyan Liu
                   ` (3 preceding siblings ...)
  2015-06-10  3:20 ` [PATCH V4 4/7] libxl: add libxl_device_usb_assignable_list API Chunyan Liu
@ 2015-06-10  3:20 ` Chunyan Liu
  2015-06-12  7:37   ` Juergen Gross
  2015-06-10  3:20 ` [PATCH V4 6/7] xl: add usb-assignable-list command Chunyan Liu
  2015-06-10  3:20 ` [PATCH V4 7/7] domcreate: support pvusb in configuration file Chunyan Liu
  6 siblings, 1 reply; 88+ messages in thread
From: Chunyan Liu @ 2015-06-10  3:20 UTC (permalink / raw)
  To: xen-devel
  Cc: wei.liu2, ian.campbell, george.dunlap, Ian.Jackson, Chunyan Liu,
	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-assignable-list
 will list assignable USB devices

 #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 1.6

 #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         |  38 +++++++
 tools/libxl/xl.h          |   5 +
 tools/libxl/xl_cmdimpl.c  | 251 ++++++++++++++++++++++++++++++++++++++++++++++
 tools/libxl/xl_cmdtable.c |  25 +++++
 4 files changed, 319 insertions(+)

diff --git a/docs/man/xl.pod.1 b/docs/man/xl.pod.1
index 4eb929d..0259b43 100644
--- a/docs/man/xl.pod.1
+++ b/docs/man/xl.pod.1
@@ -1387,6 +1387,44 @@ List pass-through pci devices for a domain.
 
 =back
 
+=head1 USB PASS-THROUGH
+
+=over 4
+
+=item B<usb-ctrl-attach> I<domain-id> [I<version=val>] [I<ports=number>]
+
+Create a new USB controller for the specified domain.
+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.
+
+=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<bus.addr>
+
+Hot-unplug a previously assigned USB device from a domain. B<bus.addr> is
+busnum.devnum of the physical USB device to be removed from the guest domain.
+
+If B<-f> is specified, B<xl> is going to forcefully remove the device even
+without guest's collaboration.
+
+=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 5bc138c..2d57ee3 100644
--- a/tools/libxl/xl.h
+++ b/tools/libxl/xl.h
@@ -86,6 +86,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 c858068..b29d0fc 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -3219,6 +3219,257 @@ int main_cd_insert(int argc, char **argv)
     return 0;
 }
 
+static void usbinfo_print(libxl_device_usb *usbs, int num) {
+    int i;
+    if (usbs == NULL)
+         return;
+    for (i = 0; i < num; i++) {
+        libxl_usbinfo usbinfo;
+        libxl_usbinfo_init(&usbinfo);
+
+        if (usbs[i].port)
+            printf("  Port %d:", usbs[i].port);
+        if (!libxl_device_usb_getinfo(ctx, &usbs[i], &usbinfo)) {
+            printf(" Bus %03x Device %03x: ID %04x:%04x %s %s\n",
+                    usbinfo.busnum, usbinfo.devnum,
+                    usbinfo.idVendor, usbinfo.idProduct,
+                    usbinfo.manuf ?: "", usbinfo.prod ?: "");
+        }
+        libxl_usbinfo_dispose(&usbinfo);
+    }
+}
+
+int main_usbctrl_attach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    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.protocol = LIBXL_USB_PROTOCOL_PV;
+            } else {
+               fprintf(stderr, "unsupported type `%s'\n", oparg);
+               exit(-1);
+            }
+        } else if (MATCH_OPTION("version", argv[optind], oparg)) {
+            usbctrl.version = atoi(oparg);
+        } else if (MATCH_OPTION("ports", argv[optind], oparg)) {
+            usbctrl.ports = atoi(oparg);
+        } else {
+            fprintf(stderr, "unrecognized argument `%s'\n", argv[optind]);
+            exit(-1);
+        }
+        optind++;
+    }
+
+    if (usbctrl.protocol == LIBXL_USB_PROTOCOL_AUTO)
+        usbctrl.protocol = LIBXL_USB_PROTOCOL_PV;
+
+    if (dryrun_only) {
+       char* json = libxl_device_usbctrl_to_json(ctx, &usbctrl);
+       printf("usb controller: %s\n", json);
+       free(json);
+       libxl_device_usbctrl_dispose(&usbctrl);
+       if (ferror(stdout) || fflush(stdout)) {
+           perror("stdout");
+           exit(-1);
+       }
+       return 0;
+    }
+
+    if (libxl_device_usbctrl_add(ctx, domid, &usbctrl, 0)) {
+        fprintf(stderr, "libxl_device_usbctrl_add failed.\n");
+        exit(-1);
+    }
+    libxl_device_usbctrl_dispose(&usbctrl);
+    return 0;
+}
+
+int main_usbctrl_detach(int argc, char **argv)
+{
+    uint32_t domid;
+    int opt;
+    libxl_device_usbctrl usbctrl;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-ctrl-detach", 2) {
+        /* No options */
+    }
+
+    domid = find_domain(argv[optind]);
+
+    libxl_device_usbctrl_init(&usbctrl);
+    usbctrl.devid = atoi(argv[optind+1]);
+
+    if (libxl_device_usbctrl_remove(ctx, domid, &usbctrl, 0)) {
+        fprintf(stderr, "libxl_device_usbctrl_remove failed.\n");
+        exit(-1);
+    }
+    libxl_device_usbctrl_dispose(&usbctrl);
+    return 0;
+
+}
+
+int main_usbattach(int argc, char **argv)
+{
+    uint32_t domid;
+    char *devname, *p;
+    int opt;
+    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.hostbus = strtoul(devname, NULL, 0);
+        usb.hostaddr = strtoul(p + 1, NULL, 0);
+    }
+
+    if (usb.hostbus < 1 || usb.hostaddr < 1) {
+        fprintf(stderr, "Invalid usb device.\n");
+        exit(-1);
+    }
+
+    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]);
+            exit(-1);
+        }
+        optind++;
+    }
+
+    if (dryrun_only) {
+        char *json = libxl_device_usb_to_json(ctx, &usb);
+        printf("usb: %s\n", json);
+        free(json);
+        libxl_device_usb_dispose(&usb);
+        if (ferror(stdout) || fflush(stdout)) {
+            perror("stdout");
+            exit(-1);
+        }
+        return 0;
+    }
+
+    if (libxl_device_usb_add(ctx, domid, &usb, 0)) {
+        fprintf(stderr, "libxl_device_usb_add failed.\n");
+        exit(-1);
+    }
+
+    libxl_device_usb_dispose(&usb);
+    return 0;
+}
+
+int main_usbdetach(int argc, char **argv)
+{
+    uint32_t domid;
+    char *devname, *p;
+    int opt;
+    libxl_device_usb usb;
+
+    SWITCH_FOREACH_OPT(opt, "", NULL, "usb-detach", 2) {
+        /* No options */
+    }
+
+    libxl_device_usb_init(&usb);
+
+    domid = find_domain(argv[optind++]);
+    devname = argv[optind++];
+
+    if (argc > optind) {
+        fprintf(stderr, "Invalid arguments.\n");
+        exit(-1);
+    }
+
+    p = strchr(devname, '.');
+    if (p) {
+        usb.hostbus = strtoul(devname, NULL, 0);
+        usb.hostaddr = strtoul(p + 1, NULL, 0);
+    }
+
+    if (usb.hostbus < 1 || usb.hostaddr < 1) {
+        fprintf(stderr, "Invalid usb device.\n");
+        exit(-1);
+    }
+
+    if (libxl_device_usb_remove(ctx, domid, &usb, 0) ) {
+        fprintf(stderr, "libxl_device_usb_remove failed.\n");
+        exit(-1);
+    }
+    libxl_device_usb_dispose(&usb);
+    return 0;
+}
+
+int main_usblist(int argc, char **argv)
+{
+    uint32_t domid;
+    libxl_device_usbctrl *usbctrls;
+    libxl_device_usb *usbs;
+    libxl_usbctrlinfo usbctrlinfo;
+    int numctrl, numusb, i, 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");
+
+        if (!libxl_device_usbctrl_getinfo(ctx, domid,
+                                &usbctrls[i], &usbctrlinfo)) {
+            printf("%-6d %-6s %-3d %-5d %-7d %-5d %-30s\n",
+                    usbctrlinfo.devid,
+                    libxl_usb_protocol_to_string(usbctrlinfo.protocol),
+                    usbctrlinfo.backend_id, usbctrlinfo.state,
+                    usbctrlinfo.version, usbctrlinfo.ports,
+                    usbctrlinfo.backend);
+
+            usbs = libxl_device_usb_list_per_usbctrl(ctx, domid,
+                                                     usbctrlinfo.devid, &numusb);
+            usbinfo_print(usbs, numusb);
+
+            libxl_usbctrlinfo_dispose(&usbctrlinfo);
+        }
+        libxl_device_usbctrl_dispose(&usbctrls[i]);
+    }
+
+    free(usbctrls);
+    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 7f4759b..f1c5b43 100644
--- a/tools/libxl/xl_cmdtable.c
+++ b/tools/libxl/xl_cmdtable.c
@@ -545,6 +545,31 @@ struct cmd_spec cmd_table[] = {
       "\"local_mem_bandwidth\":     Show local memory bandwidth(KB/s)\n",
     },
 #endif
+    { "usb-ctrl-attach",
+      &main_usbctrl_attach, 1, 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, 1, 2,
+      "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> <bus.addr>",
+    },
+    { "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] 88+ messages in thread

* [PATCH V4 6/7] xl: add usb-assignable-list command
  2015-06-10  3:20 [PATCH V4 0/7] xen pvusb toolstack work Chunyan Liu
                   ` (4 preceding siblings ...)
  2015-06-10  3:20 ` [PATCH V4 5/7] xl: add pvusb commands Chunyan Liu
@ 2015-06-10  3:20 ` Chunyan Liu
  2015-06-10  3:20 ` [PATCH V4 7/7] domcreate: support pvusb in configuration file Chunyan Liu
  6 siblings, 0 replies; 88+ messages in thread
From: Chunyan Liu @ 2015-06-10  3:20 UTC (permalink / raw)
  To: xen-devel; +Cc: george.dunlap, wei.liu2, Ian.Jackson, ian.campbell, Chunyan Liu

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  | 24 ++++++++++++++++++++++++
 tools/libxl/xl_cmdtable.c |  4 ++++
 3 files changed, 29 insertions(+)

diff --git a/tools/libxl/xl.h b/tools/libxl/xl.h
index 2d57ee3..f37a99f 100644
--- a/tools/libxl/xl.h
+++ b/tools/libxl/xl.h
@@ -86,6 +86,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 b29d0fc..840faca 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -3239,6 +3239,30 @@ static void usbinfo_print(libxl_device_usb *usbs, int num) {
     }
 }
 
+static void usb_assignable_list(void)
+{
+    libxl_device_usb *usbs;
+    int num;
+
+    usbs = libxl_device_usb_assignable_list(ctx, &num);
+
+    usbinfo_print(usbs, num);
+
+    free(usbs);
+}
+
+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 f1c5b43..b6e8786 100644
--- a/tools/libxl/xl_cmdtable.c
+++ b/tools/libxl/xl_cmdtable.c
@@ -570,6 +570,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] 88+ messages in thread

* [PATCH V4 7/7] domcreate: support pvusb in configuration file
  2015-06-10  3:20 [PATCH V4 0/7] xen pvusb toolstack work Chunyan Liu
                   ` (5 preceding siblings ...)
  2015-06-10  3:20 ` [PATCH V4 6/7] xl: add usb-assignable-list command Chunyan Liu
@ 2015-06-10  3:20 ` Chunyan Liu
  6 siblings, 0 replies; 88+ messages in thread
From: Chunyan Liu @ 2015-06-10  3:20 UTC (permalink / raw)
  To: xen-devel
  Cc: wei.liu2, ian.campbell, george.dunlap, Ian.Jackson, Chunyan Liu,
	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>

---
Changes:
  - add DEFINE_DEVICES_ADD(usbctrl) and adjust codes to use that.
  - now support type='pv' in usbctrl specification, for future qemu
    extension.
  - use "usbdev" to specify pvusb device. Keep "usb" as its original usage.
  - extract codes to parse_usbctrl_config and parse_usb_config as George
    suggests

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

diff --git a/docs/man/xl.cfg.pod.5 b/docs/man/xl.cfg.pod.5
index a3e0e2e..0af1802 100644
--- a/docs/man/xl.cfg.pod.5
+++ b/docs/man/xl.cfg.pod.5
@@ -655,6 +655,81 @@ assigned slave device.
 
 =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 86384d2..f10bb7e 100644
--- a/tools/libxl/libxl_create.c
+++ b/tools/libxl/libxl_create.c
@@ -771,6 +771,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,
@@ -1418,13 +1422,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:
@@ -1432,6 +1436,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 i;
+    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;
+    }
+
+    for (i = 0; i < d_config->num_usbs; i++) {
+        ret = libxl__device_usb_add(gc, domid, &d_config->usbs[i], 0);
+        if (ret < 0) {
+            LOG(ERROR, "libxl__device_usb_add failed: %d", ret);
+            goto error_out;
+        }
+    }
+
+    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)
 {
@@ -1445,7 +1512,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 93bb41e..7bca841 100644
--- a/tools/libxl/libxl_device.c
+++ b/tools/libxl/libxl_device.c
@@ -544,6 +544,7 @@ void libxl__multidev_prepared(libxl__egc *egc,
  * libxl__add_disks
  * libxl__add_nics
  * libxl__add_vtpms
+ * libxl__add_usbctrls
  */
 
 #define DEFINE_DEVICES_ADD(type)                                        \
@@ -563,6 +564,7 @@ void libxl__multidev_prepared(libxl__egc *egc,
 DEFINE_DEVICES_ADD(disk)
 DEFINE_DEVICES_ADD(nic)
 DEFINE_DEVICES_ADD(vtpm)
+DEFINE_DEVICES_ADD(usbctrl)
 
 #undef DEFINE_DEVICES_ADD
 
diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
index 89a9f07..465aaaa 100644
--- a/tools/libxl/libxl_internal.h
+++ b/tools/libxl/libxl_internal.h
@@ -3076,6 +3076,10 @@ _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);
+
 /*----- device model creation -----*/
 
 /* First layer; wraps libxl__spawn_spawn. */
diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
index 840faca..1ff48a2 100644
--- a/tools/libxl/xl_cmdimpl.c
+++ b/tools/libxl/xl_cmdimpl.c
@@ -1160,6 +1160,79 @@ static void parse_vnuma_config(const XLU_Config *config,
     free(vcpu_range_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->protocol = LIBXL_USB_PROTOCOL_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->hostbus = strtoul(busaddr, NULL, 0);
+                usb->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,
@@ -1168,7 +1241,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;
@@ -1961,6 +2035,42 @@ 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;
+
+            d_config->usbctrls =
+                (libxl_device_usbctrl *) realloc(d_config->usbctrls,
+                sizeof (libxl_device_usbctrl) * (d_config->num_usbctrls + 1));
+            usbctrl = d_config->usbctrls + d_config->num_usbctrls;
+            libxl_device_usbctrl_init(usbctrl);
+
+            parse_usbctrl_config(usbctrl, buf);
+
+            d_config->num_usbctrls++;
+        }
+    }
+
+    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;
+
+            d_config->usbs = (libxl_device_usb *) realloc(d_config->usbs,
+                    sizeof (libxl_device_usb) * (d_config->num_usbs+1));
+            usb = d_config->usbs + d_config->num_usbs;
+            libxl_device_usb_init(usb);
+
+            parse_usb_config(usb, buf);
+
+            d_config->num_usbs++;
+        }
+    }
+
     switch (xlu_cfg_get_list(config, "cpuid", &cpuids, 0, 1)) {
     case 0:
         {
-- 
2.1.4

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-10  3:20 ` [PATCH V4 3/7] libxl: add pvusb API Chunyan Liu
@ 2015-06-11 15:00   ` Juergen Gross
  2015-06-11 16:07     ` Ian Jackson
  2015-06-11 16:42   ` Ian Jackson
                     ` (2 subsequent siblings)
  3 siblings, 1 reply; 88+ messages in thread
From: Juergen Gross @ 2015-06-11 15:00 UTC (permalink / raw)
  To: Chunyan Liu, xen-devel
  Cc: george.dunlap, Ian.Jackson, Simon Cao, wei.liu2, ian.campbell

On 06/10/2015 05:20 AM, Chunyan Liu wrote:
> Add pvusb APIs, including:
>   - attach/detach (create/destroy) virtual usb controller.
>   - attach/detach usb device
>   - list usb controller and usb devices
>   - some other helper functions
>
> Signed-off-by: Chunyan Liu <cyliu@suse.com>
> Signed-off-by: Simon Cao <caobosimon@gmail.com>

I've tested the patches with an old SUSE pvusb backend and my new one.

While all cases I tried worked with xm, the xl variant had some problems
with both backends, the new one being worse. I suspect especially this
patch to be faulty, as it has IMHO a potential structural problem: when
trying to attach a USB device without having created a usb-controller
for the domain, an asynchronous libxl-operation will itself call
another async operation.
The second async operation is being called with ao_how being NULL, but
I'm not sure whether this is allowed (libxl_internal.h comments are not
clear for me regarding such a scenario).

libxl_device_usb_add()
   AO_CREATE(ctx, domid, ao_how)
   libxl__device_usb_add()
     libxl__device_usb_setdefault()
       libxl_device_usbctrl_add_common()
         AO_CREATE(ctx, domid, NULL)

Tests with the new backend:

What I'm seeing is an error message that the controller couldn't be
assigned and the device would fail, too.

The real result, however, is an assigned controller, but no device.
Manual assignment of the device succeeds afterwards.

doing "xl usb-ctrl-attach" and then "xl usb-attach" is working, too.

Assigning a device via config file fails always (binding of device to
backend failed).


Tests with the old backend:

All tests but assigning a device via config file worked (again the
same binding error).


As I'm currently trying to write a new pvusb backend in qemu, I don't
want to investigate the xl problems with the new kernel backend. I
suspect some timing differences between old and new kernel drivers
leading to the different results.

As the qemu variant wouldn't need any driver rebinding in libxl (qemu
is handling this by itself) I wouldn't be worried too much about the
config file problem.

If, however, the nested usage of AO_CREATE is forbidden, this has to
be changed, of course.


Juergen

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-11 15:00   ` Juergen Gross
@ 2015-06-11 16:07     ` Ian Jackson
  0 siblings, 0 replies; 88+ messages in thread
From: Ian Jackson @ 2015-06-11 16:07 UTC (permalink / raw)
  To: Juergen Gross
  Cc: wei.liu2, ian.campbell, george.dunlap, Chunyan Liu, xen-devel, Simon Cao

Juergen Gross writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
> The second async operation is being called with ao_how being NULL, but
> I'm not sure whether this is allowed (libxl_internal.h comments are not
> clear for me regarding such a scenario).

It is not allowed.

I'll have a look through this series.

Ian.

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

* Re: [PATCH V4 1/7] libxl: export some functions for pvusb use
  2015-06-10  3:20 ` [PATCH V4 1/7] libxl: export some functions for pvusb use Chunyan Liu
@ 2015-06-11 16:08   ` Ian Jackson
  2015-06-11 16:28     ` Wei Liu
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Jackson @ 2015-06-11 16:08 UTC (permalink / raw)
  To: Chunyan Liu; +Cc: george.dunlap, Simon Cao, wei.liu2, ian.campbell, xen-devel

Chunyan Liu writes ("[Xen-devel] [PATCH V4 1/7] libxl: export some functions for pvusb use"):
> Signed-off-by: Chunyan Liu <cyliu@suse.com>
> Signed-off-by: Simon Cao <caobosimon@gmail.com>
> Acked-by: Wei Liu <wei.liu2@citrix.com>
...
>  /* generic callback for devices that only need to set ao_complete */
> -static void device_addrm_aocomplete(libxl__egc *egc, libxl__ao_device *aodev)
> +void device_addrm_aocomplete(libxl__egc *egc, libxl__ao_device *aodev)

Functions in libxl with external linkage should have the appropriate
namespacing (ie, their names must start with libxl__).

So, I'm afraid, contrary to Wei's opinion:

Nacked-by: Ian Jackson <ian.jackson@eu.citrix.com>

Ian.

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

* Re: [PATCH V4 2/7] libxl_read_file_contents: add new entry to read sysfs file
  2015-06-10  3:20 ` [PATCH V4 2/7] libxl_read_file_contents: add new entry to read sysfs file Chunyan Liu
@ 2015-06-11 16:16   ` Ian Jackson
  2015-06-12  7:00     ` Chun Yan Liu
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Jackson @ 2015-06-11 16:16 UTC (permalink / raw)
  To: Chunyan Liu; +Cc: george.dunlap, wei.liu2, ian.campbell, xen-devel

Chunyan Liu writes ("[Xen-devel] [PATCH V4 2/7] libxl_read_file_contents: add new entry to read sysfs file"):
> 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.

I think this patch is roughly right, but:

> -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 is_sysfs_file)

I would prefer a functional rather than contextual name for the
variabvle is_sysfs_file.  How about `tolerate_shrinking_file' ?

> @@ -360,15 +362,16 @@ int libxl_read_file_contents(libxl_ctx *ctx, const char *filename,
>  
>      if (stab.st_size && data_r) {
>          data = malloc(datalen);
> +        memset(data, 0, datalen);

What is this for ?

>          if (!data) goto xe;
>  
>          rs = fread(data, 1, datalen, f);
> -        if (rs != datalen) {
> +        if (rs != datalen && !(feof(f) && is_sysfs_file)) {
>              if (ferror(f))
>                  LOGE(ERROR, "failed to read %s", filename);
>              else if (feof(f))

I think it would be better to handle the special case here, with
something like
   if (!tolerate_shrinking_file)
       error stuff
   else {
       assert(datalen_r);
and to move the `goto xe' into the individual branches.


Is there any risk that the file is actually bigger than advertised,
rather than smaller ?

> diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h
> index 1c1761d..7639662 100644
> --- a/tools/libxl/libxl_utils.h
> +++ b/tools/libxl/libxl_utils.h
...
> +int libxl_read_sysfs_file_contents(libxl_ctx *ctx, const char *filename,
> +                                   void **data_r, int *datalen_r);

I think this is a function with sufficiently odd semantics, and a
sufficiently internal purpose, that it should probably not be exposed
in the API.

Ian.

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

* Re: [PATCH V4 1/7] libxl: export some functions for pvusb use
  2015-06-11 16:08   ` Ian Jackson
@ 2015-06-11 16:28     ` Wei Liu
  2015-06-12 15:14       ` Ian Jackson
  0 siblings, 1 reply; 88+ messages in thread
From: Wei Liu @ 2015-06-11 16:28 UTC (permalink / raw)
  To: Ian Jackson
  Cc: wei.liu2, ian.campbell, george.dunlap, Chunyan Liu, xen-devel, Simon Cao

On Thu, Jun 11, 2015 at 05:08:57PM +0100, Ian Jackson wrote:
> Chunyan Liu writes ("[Xen-devel] [PATCH V4 1/7] libxl: export some functions for pvusb use"):
> > Signed-off-by: Chunyan Liu <cyliu@suse.com>
> > Signed-off-by: Simon Cao <caobosimon@gmail.com>
> > Acked-by: Wei Liu <wei.liu2@citrix.com>
> ...
> >  /* generic callback for devices that only need to set ao_complete */
> > -static void device_addrm_aocomplete(libxl__egc *egc, libxl__ao_device *aodev)
> > +void device_addrm_aocomplete(libxl__egc *egc, libxl__ao_device *aodev)
> 
> Functions in libxl with external linkage should have the appropriate
> namespacing (ie, their names must start with libxl__).
> 
> So, I'm afraid, contrary to Wei's opinion:
> 
> Nacked-by: Ian Jackson <ian.jackson@eu.citrix.com>
> 

I think if Chunyan moves that function to libxl__ namespace this patch
should be fine, right?

Wei.

> Ian.

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-10  3:20 ` [PATCH V4 3/7] libxl: add pvusb API Chunyan Liu
  2015-06-11 15:00   ` Juergen Gross
@ 2015-06-11 16:42   ` Ian Jackson
  2015-06-12  7:39     ` Chun Yan Liu
  2015-06-15 14:17   ` George Dunlap
  2015-06-15 17:47   ` George Dunlap
  3 siblings, 1 reply; 88+ messages in thread
From: Ian Jackson @ 2015-06-11 16:42 UTC (permalink / raw)
  To: Chunyan Liu; +Cc: george.dunlap, Simon Cao, wei.liu2, ian.campbell, xen-devel

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

Thanks for your contribution.  I'm afraid I haven't had time to
completely finish my review this, but here's what I have:

> --- /dev/null
> +++ b/docs/misc/pvusb.txt
> @@ -0,0 +1,243 @@
> +1. Overview

It's good that you have provided documentation.  But I think this
document is a bit confused about its audience.

Information about design choices should be removed from this user- and
application-facing document, and put in comments in the code, or
commit messages, I think.


> +int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid,
> +                                libxl_device_usbctrl *usbctrl,
> +                                libxl_usbctrlinfo *usbctrlinfo)
> +                                LIBXL_EXTERNAL_CALLERS_ONLY;

Why is this function marked LIBXL_EXTERNAL_CALLERS_ONLY ?

> diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h
> index ef7aa1d..89a9f07 100644
> --- a/tools/libxl/libxl_internal.h
> +++ b/tools/libxl/libxl_internal.h
> @@ -2439,6 +2439,18 @@ _hidden void libxl__device_vtpm_add(libxl__egc *egc, uint32_t domid,
...
> +/* AO operation to connect a PVUSB controller.
> + * Adding a PVUSB controller will add a 'vusb' device entry in xenstore,
> + * and will wait for device connection.

In this context I think "will wait for device connection" is
misleading.  What you mean is that the vusb is available for adding
devices to, but won't have any yet.  Nothing in libxl is "waiting".

> diff --git a/tools/libxl/libxl_pvusb.c b/tools/libxl/libxl_pvusb.c
> new file mode 100644
> index 0000000..a6e1aa1
> --- /dev/null
> +++ b/tools/libxl/libxl_pvusb.c
> @@ -0,0 +1,1249 @@
...
> +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_domain_config_init(&d_config);
> +    libxl_device_usbctrl_init(&usbctrl_saved);
> +    libxl_device_usbctrl_copy(CTX, &usbctrl_saved, usbctrl);

Wei will need to review the saved/live saved device info handling, and
the json, etc.

> +static int
> +libxl_device_usbctrl_remove_common(libxl_ctx *ctx, uint32_t domid,
> +                                   libxl_device_usbctrl *usbctrl,
> +                                   const libxl_asyncop_how *ao_how,
> +                                   int force)

As discussed, you mustn't call this within libxl.  If you need to, you
need to break it out into an internal function
(libxl__initiate_device_usbctrl_remove, maybe) which makes a callback
when done.

> +libxl_device_usbctrl *
> +libxl_device_usbctrl_list(libxl_ctx *ctx, uint32_t domid, int *num)
> +{
> +    GC_INIT(ctx);
> +    libxl_device_usbctrl *usbctrls = NULL;
> +    char *fe_path = NULL;
> +    char **dir = NULL;
> +    unsigned int ndirs = 0;
> +
> +    *num = 0;
> +
> +    fe_path = GCSPRINTF("%s/device/vusb",
> +                        libxl__xs_get_dompath(gc, domid));
> +    dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);
> +
> +    if (dir && ndirs) {
> +        usbctrls = malloc(sizeof(*usbctrls) * ndirs);

Please use libxl__calloc with NOGC.

> +        libxl_device_usbctrl* usbctrl;
> +        libxl_device_usbctrl* end = usbctrls + ndirs;
> +        for (usbctrl = usbctrls; usbctrl < end; usbctrl++, dir++, (*num)++) {
> +            char *tmp;
> +            const char *be_path = libxl__xs_read(gc, XBT_NULL,
> +                                    GCSPRINTF("%s/%s/backend", fe_path, *dir));
> +
> +            libxl_device_usbctrl_init(usbctrl);
> +            usbctrl->devid = atoi(*dir);

This function (and the corresponding writing code) is quite formulaic.
Perhaps a macro or something could be used.

I would make a similar criticism of libxl_device_usbctrl_getinfo.

> +/* check if USB device is already assigned to a domain */
> +static bool is_usb_assigned(libxl__gc *gc, libxl_device_usb *usb)
> +{
> +    libxl_device_usb *usbs;
> +    int rc, num;
> +
> +    rc = libxl__device_usb_assigned_list(gc, &usbs, &num);
> +    if (rc) {
> +        LOG(ERROR, "Fail to get assigned usb list");
> +        return true;

I don't think this is proper error handling.  You need to either
encode the boolean return value in the error code, or have the boolean
result be a reference parameter.


Thanks,
Ian.

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

* Re: [PATCH V4 2/7] libxl_read_file_contents: add new entry to read sysfs file
  2015-06-11 16:16   ` Ian Jackson
@ 2015-06-12  7:00     ` Chun Yan Liu
  2015-06-12 15:11       ` Ian Jackson
  0 siblings, 1 reply; 88+ messages in thread
From: Chun Yan Liu @ 2015-06-12  7:00 UTC (permalink / raw)
  To: Ian Jackson; +Cc: george.dunlap, wei.liu2, ian.campbell, xen-devel



>>> On 6/12/2015 at 12:16 AM, in message
<21881.46148.466883.923039@mariner.uk.xensource.com>, Ian Jackson
<Ian.Jackson@eu.citrix.com> wrote: 
> Chunyan Liu writes ("[Xen-devel] [PATCH V4 2/7] libxl_read_file_contents: add  
> new entry to read sysfs file"): 
> > 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. 
>  
> I think this patch is roughly right, but: 
>  
> > -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 is_sysfs_file) 
>  
> I would prefer a functional rather than contextual name for the 
> variabvle is_sysfs_file.  How about `tolerate_shrinking_file' ? 

OK.

>  
> > @@ -360,15 +362,16 @@ int libxl_read_file_contents(libxl_ctx *ctx, const  
> char *filename, 
> >   
> >      if (stab.st_size && data_r) { 
> >          data = malloc(datalen); 
> > +        memset(data, 0, datalen); 
>  
> What is this for ? 

I found sometimes reading sysfs file contents, at the end, there is
some random character. With this line, there is no problem then.

>  
> >          if (!data) goto xe; 
> >   
> >          rs = fread(data, 1, datalen, f); 
> > -        if (rs != datalen) { 
> > +        if (rs != datalen && !(feof(f) && is_sysfs_file)) { 
> >              if (ferror(f)) 
> >                  LOGE(ERROR, "failed to read %s", filename); 
> >              else if (feof(f)) 
>  
> I think it would be better to handle the special case here, with 
> something like 
>    if (!tolerate_shrinking_file) 
>        error stuff 
>    else { 
>        assert(datalen_r); 
> and to move the `goto xe' into the individual branches. 

OK. Will update.

>  
>  
> Is there any risk that the file is actually bigger than advertised, 
> rather than smaller ? 

For sysfs file, couldn't be bigger.

>  
> > diff --git a/tools/libxl/libxl_utils.h b/tools/libxl/libxl_utils.h 
> > index 1c1761d..7639662 100644 
> > --- a/tools/libxl/libxl_utils.h 
> > +++ b/tools/libxl/libxl_utils.h 
> ... 
> > +int libxl_read_sysfs_file_contents(libxl_ctx *ctx, const char *filename, 
> > +                                   void **data_r, int *datalen_r); 
>  
> I think this is a function with sufficiently odd semantics, and a 
> sufficiently internal purpose, that it should probably not be exposed 
> in the API. 

So move to libxl_internal.h? Or not hacking here but just adding an internal
function in libxl_pvusb.c with repeated codes?

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

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

* Re: [PATCH V4 5/7] xl: add pvusb commands
  2015-06-10  3:20 ` [PATCH V4 5/7] xl: add pvusb commands Chunyan Liu
@ 2015-06-12  7:37   ` Juergen Gross
  2015-06-12  8:03     ` Chun Yan Liu
  0 siblings, 1 reply; 88+ messages in thread
From: Juergen Gross @ 2015-06-12  7:37 UTC (permalink / raw)
  To: Chunyan Liu, xen-devel
  Cc: george.dunlap, Ian.Jackson, Simon Cao, wei.liu2, ian.campbell

On 06/10/2015 05:20 AM, 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
>
>   #xl usb-list test_vm
>   will show the usb controllers and port usage under the domain.
>
>   #xl usb-assignable-list
>   will list assignable USB devices

xl usb-assignable-list is not part of this patch. Either merge this
patch and the following one, or describe the command in the next patch.

>
>   #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 1.6
>
>   #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         |  38 +++++++
>   tools/libxl/xl.h          |   5 +
>   tools/libxl/xl_cmdimpl.c  | 251 ++++++++++++++++++++++++++++++++++++++++++++++
>   tools/libxl/xl_cmdtable.c |  25 +++++
>   4 files changed, 319 insertions(+)
>

...

> diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c
> index c858068..b29d0fc 100644
> --- a/tools/libxl/xl_cmdimpl.c
> +++ b/tools/libxl/xl_cmdimpl.c
> @@ -3219,6 +3219,257 @@ int main_cd_insert(int argc, char **argv)
>       return 0;
>   }
>
> +static void usbinfo_print(libxl_device_usb *usbs, int num) {
> +    int i;

Blank line missing.

> +    if (usbs == NULL)
> +         return;
> +    for (i = 0; i < num; i++) {
> +        libxl_usbinfo usbinfo;

Blank line missing.

> +        libxl_usbinfo_init(&usbinfo);
> +
> +        if (usbs[i].port)
> +            printf("  Port %d:", usbs[i].port);
> +        if (!libxl_device_usb_getinfo(ctx, &usbs[i], &usbinfo)) {
> +            printf(" Bus %03x Device %03x: ID %04x:%04x %s %s\n",
> +                    usbinfo.busnum, usbinfo.devnum,
> +                    usbinfo.idVendor, usbinfo.idProduct,
> +                    usbinfo.manuf ?: "", usbinfo.prod ?: "");

Is it really possible for a device to be assigned but without a port
number?

I'd rather combine the two if's and printf statements. This would avoid
the case where "  Port 1: Port 2: ..." is printed due to a failing
libxl_device_usb_getinfo() for port 1.

> +        }
> +        libxl_usbinfo_dispose(&usbinfo);
> +    }
> +}
> +
> +int main_usbctrl_attach(int argc, char **argv)
> +{
> +    uint32_t domid;
> +    int opt;
> +    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.protocol = LIBXL_USB_PROTOCOL_PV;
> +            } else {
> +               fprintf(stderr, "unsupported type `%s'\n", oparg);
> +               exit(-1);
> +            }
> +        } else if (MATCH_OPTION("version", argv[optind], oparg)) {
> +            usbctrl.version = atoi(oparg);

Shouldn't you check for valid versions?

> +        } else if (MATCH_OPTION("ports", argv[optind], oparg)) {
> +            usbctrl.ports = atoi(oparg);

Same here for number of ports. Otherwise you could blow up xenstore by
e.g. specifying 2 billion ports here.

> +        } else {
> +            fprintf(stderr, "unrecognized argument `%s'\n", argv[optind]);
> +            exit(-1);
> +        }
> +        optind++;
> +    }
> +
> +    if (usbctrl.protocol == LIBXL_USB_PROTOCOL_AUTO)
> +        usbctrl.protocol = LIBXL_USB_PROTOCOL_PV;

Is this really necessary? You do it in libxl, too.


Juergen

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-11 16:42   ` Ian Jackson
@ 2015-06-12  7:39     ` Chun Yan Liu
  2015-06-12  8:06       ` Chun Yan Liu
  2015-06-12 11:22       ` Ian Jackson
  0 siblings, 2 replies; 88+ messages in thread
From: Chun Yan Liu @ 2015-06-12  7:39 UTC (permalink / raw)
  To: Ian Jackson; +Cc: george.dunlap, Simon Cao, wei.liu2, ian.campbell, xen-devel



>>> On 6/12/2015 at 12:42 AM, in message
<21881.47707.526863.158586@mariner.uk.xensource.com>, Ian Jackson
<Ian.Jackson@eu.citrix.com> wrote: 
> Chunyan Liu writes ("[Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"): 
> > Add pvusb APIs, including: 
> ... 
>  
> Thanks for your contribution.  I'm afraid I haven't had time to 
> completely finish my review this, but here's what I have: 
>  
> > --- /dev/null 
> > +++ b/docs/misc/pvusb.txt 
> > @@ -0,0 +1,243 @@ 
> > +1. Overview 
>  
> It's good that you have provided documentation.  But I think this 
> document is a bit confused about its audience. 
>  
> Information about design choices should be removed from this user- and 
> application-facing document, and put in comments in the code, or 
> commit messages, I think. 

Thanks. Will update.

>  
>  
> > +int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid, 
> > +                                libxl_device_usbctrl *usbctrl, 
> > +                                libxl_usbctrlinfo *usbctrlinfo) 
> > +                                LIBXL_EXTERNAL_CALLERS_ONLY; 
>  
> Why is this function marked LIBXL_EXTERNAL_CALLERS_ONLY ? 

Currently libxl itself won't call it. Exposed for toolstack usage. Will
remove that if it's not proper.

>  
> > diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h 
> > index ef7aa1d..89a9f07 100644 
> > --- a/tools/libxl/libxl_internal.h 
> > +++ b/tools/libxl/libxl_internal.h 
> > @@ -2439,6 +2439,18 @@ _hidden void libxl__device_vtpm_add(libxl__egc *egc,  
> uint32_t domid, 
> ... 
> > +/* AO operation to connect a PVUSB controller. 
> > + * Adding a PVUSB controller will add a 'vusb' device entry in xenstore, 
> > + * and will wait for device connection. 
>  
> In this context I think "will wait for device connection" is 
> misleading.  What you mean is that the vusb is available for adding 
> devices to, but won't have any yet.  Nothing in libxl is "waiting". 

Here I mean libxl_wait_for_device_connection. Since it adds a new device entry
to xenstore, it needs to wait for a moment for frontend/backend connection.

>  
> > diff --git a/tools/libxl/libxl_pvusb.c b/tools/libxl/libxl_pvusb.c 
> > new file mode 100644 
> > index 0000000..a6e1aa1 
> > --- /dev/null 
> > +++ b/tools/libxl/libxl_pvusb.c 
> > @@ -0,0 +1,1249 @@ 
> ... 
> > +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_domain_config_init(&d_config); 
> > +    libxl_device_usbctrl_init(&usbctrl_saved); 
> > +    libxl_device_usbctrl_copy(CTX, &usbctrl_saved, usbctrl); 
>  
> Wei will need to review the saved/live saved device info handling, and 
> the json, etc. 
>  
> > +static int 
> > +libxl_device_usbctrl_remove_common(libxl_ctx *ctx, uint32_t domid, 
> > +                                   libxl_device_usbctrl *usbctrl, 
> > +                                   const libxl_asyncop_how *ao_how, 
> > +                                   int force) 
>  
> As discussed, you mustn't call this within libxl.
I don't quite understand why. I guess it's the same as usb_add problem,
something related to embedded ao?
As in usb_add:
libxl_device_usb_add()
   AO_CREATE(ctx, domid, ao_how)
   libxl__device_usb_add()
     libxl__device_usb_setdefault()
       libxl_device_usbctrl_add_common()
         AO_CREATE(ctx, domid, NULL)
if this is not allowed, what is the correct way?

> If you need to, you 
> need to break it out into an internal function 
> (libxl__initiate_device_usbctrl_remove, maybe) which makes a callback 
> when done.
>  
> > +libxl_device_usbctrl * 
> > +libxl_device_usbctrl_list(libxl_ctx *ctx, uint32_t domid, int *num) 
> > +{ 
> > +    GC_INIT(ctx); 
> > +    libxl_device_usbctrl *usbctrls = NULL; 
> > +    char *fe_path = NULL; 
> > +    char **dir = NULL; 
> > +    unsigned int ndirs = 0; 
> > + 
> > +    *num = 0; 
> > + 
> > +    fe_path = GCSPRINTF("%s/device/vusb", 
> > +                        libxl__xs_get_dompath(gc, domid)); 
> > +    dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs); 
> > + 
> > +    if (dir && ndirs) { 
> > +        usbctrls = malloc(sizeof(*usbctrls) * ndirs); 
>  
> Please use libxl__calloc with NOGC. 

Thanks. Missing this one.

>  
> > +        libxl_device_usbctrl* usbctrl; 
> > +        libxl_device_usbctrl* end = usbctrls + ndirs; 
> > +        for (usbctrl = usbctrls; usbctrl < end; usbctrl++, dir++, (*num)++)  
> { 
> > +            char *tmp; 
> > +            const char *be_path = libxl__xs_read(gc, XBT_NULL, 
> > +                                    GCSPRINTF("%s/%s/backend", fe_path,  
> *dir)); 
> > + 
> > +            libxl_device_usbctrl_init(usbctrl); 
> > +            usbctrl->devid = atoi(*dir); 
>  
> This function (and the corresponding writing code) is quite formulaic. 
> Perhaps a macro or something could be used. 
>  
> I would make a similar criticism of libxl_device_usbctrl_getinfo. 
>  
> > +/* check if USB device is already assigned to a domain */ 
> > +static bool is_usb_assigned(libxl__gc *gc, libxl_device_usb *usb) 
> > +{ 
> > +    libxl_device_usb *usbs; 
> > +    int rc, num; 
> > + 
> > +    rc = libxl__device_usb_assigned_list(gc, &usbs, &num); 
> > +    if (rc) { 
> > +        LOG(ERROR, "Fail to get assigned usb list"); 
> > +        return true; 
>  
> I don't think this is proper error handling.  You need to either 
> encode the boolean return value in the error code, or have the boolean 
> result be a reference parameter. 

Will improve that.

Thanks,
Chunyan

>  
>  
> Thanks, 
> Ian. 
>  
> _______________________________________________ 
> Xen-devel mailing list 
> Xen-devel@lists.xen.org 
> http://lists.xen.org/xen-devel 
>  
>  

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

* Re: [PATCH V4 5/7] xl: add pvusb commands
  2015-06-12  7:37   ` Juergen Gross
@ 2015-06-12  8:03     ` Chun Yan Liu
  2015-06-12  8:22       ` Juergen Gross
  0 siblings, 1 reply; 88+ messages in thread
From: Chun Yan Liu @ 2015-06-12  8:03 UTC (permalink / raw)
  To: xen-devel, Juergen Gross
  Cc: george.dunlap, Ian.Jackson, Simon Cao, wei.liu2, ian.campbell



>>> On 6/12/2015 at 03:37 PM, in message <557A8C57.1040108@suse.com>, Juergen Gross
<jgross@suse.com> wrote: 
> On 06/10/2015 05:20 AM, 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 
> > 
> >   #xl usb-list test_vm 
> >   will show the usb controllers and port usage under the domain. 
> > 
> >   #xl usb-assignable-list 
> >   will list assignable USB devices 
>  
> xl usb-assignable-list is not part of this patch. Either merge this 
> patch and the following one, or describe the command in the next patch. 

Oh, yes, I forget to split.

>  
> > 
> >   #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 1.6 
> > 
> >   #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         |  38 +++++++ 
> >   tools/libxl/xl.h          |   5 + 
> >   tools/libxl/xl_cmdimpl.c  | 251  
> ++++++++++++++++++++++++++++++++++++++++++++++ 
> >   tools/libxl/xl_cmdtable.c |  25 +++++ 
> >   4 files changed, 319 insertions(+) 
> > 
>  
> ... 
>  
> > diff --git a/tools/libxl/xl_cmdimpl.c b/tools/libxl/xl_cmdimpl.c 
> > index c858068..b29d0fc 100644 
> > --- a/tools/libxl/xl_cmdimpl.c 
> > +++ b/tools/libxl/xl_cmdimpl.c 
> > @@ -3219,6 +3219,257 @@ int main_cd_insert(int argc, char **argv) 
> >       return 0; 
> >   } 
> > 
> > +static void usbinfo_print(libxl_device_usb *usbs, int num) { 
> > +    int i; 
>  
> Blank line missing. 
>  
> > +    if (usbs == NULL) 
> > +         return; 
> > +    for (i = 0; i < num; i++) { 
> > +        libxl_usbinfo usbinfo; 
>  
> Blank line missing. 
>  
> > +        libxl_usbinfo_init(&usbinfo); 
> > + 
> > +        if (usbs[i].port) 
> > +            printf("  Port %d:", usbs[i].port); 
> > +        if (!libxl_device_usb_getinfo(ctx, &usbs[i], &usbinfo)) { 
> > +            printf(" Bus %03x Device %03x: ID %04x:%04x %s %s\n", 
> > +                    usbinfo.busnum, usbinfo.devnum, 
> > +                    usbinfo.idVendor, usbinfo.idProduct, 
> > +                    usbinfo.manuf ?: "", usbinfo.prod ?: ""); 
>  
> Is it really possible for a device to be assigned but without a port 
> number? 

For assigned usb device, it's not possible. But this function will be called
in two places, one is to list assigned usb devices in 'xl usb-list'; another
is to list assignable usb devices in 'xl usb-assignable-list'. If
'usb-assignable-list' is not taken, this could be improved.

>  
> I'd rather combine the two if's and printf statements. This would avoid 
> the case where "  Port 1: Port 2: ..." is printed due to a failing 
> libxl_device_usb_getinfo() for port 1. 
>  
> > +        } 
> > +        libxl_usbinfo_dispose(&usbinfo); 
> > +    } 
> > +} 
> > + 
> > +int main_usbctrl_attach(int argc, char **argv) 
> > +{ 
> > +    uint32_t domid; 
> > +    int opt; 
> > +    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.protocol = LIBXL_USB_PROTOCOL_PV; 
> > +            } else { 
> > +               fprintf(stderr, "unsupported type `%s'\n", oparg); 
> > +               exit(-1); 
> > +            } 
> > +        } else if (MATCH_OPTION("version", argv[optind], oparg)) { 
> > +            usbctrl.version = atoi(oparg); 
>  
> Shouldn't you check for valid versions? 

OK. Will check.

>  
> > +        } else if (MATCH_OPTION("ports", argv[optind], oparg)) { 
> > +            usbctrl.ports = atoi(oparg); 
>  
> Same here for number of ports. Otherwise you could blow up xenstore by 
> e.g. specifying 2 billion ports here. 

Will add check. What's the supported max ports? 

>  
> > +        } else { 
> > +            fprintf(stderr, "unrecognized argument `%s'\n", argv[optind]); 
> > +            exit(-1); 
> > +        } 
> > +        optind++; 
> > +    } 
> > + 
> > +    if (usbctrl.protocol == LIBXL_USB_PROTOCOL_AUTO) 
> > +        usbctrl.protocol = LIBXL_USB_PROTOCOL_PV; 
>  
> Is this really necessary? You do it in libxl, too. 
Yes, seems not necessary. Anyway (from config file or hotplug), it will
call libxl_device_usbctrl_setdefault and do that.

Thanks,
Chunyan
>  
>  
> Juergen 
>  
> _______________________________________________ 
> Xen-devel mailing list 
> Xen-devel@lists.xen.org 
> http://lists.xen.org/xen-devel 
>  
>  

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-12  7:39     ` Chun Yan Liu
@ 2015-06-12  8:06       ` Chun Yan Liu
  2015-06-12 11:22       ` Ian Jackson
  1 sibling, 0 replies; 88+ messages in thread
From: Chun Yan Liu @ 2015-06-12  8:06 UTC (permalink / raw)
  To: Ian Jackson, Chun Yan Liu
  Cc: george.dunlap, Simon Cao, wei.liu2, ian.campbell, xen-devel



>>> On 6/12/2015 at 03:39 PM, in message
<557AFD2F02000066000D4C7D@relay2.provo.novell.com>, "Chun Yan Liu"
<cyliu@suse.com> wrote: 

>  
>>>> On 6/12/2015 at 12:42 AM, in message 
> <21881.47707.526863.158586@mariner.uk.xensource.com>, Ian Jackson 
> <Ian.Jackson@eu.citrix.com> wrote:  
> > Chunyan Liu writes ("[Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):  
> > > Add pvusb APIs, including:  
> > ...  
> >   
> > Thanks for your contribution.  I'm afraid I haven't had time to  
> > completely finish my review this, but here's what I have:  
> >   
> > > --- /dev/null  
> > > +++ b/docs/misc/pvusb.txt  
> > > @@ -0,0 +1,243 @@  
> > > +1. Overview  
> >   
> > It's good that you have provided documentation.  But I think this  
> > document is a bit confused about its audience.  
> >   
> > Information about design choices should be removed from this user- and  
> > application-facing document, and put in comments in the code, or  
> > commit messages, I think.  
>  
> Thanks. Will update. 
>  
> >   
> >   
> > > +int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid,  
> > > +                                libxl_device_usbctrl *usbctrl,  
> > > +                                libxl_usbctrlinfo *usbctrlinfo)  
> > > +                                LIBXL_EXTERNAL_CALLERS_ONLY;  
> >   
> > Why is this function marked LIBXL_EXTERNAL_CALLERS_ONLY ?  
>  
> Currently libxl itself won't call it. Exposed for toolstack usage. Will 
> remove that if it's not proper. 
>  
> >   
> > > diff --git a/tools/libxl/libxl_internal.h b/tools/libxl/libxl_internal.h  
> > > index ef7aa1d..89a9f07 100644  
> > > --- a/tools/libxl/libxl_internal.h  
> > > +++ b/tools/libxl/libxl_internal.h  
> > > @@ -2439,6 +2439,18 @@ _hidden void libxl__device_vtpm_add(libxl__egc *egc,  
>   
> > uint32_t domid,  
> > ...  
> > > +/* AO operation to connect a PVUSB controller.  
> > > + * Adding a PVUSB controller will add a 'vusb' device entry in xenstore,  
> > > + * and will wait for device connection.  
> >   
> > In this context I think "will wait for device connection" is  
> > misleading.  What you mean is that the vusb is available for adding  
> > devices to, but won't have any yet.  Nothing in libxl is "waiting".  
>  
> Here I mean libxl_wait_for_device_connection. Since it adds a new device  
> entry 
> to xenstore, it needs to wait for a moment for frontend/backend connection. 
>  
> >   
> > > diff --git a/tools/libxl/libxl_pvusb.c b/tools/libxl/libxl_pvusb.c  
> > > new file mode 100644  
> > > index 0000000..a6e1aa1  
> > > --- /dev/null  
> > > +++ b/tools/libxl/libxl_pvusb.c  
> > > @@ -0,0 +1,1249 @@  
> > ...  
> > > +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_domain_config_init(&d_config);  
> > > +    libxl_device_usbctrl_init(&usbctrl_saved);  
> > > +    libxl_device_usbctrl_copy(CTX, &usbctrl_saved, usbctrl);  
> >   
> > Wei will need to review the saved/live saved device info handling, and  
> > the json, etc.  
> >   
> > > +static int  
> > > +libxl_device_usbctrl_remove_common(libxl_ctx *ctx, uint32_t domid,  
> > > +                                   libxl_device_usbctrl *usbctrl,  
> > > +                                   const libxl_asyncop_how *ao_how,  
> > > +                                   int force)  
> >   
> > As discussed, you mustn't call this within libxl. 
> I don't quite understand why. I guess it's the same as usb_add problem, 
> something related to embedded ao? 
> As in usb_add: 
> libxl_device_usb_add() 
>    AO_CREATE(ctx, domid, ao_how) 
>    libxl__device_usb_add() 
>      libxl__device_usb_setdefault() 
>        libxl_device_usbctrl_add_common() 
>          AO_CREATE(ctx, domid, NULL) 
> if this is not allowed, what is the correct way? 

Saw the discussion thread and got it. Will update the codes.

>  
> > If you need to, you  
> > need to break it out into an internal function  
> > (libxl__initiate_device_usbctrl_remove, maybe) which makes a callback  
> > when done. 
> >   
> > > +libxl_device_usbctrl *  
> > > +libxl_device_usbctrl_list(libxl_ctx *ctx, uint32_t domid, int *num)  
> > > +{  
> > > +    GC_INIT(ctx);  
> > > +    libxl_device_usbctrl *usbctrls = NULL;  
> > > +    char *fe_path = NULL;  
> > > +    char **dir = NULL;  
> > > +    unsigned int ndirs = 0;  
> > > +  
> > > +    *num = 0;  
> > > +  
> > > +    fe_path = GCSPRINTF("%s/device/vusb",  
> > > +                        libxl__xs_get_dompath(gc, domid));  
> > > +    dir = libxl__xs_directory(gc, XBT_NULL, fe_path, &ndirs);  
> > > +  
> > > +    if (dir && ndirs) {  
> > > +        usbctrls = malloc(sizeof(*usbctrls) * ndirs);  
> >   
> > Please use libxl__calloc with NOGC.  
>  
> Thanks. Missing this one. 
>  
> >   
> > > +        libxl_device_usbctrl* usbctrl;  
> > > +        libxl_device_usbctrl* end = usbctrls + ndirs;  
> > > +        for (usbctrl = usbctrls; usbctrl < end; usbctrl++, dir++,  
> (*num)++)   
> > {  
> > > +            char *tmp;  
> > > +            const char *be_path = libxl__xs_read(gc, XBT_NULL,  
> > > +                                    GCSPRINTF("%s/%s/backend", fe_path,   
> > *dir));  
> > > +  
> > > +            libxl_device_usbctrl_init(usbctrl);  
> > > +            usbctrl->devid = atoi(*dir);  
> >   
> > This function (and the corresponding writing code) is quite formulaic.  
> > Perhaps a macro or something could be used.  
> >   
> > I would make a similar criticism of libxl_device_usbctrl_getinfo.  
> >   
> > > +/* check if USB device is already assigned to a domain */  
> > > +static bool is_usb_assigned(libxl__gc *gc, libxl_device_usb *usb)  
> > > +{  
> > > +    libxl_device_usb *usbs;  
> > > +    int rc, num;  
> > > +  
> > > +    rc = libxl__device_usb_assigned_list(gc, &usbs, &num);  
> > > +    if (rc) {  
> > > +        LOG(ERROR, "Fail to get assigned usb list");  
> > > +        return true;  
> >   
> > I don't think this is proper error handling.  You need to either  
> > encode the boolean return value in the error code, or have the boolean  
> > result be a reference parameter.  
>  
> Will improve that. 
>  
> Thanks, 
> Chunyan 
>  
> >   
> >   
> > Thanks,  
> > Ian.  
> >   
> > _______________________________________________  
> > Xen-devel mailing list  
> > Xen-devel@lists.xen.org  
> > http://lists.xen.org/xen-devel  
> >   
> >   
>  
>  
> _______________________________________________ 
> Xen-devel mailing list 
> Xen-devel@lists.xen.org 
> http://lists.xen.org/xen-devel 
>  
>  

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

* Re: [PATCH V4 5/7] xl: add pvusb commands
  2015-06-12  8:03     ` Chun Yan Liu
@ 2015-06-12  8:22       ` Juergen Gross
  0 siblings, 0 replies; 88+ messages in thread
From: Juergen Gross @ 2015-06-12  8:22 UTC (permalink / raw)
  To: Chun Yan Liu, xen-devel
  Cc: george.dunlap, wei.liu2, Simon Cao, Ian.Jackson, ian.campbell

On 06/12/2015 10:03 AM, Chun Yan Liu wrote:
>
>
>>>> On 6/12/2015 at 03:37 PM, in message <557A8C57.1040108@suse.com>, Juergen Gross
> <jgross@suse.com> wrote:
>> On 06/10/2015 05:20 AM, Chunyan Liu wrote:

...

>>> +        } else if (MATCH_OPTION("ports", argv[optind], oparg)) {
>>> +            usbctrl.ports = atoi(oparg);
>>
>> Same here for number of ports. Otherwise you could blow up xenstore by
>> e.g. specifying 2 billion ports here.
>
> Will add check. What's the supported max ports?

31. I'm about to send a patch updating the pvusb interface description
which will then contain a define for that (USBIF_MAX_PORTNR).


Juergen

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-12  7:39     ` Chun Yan Liu
  2015-06-12  8:06       ` Chun Yan Liu
@ 2015-06-12 11:22       ` Ian Jackson
  1 sibling, 0 replies; 88+ messages in thread
From: Ian Jackson @ 2015-06-12 11:22 UTC (permalink / raw)
  To: Chun Yan Liu; +Cc: george.dunlap, Simon Cao, wei.liu2, ian.campbell, xen-devel

Chun Yan Liu writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
> <21881.47707.526863.158586@mariner.uk.xensource.com>, Ian Jackson
> <Ian.Jackson@eu.citrix.com> wrote: 
> > Chunyan Liu writes ("[Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"): 

> > > +int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid, 
> > > +                                libxl_device_usbctrl *usbctrl, 
> > > +                                libxl_usbctrlinfo *usbctrlinfo) 
> > > +                                LIBXL_EXTERNAL_CALLERS_ONLY; 
> >  
> > Why is this function marked LIBXL_EXTERNAL_CALLERS_ONLY ? 
> 
> Currently libxl itself won't call it. Exposed for toolstack usage. Will
> remove that if it's not proper.

LIBXL_EXTERNAL_CALLERS_ONLY is a special macro which _prevents_ anyone
from adding calls to the function from inside libxl.  It should be
used where adding such an internal caller would be a mistake, not
simply where there happen not to be any internal callers right now.

> > > +/* AO operation to connect a PVUSB controller. 
> > > + * Adding a PVUSB controller will add a 'vusb' device entry in xenstore, 
> > > + * and will wait for device connection. 
> >  
> > In this context I think "will wait for device connection" is 
> > misleading.  What you mean is that the vusb is available for adding 
> > devices to, but won't have any yet.  Nothing in libxl is "waiting". 
> 
> Here I mean libxl_wait_for_device_connection. Since it adds a new
> device entry to xenstore, it needs to wait for a moment for
> frontend/backend connection.

Oh, I see.  I don't think you should mention that here.  That part of
the implementation, not the interface.

AFAICT libxl__device_usbctrl_add works just like all the other
libxl__device_*_add functions, in that it adds the device and when
completed it calls aodev->callback.  There is no need to mention this
explicitly in a comment - indeed, mentioning it for this device type
but not for others would lead the reader to wonder what was different.

Thanks,
Ian.

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

* Re: [PATCH V4 2/7] libxl_read_file_contents: add new entry to read sysfs file
  2015-06-12  7:00     ` Chun Yan Liu
@ 2015-06-12 15:11       ` Ian Jackson
  0 siblings, 0 replies; 88+ messages in thread
From: Ian Jackson @ 2015-06-12 15:11 UTC (permalink / raw)
  To: Chun Yan Liu; +Cc: george.dunlap, wei.liu2, ian.campbell, xen-devel

Chun Yan Liu writes ("Re: [Xen-devel] [PATCH V4 2/7] libxl_read_file_contents: add new entry	to read sysfs file"):
> <21881.46148.466883.923039@mariner.uk.xensource.com>, Ian Jackson
> <Ian.Jackson@eu.citrix.com> wrote: 
> > Chunyan Liu writes ("[Xen-devel] [PATCH V4 2/7] libxl_read_file_contents: add  
> > What is this for ? 
> 
> I found sometimes reading sysfs file contents, at the end, there is
> some random character. With this line, there is no problem then.

I'm afraid that's not really a complete explanation.

Guessing, I think your calling code expected a trailing nul.

If you want to make an API which is useable for such code, and not
intended for byte blocks, that's fine, but you must then always
nul-terminate (not only if the data was less than 4k) and your new
function probably doesn't want to return a length at all.

> > Is there any risk that the file is actually bigger than advertised, 
> > rather than smaller ? 
> 
> For sysfs file, couldn't be bigger.

Then you should detect the condition that the file is bigger, and call
it an error.

> > > +int libxl_read_sysfs_file_contents(libxl_ctx *ctx, const char *filename, 
> > > +                                   void **data_r, int *datalen_r); 
> >  
> > I think this is a function with sufficiently odd semantics, and a 
> > sufficiently internal purpose, that it should probably not be exposed 
> > in the API. 
> 
> So move to libxl_internal.h? Or not hacking here but just adding an internal
> function in libxl_pvusb.c with repeated codes?

I meant to move it to libxl_internal.h.  Subject to consideration of
what its API ought to be.

Ian.

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

* Re: [PATCH V4 1/7] libxl: export some functions for pvusb use
  2015-06-11 16:28     ` Wei Liu
@ 2015-06-12 15:14       ` Ian Jackson
  0 siblings, 0 replies; 88+ messages in thread
From: Ian Jackson @ 2015-06-12 15:14 UTC (permalink / raw)
  To: Wei Liu; +Cc: george.dunlap, ian.campbell, Simon Cao, Chunyan Liu, xen-devel

Wei Liu writes ("Re: [Xen-devel] [PATCH V4 1/7] libxl: export some functions for pvusb use"):
> On Thu, Jun 11, 2015 at 05:08:57PM +0100, Ian Jackson wrote:
> > Functions in libxl with external linkage should have the appropriate
> > namespacing (ie, their names must start with libxl__).
> > 
> > So, I'm afraid, contrary to Wei's opinion:
> > 
> > Nacked-by: Ian Jackson <ian.jackson@eu.citrix.com>
> > 
> 
> I think if Chunyan moves that function to libxl__ namespace this patch
> should be fine, right?

Yes.

Thanks,
Ian.

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-10  3:20 ` [PATCH V4 3/7] libxl: add pvusb API Chunyan Liu
  2015-06-11 15:00   ` Juergen Gross
  2015-06-11 16:42   ` Ian Jackson
@ 2015-06-15 14:17   ` George Dunlap
  2015-06-15 14:25     ` Jürgen Groß
  2015-06-16 10:41     ` [PATCH V4 3/7] libxl: add pvusb API Ian Jackson
  2015-06-15 17:47   ` George Dunlap
  3 siblings, 2 replies; 88+ messages in thread
From: George Dunlap @ 2015-06-15 14:17 UTC (permalink / raw)
  To: Chunyan Liu
  Cc: Wei Liu, Ian Campbell, Ian Jackson, xen-devel, Jim Fehlig, Simon Cao

On Wed, Jun 10, 2015 at 4:20 AM, Chunyan Liu <cyliu@suse.com> wrote:
> diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
> index 23f27d4..4561e1b 100644
> --- a/tools/libxl/libxl_types.idl
> +++ b/tools/libxl/libxl_types.idl
> @@ -541,6 +541,29 @@ libxl_device_pci = Struct("device_pci", [
>      ("seize", bool),
>      ])
>
> +libxl_usb_protocol = Enumeration("usb_protocol", [
> +    (0, "AUTO"),
> +    (1, "PV"),
> +    (2, "QEMU"),
> +    ])
> +
> +libxl_device_usbctrl = Struct("device_usbctrl", [
> +    ("protocol", libxl_usb_protocol),
> +    ("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),
> +    ("busid", string),
> +    ("hostbus",   integer),
> +    ("hostaddr",  integer),
> +    ])

Ian / Ian / Wei / Jim:

Question about the design of the interface here.

The way that most systems in Linux specify particular USB devices is
with the bus:addr format.  It's the output you get when you run tools
like lsusb, for example, and it's the interface that qemu (and thus
KVM) uses when talking about host devices to assign.  bus:addr might
look like "002:006".

But the bus:addr is a "public api" for Linux; internally, it has a
more structured format, which contains more about the USB topology.
Chunyan is calling this "busid".  An example is something like this:
"2-3.1.1:1.0".

Internally, pvusb needs "busid" in order to find the right sysfs
files.  qemu, on the other hand, does not take busid; so the
devicemodel / HVM implementation of USB would need bus:addr
internally.

Converting bus:addr to busid involves looping through all devices and
seeing which one matches, so it's inefficient to do it every time we
need to do some operation. (See libxl_pvusb.c:usb_busaddr_to_busid().)
 Converting busid to bus:addr is simpler: you read the bus and addr
keys from sysfs using the busid.

I think for a public UI (i.e., xl), bus:addr is really the only
option; I'm pretty sure that's the main interface libvirt provides as
well.

At the libxl level, we basically have 3 options:

1. Have the libxl layer accept bus:addr.  For the pvusb code,
translate bus:addr to busid and place it in an internal structure.

2. Have the libxl layer accept busid.  For the devicemodel code,
 2a. ...translate busid to bus:addr and place it in an internal structure.
 2b. ...translate it to bus:addr when it's used (i.e., when speaking
over qmp to qemu).

3. Have the libxl layer accept both busid and bus:addr.  Translate as
necessary and store in the libxl_device_usb struct.

For #2, I think we need to provide a helper function to convert
bus:addr into busid, since bus:addr is the interface most toolstacks
will want to expose to their users.

Chunyan's initial submission had #2 (without a or b, since the
devicemodel code doesn't exist yet).  I suggested #1, and she pushed
back by compromising (#3).

The advantage of #3 internally is that the functions can do the
translation once (if necessary), and can then pass around the public
libxl_device_usb struct as-is without needing any extra parameters or
a separate libxl_device_usb_internal.  The disadvantage, I think, is
that from an interface perspective, it's fairly pointless to have
both.  busid doesn't really give you any better or more control than
the other, and it's not any more convenient for the user (in fact it's
less convenient because it's more difficult to find).

I *think* 2b wouldn't be terrible from a performance point of view,
since (I think) you'd probably only have to do the translation once
before calling the qmp command.

I still prefer #1; but if people thought #3 or #2b would be
preferable, I could live with that.

Any thoughts?

 -George

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-15 14:17   ` George Dunlap
@ 2015-06-15 14:25     ` Jürgen Groß
  2015-06-15 14:34       ` George Dunlap
  2015-06-16 10:41     ` [PATCH V4 3/7] libxl: add pvusb API Ian Jackson
  1 sibling, 1 reply; 88+ messages in thread
From: Jürgen Groß @ 2015-06-15 14:25 UTC (permalink / raw)
  To: George Dunlap, Chunyan Liu
  Cc: Wei Liu, Ian Campbell, Ian Jackson, xen-devel, Jim Fehlig, Simon Cao

On 06/15/2015 04:17 PM, George Dunlap wrote:
> On Wed, Jun 10, 2015 at 4:20 AM, Chunyan Liu <cyliu@suse.com> wrote:
>> diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
>> index 23f27d4..4561e1b 100644
>> --- a/tools/libxl/libxl_types.idl
>> +++ b/tools/libxl/libxl_types.idl
>> @@ -541,6 +541,29 @@ libxl_device_pci = Struct("device_pci", [
>>       ("seize", bool),
>>       ])
>>
>> +libxl_usb_protocol = Enumeration("usb_protocol", [
>> +    (0, "AUTO"),
>> +    (1, "PV"),
>> +    (2, "QEMU"),
>> +    ])
>> +
>> +libxl_device_usbctrl = Struct("device_usbctrl", [
>> +    ("protocol", libxl_usb_protocol),
>> +    ("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),
>> +    ("busid", string),
>> +    ("hostbus",   integer),
>> +    ("hostaddr",  integer),
>> +    ])
>
> Ian / Ian / Wei / Jim:
>
> Question about the design of the interface here.
>
> The way that most systems in Linux specify particular USB devices is
> with the bus:addr format.  It's the output you get when you run tools
> like lsusb, for example, and it's the interface that qemu (and thus
> KVM) uses when talking about host devices to assign.  bus:addr might
> look like "002:006".
>
> But the bus:addr is a "public api" for Linux; internally, it has a
> more structured format, which contains more about the USB topology.
> Chunyan is calling this "busid".  An example is something like this:
> "2-3.1.1:1.0".
>
> Internally, pvusb needs "busid" in order to find the right sysfs
> files.  qemu, on the other hand, does not take busid; so the
> devicemodel / HVM implementation of USB would need bus:addr
> internally.

A patch for qemu to support the busid is trivial, as the structures
already contain the necessary elements:

--- a/hw/usb/host-legacy.c
+++ b/hw/usb/host-legacy.c
@@ -53,11 +53,6 @@ static int parse_filter(const char *spec, struct 
USBAutoFilter *f)
      const char *p = spec;
      int i;

-    f->bus_num    = 0;
-    f->addr       = 0;
-    f->vendor_id  = 0;
-    f->product_id = 0;
-
      for (i = BUS; i < DONE; i++) {
          p = strpbrk(p, ":.");
          if (!p) {
@@ -100,32 +95,47 @@ USBDevice *usb_host_device_open(USBBus *bus, const 
char *devname)

      dev = usb_create(bus, "usb-host");

+    memset(&filter, 0, sizeof(filter));
+
      if (strstr(devname, "auto:")) {
          if (parse_filter(devname, &filter) < 0) {
              goto fail;
          }
-    } else {
-        p = strchr(devname, '.');
-        if (p) {
-            filter.bus_num    = strtoul(devname, NULL, 0);
-            filter.addr       = strtoul(p + 1, NULL, 0);
-            filter.vendor_id  = 0;
-            filter.product_id = 0;
-        } else {
-            p = strchr(devname, ':');
-            if (p) {
-                filter.bus_num    = 0;
-                filter.addr       = 0;
-                filter.vendor_id  = strtoul(devname, NULL, 16);
-                filter.product_id = strtoul(p + 1, NULL, 16);
-            } else {
-                goto fail;
-            }
-        }
+        goto out;
      }

+    /* Check for <bus>-<port> specification. */
+    p = strchr(devname, '-');
+    if (p && p != devname) {
+        filter.bus_num    = strtoul(devname, NULL, 0);
+        filter.port       = p + 1;
+        goto out;
+    }
+
+    /* Check for <bus>.<addr> specification. */
+    p = strchr(devname, '.');
+    if (p) {
+        filter.bus_num    = strtoul(devname, NULL, 0);
+        filter.addr       = strtoul(p + 1, NULL, 0);
+        goto out;
+    }
+
+    /* Check for <vendorid>:<productid> specification. */
+    p = strchr(devname, ':');
+    if (p) {
+        filter.vendor_id  = strtoul(devname, NULL, 16);
+        filter.product_id = strtoul(p + 1, NULL, 16);
+        goto out;
+    }
+
+    goto fail;
+
+out:
      qdev_prop_set_uint32(&dev->qdev, "hostbus",   filter.bus_num);
      qdev_prop_set_uint32(&dev->qdev, "hostaddr",  filter.addr);
+    if (filter.port) {
+        qdev_prop_set_string(&dev->qdev, "port",  filter.port);
+    }
      qdev_prop_set_uint32(&dev->qdev, "vendorid",  filter.vendor_id);
      qdev_prop_set_uint32(&dev->qdev, "productid", filter.product_id);
      qdev_init_nofail(&dev->qdev);


Juergen

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-15 14:25     ` Jürgen Groß
@ 2015-06-15 14:34       ` George Dunlap
  2015-06-15 18:26         ` Juergen Gross
  0 siblings, 1 reply; 88+ messages in thread
From: George Dunlap @ 2015-06-15 14:34 UTC (permalink / raw)
  To: Jürgen Groß
  Cc: Wei Liu, Ian Campbell, Ian Jackson, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

On Mon, Jun 15, 2015 at 3:25 PM, Jürgen Groß <jgross@suse.com> wrote:
> On 06/15/2015 04:17 PM, George Dunlap wrote:
>>
>> On Wed, Jun 10, 2015 at 4:20 AM, Chunyan Liu <cyliu@suse.com> wrote:
>>>
>>> diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
>>> index 23f27d4..4561e1b 100644
>>> --- a/tools/libxl/libxl_types.idl
>>> +++ b/tools/libxl/libxl_types.idl
>>> @@ -541,6 +541,29 @@ libxl_device_pci = Struct("device_pci", [
>>>       ("seize", bool),
>>>       ])
>>>
>>> +libxl_usb_protocol = Enumeration("usb_protocol", [
>>> +    (0, "AUTO"),
>>> +    (1, "PV"),
>>> +    (2, "QEMU"),
>>> +    ])
>>> +
>>> +libxl_device_usbctrl = Struct("device_usbctrl", [
>>> +    ("protocol", libxl_usb_protocol),
>>> +    ("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),
>>> +    ("busid", string),
>>> +    ("hostbus",   integer),
>>> +    ("hostaddr",  integer),
>>> +    ])
>>
>>
>> Ian / Ian / Wei / Jim:
>>
>> Question about the design of the interface here.
>>
>> The way that most systems in Linux specify particular USB devices is
>> with the bus:addr format.  It's the output you get when you run tools
>> like lsusb, for example, and it's the interface that qemu (and thus
>> KVM) uses when talking about host devices to assign.  bus:addr might
>> look like "002:006".
>>
>> But the bus:addr is a "public api" for Linux; internally, it has a
>> more structured format, which contains more about the USB topology.
>> Chunyan is calling this "busid".  An example is something like this:
>> "2-3.1.1:1.0".
>>
>> Internally, pvusb needs "busid" in order to find the right sysfs
>> files.  qemu, on the other hand, does not take busid; so the
>> devicemodel / HVM implementation of USB would need bus:addr
>> internally.
>
>
> A patch for qemu to support the busid is trivial, as the structures
> already contain the necessary elements:
>
> --- a/hw/usb/host-legacy.c
> +++ b/hw/usb/host-legacy.c
> @@ -53,11 +53,6 @@ static int parse_filter(const char *spec, struct
> USBAutoFilter *f)
>      const char *p = spec;
>      int i;
>
> -    f->bus_num    = 0;
> -    f->addr       = 0;
> -    f->vendor_id  = 0;
> -    f->product_id = 0;
> -
>      for (i = BUS; i < DONE; i++) {
>          p = strpbrk(p, ":.");
>          if (!p) {
> @@ -100,32 +95,47 @@ USBDevice *usb_host_device_open(USBBus *bus, const char
> *devname)
>
>      dev = usb_create(bus, "usb-host");
>
> +    memset(&filter, 0, sizeof(filter));
> +
>      if (strstr(devname, "auto:")) {
>          if (parse_filter(devname, &filter) < 0) {
>              goto fail;
>          }
> -    } else {
> -        p = strchr(devname, '.');
> -        if (p) {
> -            filter.bus_num    = strtoul(devname, NULL, 0);
> -            filter.addr       = strtoul(p + 1, NULL, 0);
> -            filter.vendor_id  = 0;
> -            filter.product_id = 0;
> -        } else {
> -            p = strchr(devname, ':');
> -            if (p) {
> -                filter.bus_num    = 0;
> -                filter.addr       = 0;
> -                filter.vendor_id  = strtoul(devname, NULL, 16);
> -                filter.product_id = strtoul(p + 1, NULL, 16);
> -            } else {
> -                goto fail;
> -            }
> -        }
> +        goto out;
>      }
>
> +    /* Check for <bus>-<port> specification. */
> +    p = strchr(devname, '-');
> +    if (p && p != devname) {
> +        filter.bus_num    = strtoul(devname, NULL, 0);
> +        filter.port       = p + 1;
> +        goto out;
> +    }


On my system bus:addr for my mouse is 002:005, while the "busid" (the
corresponding directory in sysfs) is 2-3.3.

This code doesn't appear to me to parse the above properly; or did I
miss something?

 -George

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

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-10  3:20 ` [PATCH V4 3/7] libxl: add pvusb API Chunyan Liu
                     ` (2 preceding siblings ...)
  2015-06-15 14:17   ` George Dunlap
@ 2015-06-15 17:47   ` George Dunlap
  2015-06-23 10:18     ` Chun Yan Liu
  3 siblings, 1 reply; 88+ messages in thread
From: George Dunlap @ 2015-06-15 17:47 UTC (permalink / raw)
  To: Chunyan Liu, xen-devel; +Cc: wei.liu2, Simon Cao, Ian.Jackson, ian.campbell

On 06/10/2015 04:20 AM, Chunyan Liu wrote:
> Add pvusb APIs, including:
>  - attach/detach (create/destroy) virtual usb controller.
>  - attach/detach usb device
>  - list usb controller and usb devices
>  - some other helper functions
> 
> Signed-off-by: Chunyan Liu <cyliu@suse.com>
> Signed-off-by: Simon Cao <caobosimon@gmail.com>
> 
> ---
> changes:
>   - make libxl_device_usbctrl_add async, to be consistent with
>     libxl_device_usbctrl_remove, using MACROs DEFINE_DEVICE_ADD
>     and DEFINE_DEVICES_ADD, adjusting related codes.
>   - correct update_json related processing.
>   - use libxl__* helper functions instead of calloc, realloc
>     and strdup, etc. whereever possible.
>   - merge protocol definition pv|qemu in this patch
>   - treat it as warning at rebind failure instead of error in usb_remove
>   - add documentation docs/misc/pvusb.txt to describe pvusb
>     details (toolstack design, libxl design, xenstore info, etc.)
>   - other fixes addring Wei and George's comments
> 
>  docs/misc/pvusb.txt                  |  243 +++++++
>  tools/libxl/Makefile                 |    2 +-
>  tools/libxl/libxl.c                  |    6 +
>  tools/libxl/libxl.h                  |   65 ++
>  tools/libxl/libxl_internal.h         |   16 +-
>  tools/libxl/libxl_osdeps.h           |   13 +
>  tools/libxl/libxl_pvusb.c            | 1249 ++++++++++++++++++++++++++++++++++
>  tools/libxl/libxl_types.idl          |   52 ++
>  tools/libxl/libxl_types_internal.idl |    1 +
>  tools/libxl/libxl_utils.c            |   16 +
>  10 files changed, 1661 insertions(+), 2 deletions(-)
>  create mode 100644 docs/misc/pvusb.txt
>  create mode 100644 tools/libxl/libxl_pvusb.c
> 
> diff --git a/docs/misc/pvusb.txt b/docs/misc/pvusb.txt
> new file mode 100644
> index 0000000..4cdf965
> --- /dev/null
> +++ b/docs/misc/pvusb.txt
> @@ -0,0 +1,243 @@
> +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).
> +
> +Additionally, for easy use of PVUSB, you need support in the toolstack
> +to get the two sides to talk to each other.

I think this paragraph is probably unnecessary.  By the time this is
checked in, the toolstack will have the necessary support.

> +2. Specifying a host USB device
> +
> +QEMU hmp commands allows USB devices to be specified either by their

s/hmp/qmp/; ?

> +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.

This paragraph comparing the different ways of specifying devices makes
sense to include in the 0/N series summary, but not so much in a file
we're checking in.

> +
> +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 Hub could not be assigned to guest.

"USB hubs cannot be assigned to a guest."

[snip]

> +int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid,
> +                                libxl_device_usbctrl *usbctrl,
> +                                libxl_usbctrlinfo *usbctrlinfo)
> +{
> +    GC_INIT(ctx);
> +    char *dompath, *usbctrlpath;
> +    char *val;
> +    int rc = 0;
> +
> +    usbctrlinfo->devid = usbctrl->devid;
> +    usbctrlinfo->ports = usbctrl->ports;
> +    usbctrlinfo->version = usbctrl->version;
> +    usbctrlinfo->protocol = usbctrl->protocol;

You seem to have missed my message about this -- the only thing you are
allowed to read from usbctrl in this function is the devid. Everything
else you have to look up and give back to the user. That's the point of
the function -- the user has the devid and is asking *you* how many
ports there are, what usb version it is, &c.

[snip]
> +/* get usb devices under certain usb controller */
> +static int
> +libxl__device_usb_list_per_usbctrl(libxl__gc *gc, uint32_t domid, int usbctrl,

Should usbctrl be of type libxl_devid?


> +static int libxl__device_usb_setdefault(libxl__gc *gc, uint32_t domid,
> +                                        libxl_device_usb *usb,
> +                                        bool update_json)
> +{
> +    char *be_path, *tmp;
> +
> +    if (usb->ctrl == -1) {
> +        int ret = libxl__device_usb_set_default_usbctrl(gc, domid, usb);
> +        /* If no existing ctrl to host this usb device, setup a new one */
> +        if (ret) {
> +            libxl_device_usbctrl usbctrl;
> +            libxl_device_usbctrl_init(&usbctrl);
> +            if (libxl_device_usbctrl_add_common(CTX, domid, &usbctrl,
> +                                                0, update_json)) {
> +                LOG(ERROR, "Failed to create usb controller");
> +                return ERROR_INVAL;
> +            }
> +            usb->ctrl = usbctrl.devid;
> +            usb->port = 1;
> +            libxl_device_usbctrl_dispose(&usbctrl);
> +        }
> +    }

Sorry for not noticing this before -- it  looks like if you set
usb->ctrl to -1, it will automatically choose both a controller and a
port number.  But what if you want to specify that you want a particular
controller (for example, if you want to specify the PV controller rather
than the emulated one, or vice versa), but didn't want to have to
manually keep track of which ports were free?

It seems like it would be better to have the code treat port 0 as
"automatically choose a port for me".

(If this were the only thing holding it up I would say this wouldn't be
a blocker to going in.)

> +static int libxl__device_usb_remove(libxl__gc *gc, uint32_t domid,
> +                                    libxl_device_usb *usb)
> +{
> +    libxl_device_usb *usbs = NULL;
> +    libxl_device_usb *usb_find = NULL;
> +    int i, num = 0, rc;
> +
> +    assert(usb->busid || (usb->hostbus > 0 && usb->hostaddr > 0));
> +
> +    if (!usb->busid) {
> +        usb->busid = usb_busaddr_to_busid(gc, usb->hostbus, usb->hostaddr);
> +        if (!usb->busid) {
> +            LOG(ERROR, "USB device doesn't exist in sysfs");
> +            return ERROR_INVAL;
> +        }
> +    }

So here you're keying the removal on the *host* idea of what the device
is.  But the standard would be to key this on the *guest* idea of what
the device is.  When you're doing disk removal, you don't say

"xl block-detach 1 /images/foo.img"

that is, the path to the disk image; you say

"xl block-detach 1 xvda"

that is, the image as seen from the guest.

Since there is no devid, you should make it possible to remove by
<ctrl,port>.  Removing also by hostbus:hostaddr seems like useful
functionality, so it's probably not bad to keep it; but the <ctrl,port>
should be the main functionality.

> +int libxl_device_usb_getinfo(libxl_ctx *ctx, libxl_device_usb *usb,
> +                             libxl_usbinfo *usbinfo)
> +{
> +    GC_INIT(ctx);
> +    char *filename;
> +    void *buf = NULL;
> +
> +    usbinfo->ctrl = usb->ctrl;
> +    usbinfo->port = usb->port;
> +
> +    if (usb->busid)
> +        usbinfo->busid = libxl__strdup(NOGC, usb->busid);
> +    else if (usb->hostbus > 0 && usb->hostaddr > 0)
> +        usbinfo->busid = usb_busaddr_to_busid(gc, usb->hostbus, usb->hostaddr);

Similar to my libxl_device_usbctrl_getinfo() comment -- the purpose of
this function is to specify a minimal amount of information, and have
the library return and look up everything else.  Since libxl_device_usb
doesn't have a devid, the "key" for this should probably be <ctrl,port>.
 Which means, you are only allowed to read usb->{ctrl,port}; everything
else you have to look up.

 -George

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-15 14:34       ` George Dunlap
@ 2015-06-15 18:26         ` Juergen Gross
  2015-06-16 10:30           ` George Dunlap
  0 siblings, 1 reply; 88+ messages in thread
From: Juergen Gross @ 2015-06-15 18:26 UTC (permalink / raw)
  To: George Dunlap
  Cc: Wei Liu, Ian Campbell, Ian Jackson, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

On 06/15/2015 04:34 PM, George Dunlap wrote:
> On Mon, Jun 15, 2015 at 3:25 PM, Jürgen Groß <jgross@suse.com> wrote:
>> On 06/15/2015 04:17 PM, George Dunlap wrote:
>>>
>>> On Wed, Jun 10, 2015 at 4:20 AM, Chunyan Liu <cyliu@suse.com> wrote:
>>>>
>>>> diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
>>>> index 23f27d4..4561e1b 100644
>>>> --- a/tools/libxl/libxl_types.idl
>>>> +++ b/tools/libxl/libxl_types.idl
>>>> @@ -541,6 +541,29 @@ libxl_device_pci = Struct("device_pci", [
>>>>        ("seize", bool),
>>>>        ])
>>>>
>>>> +libxl_usb_protocol = Enumeration("usb_protocol", [
>>>> +    (0, "AUTO"),
>>>> +    (1, "PV"),
>>>> +    (2, "QEMU"),
>>>> +    ])
>>>> +
>>>> +libxl_device_usbctrl = Struct("device_usbctrl", [
>>>> +    ("protocol", libxl_usb_protocol),
>>>> +    ("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),
>>>> +    ("busid", string),
>>>> +    ("hostbus",   integer),
>>>> +    ("hostaddr",  integer),
>>>> +    ])
>>>
>>>
>>> Ian / Ian / Wei / Jim:
>>>
>>> Question about the design of the interface here.
>>>
>>> The way that most systems in Linux specify particular USB devices is
>>> with the bus:addr format.  It's the output you get when you run tools
>>> like lsusb, for example, and it's the interface that qemu (and thus
>>> KVM) uses when talking about host devices to assign.  bus:addr might
>>> look like "002:006".
>>>
>>> But the bus:addr is a "public api" for Linux; internally, it has a
>>> more structured format, which contains more about the USB topology.
>>> Chunyan is calling this "busid".  An example is something like this:
>>> "2-3.1.1:1.0".
>>>
>>> Internally, pvusb needs "busid" in order to find the right sysfs
>>> files.  qemu, on the other hand, does not take busid; so the
>>> devicemodel / HVM implementation of USB would need bus:addr
>>> internally.
>>
>>
>> A patch for qemu to support the busid is trivial, as the structures
>> already contain the necessary elements:
>>
>> --- a/hw/usb/host-legacy.c
>> +++ b/hw/usb/host-legacy.c
>> @@ -53,11 +53,6 @@ static int parse_filter(const char *spec, struct
>> USBAutoFilter *f)
>>       const char *p = spec;
>>       int i;
>>
>> -    f->bus_num    = 0;
>> -    f->addr       = 0;
>> -    f->vendor_id  = 0;
>> -    f->product_id = 0;
>> -
>>       for (i = BUS; i < DONE; i++) {
>>           p = strpbrk(p, ":.");
>>           if (!p) {
>> @@ -100,32 +95,47 @@ USBDevice *usb_host_device_open(USBBus *bus, const char
>> *devname)
>>
>>       dev = usb_create(bus, "usb-host");
>>
>> +    memset(&filter, 0, sizeof(filter));
>> +
>>       if (strstr(devname, "auto:")) {
>>           if (parse_filter(devname, &filter) < 0) {
>>               goto fail;
>>           }
>> -    } else {
>> -        p = strchr(devname, '.');
>> -        if (p) {
>> -            filter.bus_num    = strtoul(devname, NULL, 0);
>> -            filter.addr       = strtoul(p + 1, NULL, 0);
>> -            filter.vendor_id  = 0;
>> -            filter.product_id = 0;
>> -        } else {
>> -            p = strchr(devname, ':');
>> -            if (p) {
>> -                filter.bus_num    = 0;
>> -                filter.addr       = 0;
>> -                filter.vendor_id  = strtoul(devname, NULL, 16);
>> -                filter.product_id = strtoul(p + 1, NULL, 16);
>> -            } else {
>> -                goto fail;
>> -            }
>> -        }
>> +        goto out;
>>       }
>>
>> +    /* Check for <bus>-<port> specification. */
>> +    p = strchr(devname, '-');
>> +    if (p && p != devname) {
>> +        filter.bus_num    = strtoul(devname, NULL, 0);
>> +        filter.port       = p + 1;
>> +        goto out;
>> +    }
>
>
> On my system bus:addr for my mouse is 002:005, while the "busid" (the
> corresponding directory in sysfs) is 2-3.3.
>
> This code doesn't appear to me to parse the above properly; or did I
> miss something?

Filling filter.bus_num and filter.port is enough. This was the only part
missing in qemu, finding the device via libusb using bus_num and port is
already existing. At least it is working for me. :-)


Juergen

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

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-15 18:26         ` Juergen Gross
@ 2015-06-16 10:30           ` George Dunlap
  2015-06-16 10:51             ` Juergen Gross
  0 siblings, 1 reply; 88+ messages in thread
From: George Dunlap @ 2015-06-16 10:30 UTC (permalink / raw)
  To: Juergen Gross
  Cc: Wei Liu, Ian Campbell, Ian Jackson, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

On Mon, Jun 15, 2015 at 7:26 PM, Juergen Gross <jgross@suse.com> wrote:
> On 06/15/2015 04:34 PM, George Dunlap wrote:
>>
>> On Mon, Jun 15, 2015 at 3:25 PM, Jürgen Groß <jgross@suse.com> wrote:
>>>
>>> On 06/15/2015 04:17 PM, George Dunlap wrote:
>>>>
>>>>
>>>> On Wed, Jun 10, 2015 at 4:20 AM, Chunyan Liu <cyliu@suse.com> wrote:
>>>>>
>>>>>
>>>>> diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
>>>>> index 23f27d4..4561e1b 100644
>>>>> --- a/tools/libxl/libxl_types.idl
>>>>> +++ b/tools/libxl/libxl_types.idl
>>>>> @@ -541,6 +541,29 @@ libxl_device_pci = Struct("device_pci", [
>>>>>        ("seize", bool),
>>>>>        ])
>>>>>
>>>>> +libxl_usb_protocol = Enumeration("usb_protocol", [
>>>>> +    (0, "AUTO"),
>>>>> +    (1, "PV"),
>>>>> +    (2, "QEMU"),
>>>>> +    ])
>>>>> +
>>>>> +libxl_device_usbctrl = Struct("device_usbctrl", [
>>>>> +    ("protocol", libxl_usb_protocol),
>>>>> +    ("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),
>>>>> +    ("busid", string),
>>>>> +    ("hostbus",   integer),
>>>>> +    ("hostaddr",  integer),
>>>>> +    ])
>>>>
>>>>
>>>>
>>>> Ian / Ian / Wei / Jim:
>>>>
>>>> Question about the design of the interface here.
>>>>
>>>> The way that most systems in Linux specify particular USB devices is
>>>> with the bus:addr format.  It's the output you get when you run tools
>>>> like lsusb, for example, and it's the interface that qemu (and thus
>>>> KVM) uses when talking about host devices to assign.  bus:addr might
>>>> look like "002:006".
>>>>
>>>> But the bus:addr is a "public api" for Linux; internally, it has a
>>>> more structured format, which contains more about the USB topology.
>>>> Chunyan is calling this "busid".  An example is something like this:
>>>> "2-3.1.1:1.0".
>>>>
>>>> Internally, pvusb needs "busid" in order to find the right sysfs
>>>> files.  qemu, on the other hand, does not take busid; so the
>>>> devicemodel / HVM implementation of USB would need bus:addr
>>>> internally.
>>>
>>>
>>>
>>> A patch for qemu to support the busid is trivial, as the structures
>>> already contain the necessary elements:
>>>
>>> --- a/hw/usb/host-legacy.c
>>> +++ b/hw/usb/host-legacy.c
>>> @@ -53,11 +53,6 @@ static int parse_filter(const char *spec, struct
>>> USBAutoFilter *f)
>>>       const char *p = spec;
>>>       int i;
>>>
>>> -    f->bus_num    = 0;
>>> -    f->addr       = 0;
>>> -    f->vendor_id  = 0;
>>> -    f->product_id = 0;
>>> -
>>>       for (i = BUS; i < DONE; i++) {
>>>           p = strpbrk(p, ":.");
>>>           if (!p) {
>>> @@ -100,32 +95,47 @@ USBDevice *usb_host_device_open(USBBus *bus, const
>>> char
>>> *devname)
>>>
>>>       dev = usb_create(bus, "usb-host");
>>>
>>> +    memset(&filter, 0, sizeof(filter));
>>> +
>>>       if (strstr(devname, "auto:")) {
>>>           if (parse_filter(devname, &filter) < 0) {
>>>               goto fail;
>>>           }
>>> -    } else {
>>> -        p = strchr(devname, '.');
>>> -        if (p) {
>>> -            filter.bus_num    = strtoul(devname, NULL, 0);
>>> -            filter.addr       = strtoul(p + 1, NULL, 0);
>>> -            filter.vendor_id  = 0;
>>> -            filter.product_id = 0;
>>> -        } else {
>>> -            p = strchr(devname, ':');
>>> -            if (p) {
>>> -                filter.bus_num    = 0;
>>> -                filter.addr       = 0;
>>> -                filter.vendor_id  = strtoul(devname, NULL, 16);
>>> -                filter.product_id = strtoul(p + 1, NULL, 16);
>>> -            } else {
>>> -                goto fail;
>>> -            }
>>> -        }
>>> +        goto out;
>>>       }
>>>
>>> +    /* Check for <bus>-<port> specification. */
>>> +    p = strchr(devname, '-');
>>> +    if (p && p != devname) {
>>> +        filter.bus_num    = strtoul(devname, NULL, 0);
>>> +        filter.port       = p + 1;
>>> +        goto out;
>>> +    }
>>
>>
>>
>> On my system bus:addr for my mouse is 002:005, while the "busid" (the
>> corresponding directory in sysfs) is 2-3.3.
>>
>> This code doesn't appear to me to parse the above properly; or did I
>> miss something?
>
>
> Filling filter.bus_num and filter.port is enough. This was the only part
> missing in qemu, finding the device via libusb using bus_num and port is
> already existing. At least it is working for me. :-)

Well, one of us is completely wrong.

Let's follow the example above:

$ ls /sys/bus/usb/devices/2-3*
/sys/bus/usb/devices/2-3@
/sys/bus/usb/devices/2-3.1@
/sys/bus/usb/devices/2-3:1.0@
/sys/bus/usb/devices/2-3.1.1@
/sys/bus/usb/devices/2-3.1:1.0@
/sys/bus/usb/devices/2-3.1.1:1.0@
/sys/bus/usb/devices/2-3.1.2@
/sys/bus/usb/devices/2-3.1.2:1.0@
/sys/bus/usb/devices/2-3.1.2:1.1@
/sys/bus/usb/devices/2-3.2@
/sys/bus/usb/devices/2-3.2:1.0@
/sys/bus/usb/devices/2-3.3@
/sys/bus/usb/devices/2-3.3:1.0@

$ for i in /sys/bus/usb/devices/2-3*/; do grep . $i/{bus,dev}num ; done
/sys/bus/usb/devices/2-3//busnum:2
/sys/bus/usb/devices/2-3//devnum:2
/sys/bus/usb/devices/2-3.1//busnum:2
/sys/bus/usb/devices/2-3.1//devnum:3
/sys/bus/usb/devices/2-3.1.1//busnum:2
/sys/bus/usb/devices/2-3.1.1//devnum:6
/sys/bus/usb/devices/2-3.1.2//busnum:2
/sys/bus/usb/devices/2-3.1.2//devnum:10
/sys/bus/usb/devices/2-3.2//busnum:2
/sys/bus/usb/devices/2-3.2//devnum:4
/sys/bus/usb/devices/2-3.3//busnum:2
/sys/bus/usb/devices/2-3.3//devnum:5

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

In other words, there are 6 distinct devices that correspond to "bus 2
port 3".  I don't know what it was you were passing through, but
giving qemu (or libusb) only "2-3" is absolutely not enough for it to
distinquish between my mouse (002:005, at 2-3.3) and my yubikey
(002:010 at 2-3.1.2).  That's why the bus:addr convention was invented
in the first place, I presume -- to abstract away the topology of the
USB hubs for the user.

The "busid" interface that Chunyan is describing requires the caller
to find out that long name -- 2-3.1.2 -- rather than the traditional
short name (002:010).  Just accepting "2-3" is not sufficient.

 -George

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

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-15 14:17   ` George Dunlap
  2015-06-15 14:25     ` Jürgen Groß
@ 2015-06-16 10:41     ` Ian Jackson
  2015-06-16 10:56       ` Jürgen Groß
  2015-06-16 11:01       ` George Dunlap
  1 sibling, 2 replies; 88+ messages in thread
From: Ian Jackson @ 2015-06-16 10:41 UTC (permalink / raw)
  To: George Dunlap
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
> Ian / Ian / Wei / Jim:

Hi.

> 3. Have the libxl layer accept both busid and bus:addr.  Translate as
> necessary and store in the libxl_device_usb struct.
...
> The advantage of #3 internally is that the functions can do the
> translation once (if necessary), and can then pass around the public
> libxl_device_usb struct as-is without needing any extra parameters or
> a separate libxl_device_usb_internal.  The disadvantage, I think, is
> that from an interface perspective, it's fairly pointless to have
> both.  busid doesn't really give you any better or more control than
> the other, and it's not any more convenient for the user (in fact it's
> less convenient because it's more difficult to find).

Is the busid more stable in the face of plug/unplug ?  This is the
normal reason for a more path-like device specification.

If so then we must support it, even if it's not the usual way an
ordinary user would use it for a one-off.  Otherwise you have to write
something in your config files for the VMs on your VM host, which will
break when someone plugs a keyboard into the `wrong' USB port.

Ian.

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 10:30           ` George Dunlap
@ 2015-06-16 10:51             ` Juergen Gross
  2015-06-16 11:11               ` George Dunlap
  0 siblings, 1 reply; 88+ messages in thread
From: Juergen Gross @ 2015-06-16 10:51 UTC (permalink / raw)
  To: George Dunlap
  Cc: Wei Liu, Ian Campbell, Ian Jackson, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

On 06/16/2015 12:30 PM, George Dunlap wrote:
> On Mon, Jun 15, 2015 at 7:26 PM, Juergen Gross <jgross@suse.com> wrote:
>> On 06/15/2015 04:34 PM, George Dunlap wrote:
>>>
>>> On Mon, Jun 15, 2015 at 3:25 PM, Jürgen Groß <jgross@suse.com> wrote:
>>>>
>>>> On 06/15/2015 04:17 PM, George Dunlap wrote:
>>>>>
>>>>>
>>>>> On Wed, Jun 10, 2015 at 4:20 AM, Chunyan Liu <cyliu@suse.com> wrote:
>>>>>>
>>>>>>
>>>>>> diff --git a/tools/libxl/libxl_types.idl b/tools/libxl/libxl_types.idl
>>>>>> index 23f27d4..4561e1b 100644
>>>>>> --- a/tools/libxl/libxl_types.idl
>>>>>> +++ b/tools/libxl/libxl_types.idl
>>>>>> @@ -541,6 +541,29 @@ libxl_device_pci = Struct("device_pci", [
>>>>>>         ("seize", bool),
>>>>>>         ])
>>>>>>
>>>>>> +libxl_usb_protocol = Enumeration("usb_protocol", [
>>>>>> +    (0, "AUTO"),
>>>>>> +    (1, "PV"),
>>>>>> +    (2, "QEMU"),
>>>>>> +    ])
>>>>>> +
>>>>>> +libxl_device_usbctrl = Struct("device_usbctrl", [
>>>>>> +    ("protocol", libxl_usb_protocol),
>>>>>> +    ("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),
>>>>>> +    ("busid", string),
>>>>>> +    ("hostbus",   integer),
>>>>>> +    ("hostaddr",  integer),
>>>>>> +    ])
>>>>>
>>>>>
>>>>>
>>>>> Ian / Ian / Wei / Jim:
>>>>>
>>>>> Question about the design of the interface here.
>>>>>
>>>>> The way that most systems in Linux specify particular USB devices is
>>>>> with the bus:addr format.  It's the output you get when you run tools
>>>>> like lsusb, for example, and it's the interface that qemu (and thus
>>>>> KVM) uses when talking about host devices to assign.  bus:addr might
>>>>> look like "002:006".
>>>>>
>>>>> But the bus:addr is a "public api" for Linux; internally, it has a
>>>>> more structured format, which contains more about the USB topology.
>>>>> Chunyan is calling this "busid".  An example is something like this:
>>>>> "2-3.1.1:1.0".
>>>>>
>>>>> Internally, pvusb needs "busid" in order to find the right sysfs
>>>>> files.  qemu, on the other hand, does not take busid; so the
>>>>> devicemodel / HVM implementation of USB would need bus:addr
>>>>> internally.
>>>>
>>>>
>>>>
>>>> A patch for qemu to support the busid is trivial, as the structures
>>>> already contain the necessary elements:
>>>>
>>>> --- a/hw/usb/host-legacy.c
>>>> +++ b/hw/usb/host-legacy.c
>>>> @@ -53,11 +53,6 @@ static int parse_filter(const char *spec, struct
>>>> USBAutoFilter *f)
>>>>        const char *p = spec;
>>>>        int i;
>>>>
>>>> -    f->bus_num    = 0;
>>>> -    f->addr       = 0;
>>>> -    f->vendor_id  = 0;
>>>> -    f->product_id = 0;
>>>> -
>>>>        for (i = BUS; i < DONE; i++) {
>>>>            p = strpbrk(p, ":.");
>>>>            if (!p) {
>>>> @@ -100,32 +95,47 @@ USBDevice *usb_host_device_open(USBBus *bus, const
>>>> char
>>>> *devname)
>>>>
>>>>        dev = usb_create(bus, "usb-host");
>>>>
>>>> +    memset(&filter, 0, sizeof(filter));
>>>> +
>>>>        if (strstr(devname, "auto:")) {
>>>>            if (parse_filter(devname, &filter) < 0) {
>>>>                goto fail;
>>>>            }
>>>> -    } else {
>>>> -        p = strchr(devname, '.');
>>>> -        if (p) {
>>>> -            filter.bus_num    = strtoul(devname, NULL, 0);
>>>> -            filter.addr       = strtoul(p + 1, NULL, 0);
>>>> -            filter.vendor_id  = 0;
>>>> -            filter.product_id = 0;
>>>> -        } else {
>>>> -            p = strchr(devname, ':');
>>>> -            if (p) {
>>>> -                filter.bus_num    = 0;
>>>> -                filter.addr       = 0;
>>>> -                filter.vendor_id  = strtoul(devname, NULL, 16);
>>>> -                filter.product_id = strtoul(p + 1, NULL, 16);
>>>> -            } else {
>>>> -                goto fail;
>>>> -            }
>>>> -        }
>>>> +        goto out;
>>>>        }
>>>>
>>>> +    /* Check for <bus>-<port> specification. */
>>>> +    p = strchr(devname, '-');
>>>> +    if (p && p != devname) {
>>>> +        filter.bus_num    = strtoul(devname, NULL, 0);
>>>> +        filter.port       = p + 1;
>>>> +        goto out;
>>>> +    }
>>>
>>>
>>>
>>> On my system bus:addr for my mouse is 002:005, while the "busid" (the
>>> corresponding directory in sysfs) is 2-3.3.
>>>
>>> This code doesn't appear to me to parse the above properly; or did I
>>> miss something?
>>
>>
>> Filling filter.bus_num and filter.port is enough. This was the only part
>> missing in qemu, finding the device via libusb using bus_num and port is
>> already existing. At least it is working for me. :-)
>
> Well, one of us is completely wrong.
>
> Let's follow the example above:
>
> $ ls /sys/bus/usb/devices/2-3*
> /sys/bus/usb/devices/2-3@
> /sys/bus/usb/devices/2-3.1@
> /sys/bus/usb/devices/2-3:1.0@
> /sys/bus/usb/devices/2-3.1.1@
> /sys/bus/usb/devices/2-3.1:1.0@
> /sys/bus/usb/devices/2-3.1.1:1.0@
> /sys/bus/usb/devices/2-3.1.2@
> /sys/bus/usb/devices/2-3.1.2:1.0@
> /sys/bus/usb/devices/2-3.1.2:1.1@
> /sys/bus/usb/devices/2-3.2@
> /sys/bus/usb/devices/2-3.2:1.0@
> /sys/bus/usb/devices/2-3.3@
> /sys/bus/usb/devices/2-3.3:1.0@
>
> $ for i in /sys/bus/usb/devices/2-3*/; do grep . $i/{bus,dev}num ; done
> /sys/bus/usb/devices/2-3//busnum:2
> /sys/bus/usb/devices/2-3//devnum:2
> /sys/bus/usb/devices/2-3.1//busnum:2
> /sys/bus/usb/devices/2-3.1//devnum:3
> /sys/bus/usb/devices/2-3.1.1//busnum:2
> /sys/bus/usb/devices/2-3.1.1//devnum:6
> /sys/bus/usb/devices/2-3.1.2//busnum:2
> /sys/bus/usb/devices/2-3.1.2//devnum:10
> /sys/bus/usb/devices/2-3.2//busnum:2
> /sys/bus/usb/devices/2-3.2//devnum:4
> /sys/bus/usb/devices/2-3.3//busnum:2
> /sys/bus/usb/devices/2-3.3//devnum:5
>
> $ lsusb | grep "Bus 002"
> Bus 002 Device 005: ID 046d:c016 Logitech, Inc. Optical Wheel Mouse
> Bus 002 Device 004: ID f617:0905
> Bus 002 Device 010: ID 1050:0111 Yubico.com
> Bus 002 Device 006: ID 0424:4060 Standard Microsystems Corp. Ultra
> Fast Media Reader
> Bus 002 Device 003: ID 0424:2640 Standard Microsystems Corp. USB 2.0 Hub
> Bus 002 Device 002: ID 0424:2514 Standard Microsystems Corp. USB 2.0 Hub
> Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
>
> In other words, there are 6 distinct devices that correspond to "bus 2
> port 3".  I don't know what it was you were passing through, but
> giving qemu (or libusb) only "2-3" is absolutely not enough for it to
> distinquish between my mouse (002:005, at 2-3.3) and my yubikey
> (002:010 at 2-3.1.2).  That's why the bus:addr convention was invented
> in the first place, I presume -- to abstract away the topology of the
> USB hubs for the user.
>
> The "busid" interface that Chunyan is describing requires the caller
> to find out that long name -- 2-3.1.2 -- rather than the traditional
> short name (002:010).  Just accepting "2-3" is not sufficient.

qemu with my patch will find the device only if the long name is used.
So the "port" in qemu would be "3.1.2" in your example above.

BTW: be careful with the syntax: x:y is used by qemu to specify a device
by vendorId:productId, you should write "002.010" to use the short name
above.


Juergen

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

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 10:41     ` [PATCH V4 3/7] libxl: add pvusb API Ian Jackson
@ 2015-06-16 10:56       ` Jürgen Groß
  2015-06-16 11:03         ` George Dunlap
  2015-06-16 11:10         ` Ian Jackson
  2015-06-16 11:01       ` George Dunlap
  1 sibling, 2 replies; 88+ messages in thread
From: Jürgen Groß @ 2015-06-16 10:56 UTC (permalink / raw)
  To: Ian Jackson, George Dunlap
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On 06/16/2015 12:41 PM, Ian Jackson wrote:
> George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
>> Ian / Ian / Wei / Jim:
>
> Hi.
>
>> 3. Have the libxl layer accept both busid and bus:addr.  Translate as
>> necessary and store in the libxl_device_usb struct.
> ...
>> The advantage of #3 internally is that the functions can do the
>> translation once (if necessary), and can then pass around the public
>> libxl_device_usb struct as-is without needing any extra parameters or
>> a separate libxl_device_usb_internal.  The disadvantage, I think, is
>> that from an interface perspective, it's fairly pointless to have
>> both.  busid doesn't really give you any better or more control than
>> the other, and it's not any more convenient for the user (in fact it's
>> less convenient because it's more difficult to find).
>
> Is the busid more stable in the face of plug/unplug ?  This is the
> normal reason for a more path-like device specification.
>
> If so then we must support it, even if it's not the usual way an
> ordinary user would use it for a one-off.  Otherwise you have to write
> something in your config files for the VMs on your VM host, which will
> break when someone plugs a keyboard into the `wrong' USB port.

Unfortunately the busid isn't stable at least across reboots.

qemu does support specifying a USB device via <vendorId>:<productId>,
which is stable even across reboots, but unfortunately it isn't
guaranteed to be unique (you can have plugged in two devices of the
same type).

My pvUSB backend in qemu will accept all three variants of device
specification, so may be libxl should do so, too.


Juergen

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 10:41     ` [PATCH V4 3/7] libxl: add pvusb API Ian Jackson
  2015-06-16 10:56       ` Jürgen Groß
@ 2015-06-16 11:01       ` George Dunlap
  2015-06-16 11:12         ` Ian Jackson
  1 sibling, 1 reply; 88+ messages in thread
From: George Dunlap @ 2015-06-16 11:01 UTC (permalink / raw)
  To: Ian Jackson
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On Tue, Jun 16, 2015 at 11:41 AM, Ian Jackson <Ian.Jackson@eu.citrix.com> wrote:
>> 3. Have the libxl layer accept both busid and bus:addr.  Translate as
>> necessary and store in the libxl_device_usb struct.
> ...
>> The advantage of #3 internally is that the functions can do the
>> translation once (if necessary), and can then pass around the public
>> libxl_device_usb struct as-is without needing any extra parameters or
>> a separate libxl_device_usb_internal.  The disadvantage, I think, is
>> that from an interface perspective, it's fairly pointless to have
>> both.  busid doesn't really give you any better or more control than
>> the other, and it's not any more convenient for the user (in fact it's
>> less convenient because it's more difficult to find).
>
> Is the busid more stable in the face of plug/unplug ?  This is the
> normal reason for a more path-like device specification.
>
> If so then we must support it, even if it's not the usual way an
> ordinary user would use it for a one-off.  Otherwise you have to write
> something in your config files for the VMs on your VM host, which will
> break when someone plugs a keyboard into the `wrong' USB port.

It's complicated. :-)

The "busid" we're talking about here will identify a device at a
particular *port* in the USB topology; the busid will take whatever is
plugged into that particular port.  So in the example in my other
thread, the Yubikey "busid" is 2-3.1.2; but if I were to unplug the
yubikey and plud my mouse into that port, the mouse would then be at
2-3.1.2.

The "bus:addr" thing that Linux uses assigns a new "addr" every time
you plug in a device.  The first time I plugged in my Yubikey it got
"002:010"; but when I unplugged it and plugged it back in again, it
got "002:011".  I take it this is on purpose, to solve exactly the
problem above -- my mouse was at 2-3.1.2 before, and then I plug in a
USB disk or a smartcard, I want to make sure I don't accidentally send
commands to the wrong device.

The other thing that most programs seem to handle is vendor:deviceid.
The vendor:deviceid is the same every time you plug the device in, no
matter where. The vendorid:deviceid for my Yubikey is "1050:0111"; so
if I put that in my config file for libvirt or qemu, it will pass
through my Yubikey to the VM, no matter where it's plugged in and no
matter how many times it's been plugged in.  Unfortunately,
vendorid:deviceid is not like a MAC address; it's meant to describe
the *type* of device, not be unique to the device itself.  So if you
have multiple devices of the same kind (say, several different
Yubikeys) then vendorid:deviceid can't distinguish which is which.

That's why qemu accepts at both bus:addr and vendorid:deviceid.

We could in theory do the same thing -- accept any subset of {bus,
port, address, vendorid, deviceid} which will uniquely identify a
specific device.  That may actually be a feature as well -- "Pass
through the device at this bus / port, and by the way I expect it to
be a mouse, so don't pass it through if it's something else."

 -George

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 10:56       ` Jürgen Groß
@ 2015-06-16 11:03         ` George Dunlap
  2015-06-16 11:10         ` Ian Jackson
  1 sibling, 0 replies; 88+ messages in thread
From: George Dunlap @ 2015-06-16 11:03 UTC (permalink / raw)
  To: Jürgen Groß
  Cc: Wei Liu, Ian Campbell, Ian Jackson, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

On Tue, Jun 16, 2015 at 11:56 AM, Jürgen Groß <jgross@suse.com> wrote:
> On 06/16/2015 12:41 PM, Ian Jackson wrote:
>>
>> George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb
>> API"):
>>>
>>> Ian / Ian / Wei / Jim:
>>
>>
>> Hi.
>>
>>> 3. Have the libxl layer accept both busid and bus:addr.  Translate as
>>> necessary and store in the libxl_device_usb struct.
>>
>> ...
>>>
>>> The advantage of #3 internally is that the functions can do the
>>> translation once (if necessary), and can then pass around the public
>>> libxl_device_usb struct as-is without needing any extra parameters or
>>> a separate libxl_device_usb_internal.  The disadvantage, I think, is
>>> that from an interface perspective, it's fairly pointless to have
>>> both.  busid doesn't really give you any better or more control than
>>> the other, and it's not any more convenient for the user (in fact it's
>>> less convenient because it's more difficult to find).
>>
>>
>> Is the busid more stable in the face of plug/unplug ?  This is the
>> normal reason for a more path-like device specification.
>>
>> If so then we must support it, even if it's not the usual way an
>> ordinary user would use it for a one-off.  Otherwise you have to write
>> something in your config files for the VMs on your VM host, which will
>> break when someone plugs a keyboard into the `wrong' USB port.
>
>
> Unfortunately the busid isn't stable at least across reboots.

Isn't it based on the physical topology of the USB network?  Shouldn't
it be the same as long as you don't actually unplug anything?

 -George

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

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 10:56       ` Jürgen Groß
  2015-06-16 11:03         ` George Dunlap
@ 2015-06-16 11:10         ` Ian Jackson
  2015-06-16 11:25           ` Juergen Gross
  1 sibling, 1 reply; 88+ messages in thread
From: Ian Jackson @ 2015-06-16 11:10 UTC (permalink / raw)
  To: Jürgen Groß
  Cc: Wei Liu, Ian Campbell, George Dunlap, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

Jürgen Groß writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
> On 06/16/2015 12:41 PM, Ian Jackson wrote:
> > Is the busid more stable in the face of plug/unplug ?  This is the
> > normal reason for a more path-like device specification.
...
> Unfortunately the busid isn't stable at least across reboots.

I see.

Presumably the busdev isn't either.  We need to be let users specify
something that _is_ stable, obviously.

On my netbook I have this kind of thing in /etc/fstab:

/dev/disk/by-path/pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0-part1 /media/usb1 auto rw,user,noauto 0 0

Is a similar specification possible ?

> qemu does support specifying a USB device via <vendorId>:<productId>,
> which is stable even across reboots, but unfortunately it isn't
> guaranteed to be unique (you can have plugged in two devices of the
> same type).

Indeed.  That would also be a thing we should allow people to do.

AIUI some devices have serial numbers, which means you can distinguish
them ?

Ian.

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 10:51             ` Juergen Gross
@ 2015-06-16 11:11               ` George Dunlap
  2015-06-16 11:19                 ` Juergen Gross
  0 siblings, 1 reply; 88+ messages in thread
From: George Dunlap @ 2015-06-16 11:11 UTC (permalink / raw)
  To: Juergen Gross
  Cc: Wei Liu, Ian Campbell, Ian Jackson, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

On Tue, Jun 16, 2015 at 11:51 AM, Juergen Gross <jgross@suse.com> wrote:
>> The "busid" interface that Chunyan is describing requires the caller
>> to find out that long name -- 2-3.1.2 -- rather than the traditional
>> short name (002:010).  Just accepting "2-3" is not sufficient.
>
>
> qemu with my patch will find the device only if the long name is used.
> So the "port" in qemu would be "3.1.2" in your example above.

Ah, right -- sorry, looking at the patch I saw that "port" was
converted using strtoul, but now I see that was "bus", and that "port"
is a string.  That's what I was missing.

> BTW: be careful with the syntax: x:y is used by qemu to specify a device
> by vendorId:productId, you should write "002.010" to use the short name
> above.

Yes, thanks for the reminder.  I knew there was some way to
distinguish bus.addr and vendor:device, but I'd forgotten the exact
semantics.

So as Juergen says, the typical way to write these would be:
- bus-port; e.g., 2-3.1.2  is bus=2, port=3.1.2.  Stable in topology,
not in device
- bus.addr: e.g., 2.10 is bus=2, address=10.  Unique every time a
device is plugged in (so no risk of aliasing, but not stable across
reboots)
- vendorid:deviceid: e.g., 1050:0111 is vendorid=1050, deviceid=0111.
Stable on device class (so same no matter when or where you plug it
in, but can't tell two identical devices apart).

 -George

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 11:01       ` George Dunlap
@ 2015-06-16 11:12         ` Ian Jackson
  2015-06-16 11:21           ` George Dunlap
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Jackson @ 2015-06-16 11:12 UTC (permalink / raw)
  To: George Dunlap
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
> The "busid" we're talking about here will identify a device at a
> particular *port* in the USB topology; the busid will take whatever is
> plugged into that particular port.  So in the example in my other
> thread, the Yubikey "busid" is 2-3.1.2; but if I were to unplug the
> yubikey and plud my mouse into that port, the mouse would then be at
> 2-3.1.2.

What you have just said contradicts Juergen's assertion that the busid
is not stable across reboots.

I think perhaps the difficulty is that the very first number, the usb
controller number, may not be stable, because it depends on the order
of device discovery.

Ian.

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 11:11               ` George Dunlap
@ 2015-06-16 11:19                 ` Juergen Gross
  2015-06-16 11:23                   ` George Dunlap
  0 siblings, 1 reply; 88+ messages in thread
From: Juergen Gross @ 2015-06-16 11:19 UTC (permalink / raw)
  To: George Dunlap
  Cc: Wei Liu, Ian Campbell, Ian Jackson, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

On 06/16/2015 01:11 PM, George Dunlap wrote:
> On Tue, Jun 16, 2015 at 11:51 AM, Juergen Gross <jgross@suse.com> wrote:
>>> The "busid" interface that Chunyan is describing requires the caller
>>> to find out that long name -- 2-3.1.2 -- rather than the traditional
>>> short name (002:010).  Just accepting "2-3" is not sufficient.
>>
>>
>> qemu with my patch will find the device only if the long name is used.
>> So the "port" in qemu would be "3.1.2" in your example above.
>
> Ah, right -- sorry, looking at the patch I saw that "port" was
> converted using strtoul, but now I see that was "bus", and that "port"
> is a string.  That's what I was missing.
>
>> BTW: be careful with the syntax: x:y is used by qemu to specify a device
>> by vendorId:productId, you should write "002.010" to use the short name
>> above.
>
> Yes, thanks for the reminder.  I knew there was some way to
> distinguish bus.addr and vendor:device, but I'd forgotten the exact
> semantics.
>
> So as Juergen says, the typical way to write these would be:
> - bus-port; e.g., 2-3.1.2  is bus=2, port=3.1.2.  Stable in topology,
> not in device

Nah, not stable in topology. At least on my laptop I've seen a memory
stick plugged in at the same position as "3-3" or as "1-3".

I'm pretty sure this is just a matter of timing during boot: the busses
are all (or at least some of them) queried at the same time and the
first answering gets number 1, the next 2, and so on. And timing seems
to be different enough to result in unstable bus numbers.


Juergen

> - bus.addr: e.g., 2.10 is bus=2, address=10.  Unique every time a
> device is plugged in (so no risk of aliasing, but not stable across
> reboots)
> - vendorid:deviceid: e.g., 1050:0111 is vendorid=1050, deviceid=0111.
> Stable on device class (so same no matter when or where you plug it
> in, but can't tell two identical devices apart).
>
>   -George
>

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 11:12         ` Ian Jackson
@ 2015-06-16 11:21           ` George Dunlap
  2015-06-16 16:32             ` Ian Jackson
  0 siblings, 1 reply; 88+ messages in thread
From: George Dunlap @ 2015-06-16 11:21 UTC (permalink / raw)
  To: Ian Jackson
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On Tue, Jun 16, 2015 at 12:12 PM, Ian Jackson <Ian.Jackson@eu.citrix.com> wrote:
> George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
>> The "busid" we're talking about here will identify a device at a
>> particular *port* in the USB topology; the busid will take whatever is
>> plugged into that particular port.  So in the example in my other
>> thread, the Yubikey "busid" is 2-3.1.2; but if I were to unplug the
>> yubikey and plud my mouse into that port, the mouse would then be at
>> 2-3.1.2.
>
> What you have just said contradicts Juergen's assertion that the busid
> is not stable across reboots.
>
> I think perhaps the difficulty is that the very first number, the usb
> controller number, may not be stable, because it depends on the order
> of device discovery.

I wasn't considering reboots when I made my statement.  According to a
comment on the libusb mailing list:

"The operating system does not guarantee that bus numbers will remain
fixed across reboots.  Usually they will (if the computer's hardware
hasn't been changed), but it isn't guaranteed." [1]

I just used "lsusb -v" to scan through all the devices I have
connected; some of them do have a field called "iSerial", but as most
of these are '0' and the ones that are non-zero are between 1 and 3, I
doubt that will be much use in most cases.  I don't immediately see
anything that might be a unique identifier.

 -George

[1] http://sourceforge.net/p/libusb/mailman/libusb-devel/thread/20080324215139.22289.qmail@cdy.org/

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 11:19                 ` Juergen Gross
@ 2015-06-16 11:23                   ` George Dunlap
  2015-06-16 11:44                     ` Ian Jackson
  0 siblings, 1 reply; 88+ messages in thread
From: George Dunlap @ 2015-06-16 11:23 UTC (permalink / raw)
  To: Juergen Gross
  Cc: Wei Liu, Ian Campbell, Ian Jackson, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

On Tue, Jun 16, 2015 at 12:19 PM, Juergen Gross <jgross@suse.com> wrote:
> On 06/16/2015 01:11 PM, George Dunlap wrote:
>>
>> On Tue, Jun 16, 2015 at 11:51 AM, Juergen Gross <jgross@suse.com> wrote:
>>>>
>>>> The "busid" interface that Chunyan is describing requires the caller
>>>> to find out that long name -- 2-3.1.2 -- rather than the traditional
>>>> short name (002:010).  Just accepting "2-3" is not sufficient.
>>>
>>>
>>>
>>> qemu with my patch will find the device only if the long name is used.
>>> So the "port" in qemu would be "3.1.2" in your example above.
>>
>>
>> Ah, right -- sorry, looking at the patch I saw that "port" was
>> converted using strtoul, but now I see that was "bus", and that "port"
>> is a string.  That's what I was missing.
>>
>>> BTW: be careful with the syntax: x:y is used by qemu to specify a device
>>> by vendorId:productId, you should write "002.010" to use the short name
>>> above.
>>
>>
>> Yes, thanks for the reminder.  I knew there was some way to
>> distinguish bus.addr and vendor:device, but I'd forgotten the exact
>> semantics.
>>
>> So as Juergen says, the typical way to write these would be:
>> - bus-port; e.g., 2-3.1.2  is bus=2, port=3.1.2.  Stable in topology,
>> not in device
>
>
> Nah, not stable in topology. At least on my laptop I've seen a memory
> stick plugged in at the same position as "3-3" or as "1-3".
>
> I'm pretty sure this is just a matter of timing during boot: the busses
> are all (or at least some of them) queried at the same time and the
> first answering gets number 1, the next 2, and so on. And timing seems
> to be different enough to result in unstable bus numbers.

Right -- I meant "stable in topology within one boot", but at least
two of you have now understood me to mean "across reboots" by default,
so that's obviously a detail that needs to be specified. :-)

 -George

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 11:10         ` Ian Jackson
@ 2015-06-16 11:25           ` Juergen Gross
  2015-06-16 11:45             ` George Dunlap
                               ` (2 more replies)
  0 siblings, 3 replies; 88+ messages in thread
From: Juergen Gross @ 2015-06-16 11:25 UTC (permalink / raw)
  To: Ian Jackson
  Cc: Wei Liu, Ian Campbell, George Dunlap, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

On 06/16/2015 01:10 PM, Ian Jackson wrote:
> Jürgen Groß writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
>> On 06/16/2015 12:41 PM, Ian Jackson wrote:
>>> Is the busid more stable in the face of plug/unplug ?  This is the
>>> normal reason for a more path-like device specification.
> ...
>> Unfortunately the busid isn't stable at least across reboots.
>
> I see.
>
> Presumably the busdev isn't either.  We need to be let users specify
> something that _is_ stable, obviously.
>
> On my netbook I have this kind of thing in /etc/fstab:
>
> /dev/disk/by-path/pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0-part1 /media/usb1 auto rw,user,noauto 0 0
>
> Is a similar specification possible ?
>
>> qemu does support specifying a USB device via <vendorId>:<productId>,
>> which is stable even across reboots, but unfortunately it isn't
>> guaranteed to be unique (you can have plugged in two devices of the
>> same type).
>
> Indeed.  That would also be a thing we should allow people to do.
>
> AIUI some devices have serial numbers, which means you can distinguish
> them ?

Yes, they have. The question is whether those are different on multiple
instances? With "lsusb" I've found a device with serial number
0123456789ABCD. Do you really believe I'm just lucky owning the one with
such a nice serial number? ;-)

Juergen

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 11:23                   ` George Dunlap
@ 2015-06-16 11:44                     ` Ian Jackson
  2015-06-17 11:24                       ` Ian Campbell
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Jackson @ 2015-06-16 11:44 UTC (permalink / raw)
  To: George Dunlap
  Cc: Juergen Gross, Wei Liu, Ian Campbell, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
> On Tue, Jun 16, 2015 at 12:19 PM, Juergen Gross <jgross@suse.com> wrote:
> > I'm pretty sure this is just a matter of timing during boot: the busses
> > are all (or at least some of them) queried at the same time and the
> > first answering gets number 1, the next 2, and so on. And timing seems
> > to be different enough to result in unstable bus numbers.
> 
> Right -- I meant "stable in topology within one boot", but at least
> two of you have now understood me to mean "across reboots" by default,
> so that's obviously a detail that needs to be specified. :-)

I think "stable in topology within one boot" is nearly vacuous (or are
we expecting buses or devices to spontaneously renumber themselves for
no reason) and also nearly useless.

We definitely need _some_ way for a user to identify a specific device
uniquely in a way that is reliable from one boot to the next.  vid:pid
is one way to do this, but not always sufficient.

Ian.

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 11:25           ` Juergen Gross
@ 2015-06-16 11:45             ` George Dunlap
  2015-06-16 12:02               ` Ian Jackson
  2015-06-16 11:45             ` [PATCH V4 3/7] libxl: add pvusb API Ian Jackson
  2015-06-16 15:38             ` George Dunlap
  2 siblings, 1 reply; 88+ messages in thread
From: George Dunlap @ 2015-06-16 11:45 UTC (permalink / raw)
  To: Juergen Gross
  Cc: Wei Liu, Ian Campbell, Ian Jackson, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

On Tue, Jun 16, 2015 at 12:25 PM, Juergen Gross <jgross@suse.com> wrote:
>>> qemu does support specifying a USB device via <vendorId>:<productId>,
>>> which is stable even across reboots, but unfortunately it isn't
>>> guaranteed to be unique (you can have plugged in two devices of the
>>> same type).
>>
>>
>> Indeed.  That would also be a thing we should allow people to do.
>>
>> AIUI some devices have serial numbers, which means you can distinguish
>> them ?
>
>
> Yes, they have. The question is whether those are different on multiple
> instances? With "lsusb" I've found a device with serial number
> 0123456789ABCD. Do you really believe I'm just lucky owning the one with
> such a nice serial number? ;-)

So it sounds like we're converging on "Allow multiple ways to specify
the interface", with at least the following fields:
- bus (int - 1,2,3, &c)
- port (string - 2.1.3, &c)
- address/devnum (int)
- vendorid (uint16_t)
- deviceid (uint16_t)

That solves the basic problem, because then the missing information
needed by the various paths can be looked up and added to the device
struct as needed.

 -George

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 11:25           ` Juergen Gross
  2015-06-16 11:45             ` George Dunlap
@ 2015-06-16 11:45             ` Ian Jackson
  2015-06-16 13:06               ` Juergen Gross
  2015-06-16 15:38             ` George Dunlap
  2 siblings, 1 reply; 88+ messages in thread
From: Ian Jackson @ 2015-06-16 11:45 UTC (permalink / raw)
  To: Juergen Gross
  Cc: Wei Liu, Ian Campbell, George Dunlap, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

Juergen Gross writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
> On 06/16/2015 01:10 PM, Ian Jackson wrote:
> > AIUI some devices have serial numbers, which means you can distinguish
> > them ?
> 
> Yes, they have. The question is whether those are different on multiple
> instances? With "lsusb" I've found a device with serial number
> 0123456789ABCD. Do you really believe I'm just lucky owning the one with
> such a nice serial number? ;-)

Heh.  I think, though, that this suggests that if the user has devices
whose serial numbers are actually different, they should be able to
specify a device by vid/pid/serial.

Ian.

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 11:45             ` George Dunlap
@ 2015-06-16 12:02               ` Ian Jackson
  2015-06-16 13:19                 ` George Dunlap
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Jackson @ 2015-06-16 12:02 UTC (permalink / raw)
  To: George Dunlap
  Cc: Juergen Gross, Wei Liu, Ian Campbell, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
> So it sounds like we're converging on "Allow multiple ways to specify
> the interface", with at least the following fields:
> - bus (int - 1,2,3, &c)
> - port (string - 2.1.3, &c)
> - address/devnum (int)
> - vendorid (uint16_t)
> - deviceid (uint16_t)

You're missing the full device path from that list.  Typically that
will include at least one pci bus address.

Ian.

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 11:45             ` [PATCH V4 3/7] libxl: add pvusb API Ian Jackson
@ 2015-06-16 13:06               ` Juergen Gross
  2015-06-16 13:09                 ` George Dunlap
  0 siblings, 1 reply; 88+ messages in thread
From: Juergen Gross @ 2015-06-16 13:06 UTC (permalink / raw)
  To: Ian Jackson
  Cc: Wei Liu, Ian Campbell, George Dunlap, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

On 06/16/2015 01:45 PM, Ian Jackson wrote:
> Juergen Gross writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
>> On 06/16/2015 01:10 PM, Ian Jackson wrote:
>>> AIUI some devices have serial numbers, which means you can distinguish
>>> them ?
>>
>> Yes, they have. The question is whether those are different on multiple
>> instances? With "lsusb" I've found a device with serial number
>> 0123456789ABCD. Do you really believe I'm just lucky owning the one with
>> such a nice serial number? ;-)
>
> Heh.  I think, though, that this suggests that if the user has devices
> whose serial numbers are actually different, they should be able to
> specify a device by vid/pid/serial.

I think you are right.

The next question: should this be part of libxl or qemu? It should be
possible to extend the qemu <vendorId>:<productId> syntax to
<vendorId>:<productId>:<serial> without too much effort, as libusb
includes some support to obtain the serial number.


Juergen

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 13:06               ` Juergen Gross
@ 2015-06-16 13:09                 ` George Dunlap
  2015-06-16 13:23                   ` Juergen Gross
  0 siblings, 1 reply; 88+ messages in thread
From: George Dunlap @ 2015-06-16 13:09 UTC (permalink / raw)
  To: Juergen Gross, Ian Jackson
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On 06/16/2015 02:06 PM, Juergen Gross wrote:
> On 06/16/2015 01:45 PM, Ian Jackson wrote:
>> Juergen Gross writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb
>> API"):
>>> On 06/16/2015 01:10 PM, Ian Jackson wrote:
>>>> AIUI some devices have serial numbers, which means you can distinguish
>>>> them ?
>>>
>>> Yes, they have. The question is whether those are different on multiple
>>> instances? With "lsusb" I've found a device with serial number
>>> 0123456789ABCD. Do you really believe I'm just lucky owning the one with
>>> such a nice serial number? ;-)
>>
>> Heh.  I think, though, that this suggests that if the user has devices
>> whose serial numbers are actually different, they should be able to
>> specify a device by vid/pid/serial.
> 
> I think you are right.
> 
> The next question: should this be part of libxl or qemu? It should be
> possible to extend the qemu <vendorId>:<productId> syntax to
> <vendorId>:<productId>:<serial> without too much effort, as libusb
> includes some support to obtain the serial number.

It doesn't really matter what qemu or pvusb can do, as long as libxl can
convert what it has into something that they can use.  So if libxl is
given vid, pid, and serial (remember, this will be a struct, not a
string), it can look in sysfs and find the bus:addr (which is unique at
any given time) and hand it to qemu  (or the bus-port in the case of pvusb).

 -George

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 12:02               ` Ian Jackson
@ 2015-06-16 13:19                 ` George Dunlap
  2015-06-16 13:32                   ` Juergen Gross
  2015-06-16 13:37                   ` [PATCH V4 3/7] libxl: add pvusb API [and 1 more messages] Ian Jackson
  0 siblings, 2 replies; 88+ messages in thread
From: George Dunlap @ 2015-06-16 13:19 UTC (permalink / raw)
  To: Ian Jackson
  Cc: Juergen Gross, Wei Liu, Ian Campbell, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

On Tue, Jun 16, 2015 at 1:02 PM, Ian Jackson <Ian.Jackson@eu.citrix.com> wrote:
> George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
>> So it sounds like we're converging on "Allow multiple ways to specify
>> the interface", with at least the following fields:
>> - bus (int - 1,2,3, &c)
>> - port (string - 2.1.3, &c)
>> - address/devnum (int)
>> - vendorid (uint16_t)
>> - deviceid (uint16_t)
>
> You're missing the full device path from that list.  Typically that
> will include at least one pci bus address.

I'm not sure what constitutes a "full device path".  Is that defined somewhere?

Remember that the path you gave in your previous e-mail isn't the path
for the *usb device*, it's the path for the *block device*.  It
contains a PCI address, but it looks like it also contains part of the
USB topology.  Are you sure that's actually a stable interface, or
does it just happen that on your hardware the discovery always happens
in the same order?

On my system /sys/bus/usb/devices/2-3.3 is a link to
/sys/devices/pci0000:00/0000:00:1d.7/usb2/2-3/2-3.3/.  This contains
the pci bus address, but it also contains the bus number, which we've
just said may be unstable across reboots.

I suppose it might be possible to specify <buspci,port> -- the pci
address of the root bus, and the topology from there.  In theory I
guess that should be stable?

In any case, at the moment you're essentially inventing from whole
cloth a new way of specifying USB devices that (as far as I know)
isn't supported by any other program that uses USB.

 -George

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 13:09                 ` George Dunlap
@ 2015-06-16 13:23                   ` Juergen Gross
  2015-06-16 13:29                     ` George Dunlap
  0 siblings, 1 reply; 88+ messages in thread
From: Juergen Gross @ 2015-06-16 13:23 UTC (permalink / raw)
  To: George Dunlap, Ian Jackson
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On 06/16/2015 03:09 PM, George Dunlap wrote:
> On 06/16/2015 02:06 PM, Juergen Gross wrote:
>> On 06/16/2015 01:45 PM, Ian Jackson wrote:
>>> Juergen Gross writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb
>>> API"):
>>>> On 06/16/2015 01:10 PM, Ian Jackson wrote:
>>>>> AIUI some devices have serial numbers, which means you can distinguish
>>>>> them ?
>>>>
>>>> Yes, they have. The question is whether those are different on multiple
>>>> instances? With "lsusb" I've found a device with serial number
>>>> 0123456789ABCD. Do you really believe I'm just lucky owning the one with
>>>> such a nice serial number? ;-)
>>>
>>> Heh.  I think, though, that this suggests that if the user has devices
>>> whose serial numbers are actually different, they should be able to
>>> specify a device by vid/pid/serial.
>>
>> I think you are right.
>>
>> The next question: should this be part of libxl or qemu? It should be
>> possible to extend the qemu <vendorId>:<productId> syntax to
>> <vendorId>:<productId>:<serial> without too much effort, as libusb
>> includes some support to obtain the serial number.
>
> It doesn't really matter what qemu or pvusb can do, as long as libxl can
> convert what it has into something that they can use.  So if libxl is
> given vid, pid, and serial (remember, this will be a struct, not a
> string), it can look in sysfs and find the bus:addr (which is unique at
> any given time) and hand it to qemu  (or the bus-port in the case of pvusb).

Hmm, I'd rather have it all in one place. Putting it in qemu would
enable us to handle hotplug as well. A USB device assigned via it's
serial to a domU could be automatically passed through by qemu when
showing up. This isn't possible today, but we wouldn't have to change
libxl again for supporting it, only qemu would have to be adapted.


Juergen

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 13:23                   ` Juergen Gross
@ 2015-06-16 13:29                     ` George Dunlap
  2015-06-16 13:49                       ` Juergen Gross
  0 siblings, 1 reply; 88+ messages in thread
From: George Dunlap @ 2015-06-16 13:29 UTC (permalink / raw)
  To: Juergen Gross, Ian Jackson
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On 06/16/2015 02:23 PM, Juergen Gross wrote:
> On 06/16/2015 03:09 PM, George Dunlap wrote:
>> On 06/16/2015 02:06 PM, Juergen Gross wrote:
>>> On 06/16/2015 01:45 PM, Ian Jackson wrote:
>>>> Juergen Gross writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb
>>>> API"):
>>>>> On 06/16/2015 01:10 PM, Ian Jackson wrote:
>>>>>> AIUI some devices have serial numbers, which means you can
>>>>>> distinguish
>>>>>> them ?
>>>>>
>>>>> Yes, they have. The question is whether those are different on
>>>>> multiple
>>>>> instances? With "lsusb" I've found a device with serial number
>>>>> 0123456789ABCD. Do you really believe I'm just lucky owning the one
>>>>> with
>>>>> such a nice serial number? ;-)
>>>>
>>>> Heh.  I think, though, that this suggests that if the user has devices
>>>> whose serial numbers are actually different, they should be able to
>>>> specify a device by vid/pid/serial.
>>>
>>> I think you are right.
>>>
>>> The next question: should this be part of libxl or qemu? It should be
>>> possible to extend the qemu <vendorId>:<productId> syntax to
>>> <vendorId>:<productId>:<serial> without too much effort, as libusb
>>> includes some support to obtain the serial number.
>>
>> It doesn't really matter what qemu or pvusb can do, as long as libxl can
>> convert what it has into something that they can use.  So if libxl is
>> given vid, pid, and serial (remember, this will be a struct, not a
>> string), it can look in sysfs and find the bus:addr (which is unique at
>> any given time) and hand it to qemu  (or the bus-port in the case of
>> pvusb).
> 
> Hmm, I'd rather have it all in one place. Putting it in qemu would
> enable us to handle hotplug as well. A USB device assigned via it's
> serial to a domU could be automatically passed through by qemu when
> showing up. This isn't possible today, but we wouldn't have to change
> libxl again for supporting it, only qemu would have to be adapted.

Look, we're talking here about the libxl interface.  Ian thinks that *at
the libxl layer* we need to be able to specify all these things.  It
doesn't matter at this point whether qemu can also do it or not.

In the future, if we actually implement the "automatically grab this
device when it shows up" functionality, then yes, having it in qemu
rather than having a libxl daemon sit around and watch for those things,
might be handy.  But we can cross that bridge when we come to it.

 -George

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 13:19                 ` George Dunlap
@ 2015-06-16 13:32                   ` Juergen Gross
  2015-06-16 13:37                   ` [PATCH V4 3/7] libxl: add pvusb API [and 1 more messages] Ian Jackson
  1 sibling, 0 replies; 88+ messages in thread
From: Juergen Gross @ 2015-06-16 13:32 UTC (permalink / raw)
  To: George Dunlap, Ian Jackson
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On 06/16/2015 03:19 PM, George Dunlap wrote:
> On Tue, Jun 16, 2015 at 1:02 PM, Ian Jackson <Ian.Jackson@eu.citrix.com> wrote:
>> George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
>>> So it sounds like we're converging on "Allow multiple ways to specify
>>> the interface", with at least the following fields:
>>> - bus (int - 1,2,3, &c)
>>> - port (string - 2.1.3, &c)
>>> - address/devnum (int)
>>> - vendorid (uint16_t)
>>> - deviceid (uint16_t)
>>
>> You're missing the full device path from that list.  Typically that
>> will include at least one pci bus address.
>
> I'm not sure what constitutes a "full device path".  Is that defined somewhere?
>
> Remember that the path you gave in your previous e-mail isn't the path
> for the *usb device*, it's the path for the *block device*.  It
> contains a PCI address, but it looks like it also contains part of the
> USB topology.  Are you sure that's actually a stable interface, or
> does it just happen that on your hardware the discovery always happens
> in the same order?
>
> On my system /sys/bus/usb/devices/2-3.3 is a link to
> /sys/devices/pci0000:00/0000:00:1d.7/usb2/2-3/2-3.3/.  This contains
> the pci bus address, but it also contains the bus number, which we've
> just said may be unstable across reboots.
>
> I suppose it might be possible to specify <buspci,port> -- the pci
> address of the root bus, and the topology from there.  In theory I
> guess that should be stable?

Hmm, perhaps. On my system I've got:

/sys/devices/pci0000:00/0000:00:14.0/usb3/
/sys/devices/pci0000:00/0000:00:14.0/usb4/

So two busses on one pci bus address. Are usb3 and usb4 always in this
order or are they sometimes just numbered the other way round?


Juergen

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

* Re: [PATCH V4 3/7] libxl: add pvusb API [and 1 more messages]
  2015-06-16 13:19                 ` George Dunlap
  2015-06-16 13:32                   ` Juergen Gross
@ 2015-06-16 13:37                   ` Ian Jackson
  2015-06-16 14:41                     ` George Dunlap
  1 sibling, 1 reply; 88+ messages in thread
From: Ian Jackson @ 2015-06-16 13:37 UTC (permalink / raw)
  To: George Dunlap
  Cc: Jürgen Groß,
	Wei Liu, Ian Campbell, Ian Jackson, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
> Remember that the path you gave in your previous e-mail isn't the path
> for the *usb device*, it's the path for the *block device*.  It
> contains a PCI address, but it looks like it also contains part of the
> USB topology.  Are you sure that's actually a stable interface, or
> does it just happen that on your hardware the discovery always happens
> in the same order?

The block device is (in path terms) underneath the usb device,
obviously.  Not all of that path is relevant to identifying the
USB device.

> On my system /sys/bus/usb/devices/2-3.3 is a link to
> /sys/devices/pci0000:00/0000:00:1d.7/usb2/2-3/2-3.3/.  This contains
> the pci bus address, but it also contains the bus number, which we've
> just said may be unstable across reboots.

You mean the 2 in `usb2' ?  I think that bus number is the bus number
within the controller, not globally.

> I suppose it might be possible to specify <buspci,port> -- the pci
> address of the root bus, and the topology from there.  In theory I
> guess that should be stable?

Yes.  The whole point of paths like this is that they are stable if
the physical topology doesn't change.  So on my netbook

  /dev/disk/by-path/pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0-part1

always refers to the 1st MBR partition on logical device 0 on the USB
storage device plugged into the USB port physically on the front left
of the computer.

> In any case, at the moment you're essentially inventing from whole
> cloth a new way of specifying USB devices that (as far as I know)
> isn't supported by any other program that uses USB.

If you can't specify the device by hardware path, you can't specify it
deterministically.

And as you can see it _is_ supported by other programs that use USB.
"mount" can use it!

I think the hardware path to the controller, at least, should be
treated as an opaque OS-specific string.  It might have a different
format on BSD.

Ian.

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 13:29                     ` George Dunlap
@ 2015-06-16 13:49                       ` Juergen Gross
  2015-06-16 14:06                         ` George Dunlap
  0 siblings, 1 reply; 88+ messages in thread
From: Juergen Gross @ 2015-06-16 13:49 UTC (permalink / raw)
  To: George Dunlap, Ian Jackson
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On 06/16/2015 03:29 PM, George Dunlap wrote:
> On 06/16/2015 02:23 PM, Juergen Gross wrote:
>> On 06/16/2015 03:09 PM, George Dunlap wrote:
>>> On 06/16/2015 02:06 PM, Juergen Gross wrote:
>>>> On 06/16/2015 01:45 PM, Ian Jackson wrote:
>>>>> Juergen Gross writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb
>>>>> API"):
>>>>>> On 06/16/2015 01:10 PM, Ian Jackson wrote:
>>>>>>> AIUI some devices have serial numbers, which means you can
>>>>>>> distinguish
>>>>>>> them ?
>>>>>>
>>>>>> Yes, they have. The question is whether those are different on
>>>>>> multiple
>>>>>> instances? With "lsusb" I've found a device with serial number
>>>>>> 0123456789ABCD. Do you really believe I'm just lucky owning the one
>>>>>> with
>>>>>> such a nice serial number? ;-)
>>>>>
>>>>> Heh.  I think, though, that this suggests that if the user has devices
>>>>> whose serial numbers are actually different, they should be able to
>>>>> specify a device by vid/pid/serial.
>>>>
>>>> I think you are right.
>>>>
>>>> The next question: should this be part of libxl or qemu? It should be
>>>> possible to extend the qemu <vendorId>:<productId> syntax to
>>>> <vendorId>:<productId>:<serial> without too much effort, as libusb
>>>> includes some support to obtain the serial number.
>>>
>>> It doesn't really matter what qemu or pvusb can do, as long as libxl can
>>> convert what it has into something that they can use.  So if libxl is
>>> given vid, pid, and serial (remember, this will be a struct, not a
>>> string), it can look in sysfs and find the bus:addr (which is unique at
>>> any given time) and hand it to qemu  (or the bus-port in the case of
>>> pvusb).
>>
>> Hmm, I'd rather have it all in one place. Putting it in qemu would
>> enable us to handle hotplug as well. A USB device assigned via it's
>> serial to a domU could be automatically passed through by qemu when
>> showing up. This isn't possible today, but we wouldn't have to change
>> libxl again for supporting it, only qemu would have to be adapted.
>
> Look, we're talking here about the libxl interface.  Ian thinks that *at
> the libxl layer* we need to be able to specify all these things.  It
> doesn't matter at this point whether qemu can also do it or not.

When I'm adding new functionality (and this is the case here) I always
try to add it at the level where it should be. qemu already is capable
of finding a USB device by various means and can be extended easily to
support our needs. And please remember, for writing the pvusb backend
I'm already doing changes to qemu.

So why should we add the same functionality to libxl by reading sysfs
instead of letting it do qemu via libusb? And what about BSD? Letting
qemu find the device would avoid two variants in libxl.

> In the future, if we actually implement the "automatically grab this
> device when it shows up" functionality, then yes, having it in qemu
> rather than having a libxl daemon sit around and watch for those things,
> might be handy.  But we can cross that bridge when we come to it.

I would agree if the efforts in libxl would be much smaller than in
qemu. But if the efforts are comparable I'd rather do it in the
component which will make such an enhancement easier.

Just my $0.02


Juergen

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 13:49                       ` Juergen Gross
@ 2015-06-16 14:06                         ` George Dunlap
  2015-06-16 14:20                           ` Juergen Gross
  0 siblings, 1 reply; 88+ messages in thread
From: George Dunlap @ 2015-06-16 14:06 UTC (permalink / raw)
  To: Juergen Gross, Ian Jackson
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On 06/16/2015 02:49 PM, Juergen Gross wrote:
> On 06/16/2015 03:29 PM, George Dunlap wrote:
>> On 06/16/2015 02:23 PM, Juergen Gross wrote:
>>> Hmm, I'd rather have it all in one place. Putting it in qemu would
>>> enable us to handle hotplug as well. A USB device assigned via it's
>>> serial to a domU could be automatically passed through by qemu when
>>> showing up. This isn't possible today, but we wouldn't have to change
>>> libxl again for supporting it, only qemu would have to be adapted.
>>
>> Look, we're talking here about the libxl interface.  Ian thinks that *at
>> the libxl layer* we need to be able to specify all these things.  It
>> doesn't matter at this point whether qemu can also do it or not.
> 
> When I'm adding new functionality (and this is the case here) I always
> try to add it at the level where it should be. qemu already is capable
> of finding a USB device by various means and can be extended easily to
> support our needs. And please remember, for writing the pvusb backend
> I'm already doing changes to qemu.
> 
> So why should we add the same functionality to libxl by reading sysfs
> instead of letting it do qemu via libusb? And what about BSD? Letting
> qemu find the device would avoid two variants in libxl.

If the libxl interface only has "bus" and "port", then it doesn't matter
what qemu can do -- the caller has no way of asking qemu to watch for
vid:did:serial.

If libxl has vid:did:serial in the interface, then it's only an
implementation detail whether we pass that into qemu or whether we pass
some other way of uniquely indentifying a particular device.  And given
that no *current* versions of qemu support vid:did:serial, the most
sensible way to implement this would be to have libxl do the conversion
and send over bus:addr -- that way when you update libxl you get that
functionality regardless of whether qemu has it.

Unless you're suggesting that the libxl interface should be a string
that we just pass verbatim to qemu.  If that's what you mean, it's a
complete non-starter, and I'm sure Ian will agree with me.  There's no
way that we can provide any interface consistency or any documentation
of what this string does if it boils down to "This does whatever the
version of qemu you happen to be running does".

>> In the future, if we actually implement the "automatically grab this
>> device when it shows up" functionality, then yes, having it in qemu
>> rather than having a libxl daemon sit around and watch for those things,
>> might be handy.  But we can cross that bridge when we come to it.
> 
> I would agree if the efforts in libxl would be much smaller than in
> qemu. But if the efforts are comparable I'd rather do it in the
> component which will make such an enhancement easier.

They're both small, so this is really bikeshedding at the moment.  The
most important question is the interface: do we include vid:did:serial
in the libxl interface.  Since you want qemu to do that, I take it that
your answer to that is "yes".

When we have patches submitted, we can discuss whether libxl should only
support the (as-yet unreleased) versions of qemu that do the search
themselves, or whether they should support all versions of qemu-xen.
(The answer seems pretty obvious to me...)

 -George

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 14:06                         ` George Dunlap
@ 2015-06-16 14:20                           ` Juergen Gross
  2015-06-16 14:37                             ` George Dunlap
  2015-06-17 11:34                             ` Ian Campbell
  0 siblings, 2 replies; 88+ messages in thread
From: Juergen Gross @ 2015-06-16 14:20 UTC (permalink / raw)
  To: George Dunlap, Ian Jackson
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On 06/16/2015 04:06 PM, George Dunlap wrote:
> On 06/16/2015 02:49 PM, Juergen Gross wrote:
>> On 06/16/2015 03:29 PM, George Dunlap wrote:
>>> On 06/16/2015 02:23 PM, Juergen Gross wrote:
>>>> Hmm, I'd rather have it all in one place. Putting it in qemu would
>>>> enable us to handle hotplug as well. A USB device assigned via it's
>>>> serial to a domU could be automatically passed through by qemu when
>>>> showing up. This isn't possible today, but we wouldn't have to change
>>>> libxl again for supporting it, only qemu would have to be adapted.
>>>
>>> Look, we're talking here about the libxl interface.  Ian thinks that *at
>>> the libxl layer* we need to be able to specify all these things.  It
>>> doesn't matter at this point whether qemu can also do it or not.
>>
>> When I'm adding new functionality (and this is the case here) I always
>> try to add it at the level where it should be. qemu already is capable
>> of finding a USB device by various means and can be extended easily to
>> support our needs. And please remember, for writing the pvusb backend
>> I'm already doing changes to qemu.
>>
>> So why should we add the same functionality to libxl by reading sysfs
>> instead of letting it do qemu via libusb? And what about BSD? Letting
>> qemu find the device would avoid two variants in libxl.
>
> If the libxl interface only has "bus" and "port", then it doesn't matter
> what qemu can do -- the caller has no way of asking qemu to watch for
> vid:did:serial.
>
> If libxl has vid:did:serial in the interface, then it's only an
> implementation detail whether we pass that into qemu or whether we pass
> some other way of uniquely indentifying a particular device.  And given
> that no *current* versions of qemu support vid:did:serial, the most
> sensible way to implement this would be to have libxl do the conversion
> and send over bus:addr -- that way when you update libxl you get that
> functionality regardless of whether qemu has it.
>
> Unless you're suggesting that the libxl interface should be a string
> that we just pass verbatim to qemu.  If that's what you mean, it's a
> complete non-starter, and I'm sure Ian will agree with me.  There's no
> way that we can provide any interface consistency or any documentation
> of what this string does if it boils down to "This does whatever the
> version of qemu you happen to be running does".

No, I didn't expect libxl to just pass an arbitrary string to qemu.
My point was to avoid the sysfs accesses in libxl in order to support
BSD as well and to reduce the complexity.

>>> In the future, if we actually implement the "automatically grab this
>>> device when it shows up" functionality, then yes, having it in qemu
>>> rather than having a libxl daemon sit around and watch for those things,
>>> might be handy.  But we can cross that bridge when we come to it.
>>
>> I would agree if the efforts in libxl would be much smaller than in
>> qemu. But if the efforts are comparable I'd rather do it in the
>> component which will make such an enhancement easier.
>
> They're both small, so this is really bikeshedding at the moment.  The
> most important question is the interface: do we include vid:did:serial
> in the libxl interface.  Since you want qemu to do that, I take it that
> your answer to that is "yes".

Correct.

> When we have patches submitted, we can discuss whether libxl should only
> support the (as-yet unreleased) versions of qemu that do the search
> themselves, or whether they should support all versions of qemu-xen.
> (The answer seems pretty obvious to me...)

May be I made one wrong assumption: I thought adding USB-passthrough for
HVM domains would require qemu changes as well. If this is not the case
I can understand your reasoning.


Juergen

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 14:20                           ` Juergen Gross
@ 2015-06-16 14:37                             ` George Dunlap
  2015-06-17 11:34                             ` Ian Campbell
  1 sibling, 0 replies; 88+ messages in thread
From: George Dunlap @ 2015-06-16 14:37 UTC (permalink / raw)
  To: Juergen Gross, Ian Jackson
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On 06/16/2015 03:20 PM, Juergen Gross wrote:
> On 06/16/2015 04:06 PM, George Dunlap wrote:
>> On 06/16/2015 02:49 PM, Juergen Gross wrote:
>>> On 06/16/2015 03:29 PM, George Dunlap wrote:
>>>> On 06/16/2015 02:23 PM, Juergen Gross wrote:
>>>>> Hmm, I'd rather have it all in one place. Putting it in qemu would
>>>>> enable us to handle hotplug as well. A USB device assigned via it's
>>>>> serial to a domU could be automatically passed through by qemu when
>>>>> showing up. This isn't possible today, but we wouldn't have to change
>>>>> libxl again for supporting it, only qemu would have to be adapted.
>>>>
>>>> Look, we're talking here about the libxl interface.  Ian thinks that
>>>> *at
>>>> the libxl layer* we need to be able to specify all these things.  It
>>>> doesn't matter at this point whether qemu can also do it or not.
>>>
>>> When I'm adding new functionality (and this is the case here) I always
>>> try to add it at the level where it should be. qemu already is capable
>>> of finding a USB device by various means and can be extended easily to
>>> support our needs. And please remember, for writing the pvusb backend
>>> I'm already doing changes to qemu.
>>>
>>> So why should we add the same functionality to libxl by reading sysfs
>>> instead of letting it do qemu via libusb? And what about BSD? Letting
>>> qemu find the device would avoid two variants in libxl.
>>
>> If the libxl interface only has "bus" and "port", then it doesn't matter
>> what qemu can do -- the caller has no way of asking qemu to watch for
>> vid:did:serial.
>>
>> If libxl has vid:did:serial in the interface, then it's only an
>> implementation detail whether we pass that into qemu or whether we pass
>> some other way of uniquely indentifying a particular device.  And given
>> that no *current* versions of qemu support vid:did:serial, the most
>> sensible way to implement this would be to have libxl do the conversion
>> and send over bus:addr -- that way when you update libxl you get that
>> functionality regardless of whether qemu has it.
>>
>> Unless you're suggesting that the libxl interface should be a string
>> that we just pass verbatim to qemu.  If that's what you mean, it's a
>> complete non-starter, and I'm sure Ian will agree with me.  There's no
>> way that we can provide any interface consistency or any documentation
>> of what this string does if it boils down to "This does whatever the
>> version of qemu you happen to be running does".
> 
> No, I didn't expect libxl to just pass an arbitrary string to qemu.
> My point was to avoid the sysfs accesses in libxl in order to support
> BSD as well and to reduce the complexity.
> 
>>>> In the future, if we actually implement the "automatically grab this
>>>> device when it shows up" functionality, then yes, having it in qemu
>>>> rather than having a libxl daemon sit around and watch for those
>>>> things,
>>>> might be handy.  But we can cross that bridge when we come to it.
>>>
>>> I would agree if the efforts in libxl would be much smaller than in
>>> qemu. But if the efforts are comparable I'd rather do it in the
>>> component which will make such an enhancement easier.
>>
>> They're both small, so this is really bikeshedding at the moment.  The
>> most important question is the interface: do we include vid:did:serial
>> in the libxl interface.  Since you want qemu to do that, I take it that
>> your answer to that is "yes".
> 
> Correct.
> 
>> When we have patches submitted, we can discuss whether libxl should only
>> support the (as-yet unreleased) versions of qemu that do the search
>> themselves, or whether they should support all versions of qemu-xen.
>> (The answer seems pretty obvious to me...)
> 
> May be I made one wrong assumption: I thought adding USB-passthrough for
> HVM domains would require qemu changes as well. If this is not the case
> I can understand your reasoning.

Oh, right.  No, getting HVM hotplug working over QMP was pretty
straightforward; probably only a week's work.  It's been the interface
that has been the real difficult bit.

There are some things that would be nicer to implement in qemu.  Right
now there's no way to *query* what devices have been plugged in; my
patch series had to store information in xenstore.

At some point in the future, it might make sense for libxl to mainly
just ferry the options back and forth to qemu; even then I'm not sure.
In any case it's an implementation detail that can be changed at any
time.  It's the interface we have to be really careful about.

 -George

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

* Re: [PATCH V4 3/7] libxl: add pvusb API [and 1 more messages]
  2015-06-16 13:37                   ` [PATCH V4 3/7] libxl: add pvusb API [and 1 more messages] Ian Jackson
@ 2015-06-16 14:41                     ` George Dunlap
  2015-06-16 15:58                       ` Sander Eikelenboom
  2015-06-16 15:59                       ` Ian Jackson
  0 siblings, 2 replies; 88+ messages in thread
From: George Dunlap @ 2015-06-16 14:41 UTC (permalink / raw)
  To: Ian Jackson
  Cc: Jürgen Groß,
	Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig,
	Simon Cao

On 06/16/2015 02:37 PM, Ian Jackson wrote:
> George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
>> Remember that the path you gave in your previous e-mail isn't the path
>> for the *usb device*, it's the path for the *block device*.  It
>> contains a PCI address, but it looks like it also contains part of the
>> USB topology.  Are you sure that's actually a stable interface, or
>> does it just happen that on your hardware the discovery always happens
>> in the same order?
> 
> The block device is (in path terms) underneath the usb device,
> obviously.  Not all of that path is relevant to identifying the
> USB device.
> 
>> On my system /sys/bus/usb/devices/2-3.3 is a link to
>> /sys/devices/pci0000:00/0000:00:1d.7/usb2/2-3/2-3.3/.  This contains
>> the pci bus address, but it also contains the bus number, which we've
>> just said may be unstable across reboots.
> 
> You mean the 2 in `usb2' ?  I think that bus number is the bus number
> within the controller, not globally.

On the contrary:

$ ls -l usb*
lrwxrwxrwx 1 root root 0 Jun 15 10:14 usb1 ->
../../../devices/pci0000:00/0000:00:1a.7/usb1/
lrwxrwxrwx 1 root root 0 Jun 15 10:14 usb2 ->
../../../devices/pci0000:00/0000:00:1d.7/usb2/
lrwxrwxrwx 1 root root 0 Jun 15 10:14 usb3 ->
../../../devices/pci0000:00/0000:00:1a.0/usb3/
lrwxrwxrwx 1 root root 0 Jun 15 10:14 usb4 ->
../../../devices/pci0000:00/0000:00:1a.1/usb4/
lrwxrwxrwx 1 root root 0 Jun 15 10:14 usb5 ->
../../../devices/pci0000:00/0000:00:1a.2/usb5/
lrwxrwxrwx 1 root root 0 Jun 15 10:14 usb6 ->
../../../devices/pci0000:00/0000:00:1d.0/usb6/
lrwxrwxrwx 1 root root 0 Jun 15 10:14 usb7 ->
../../../devices/pci0000:00/0000:00:1d.1/usb7/
lrwxrwxrwx 1 root root 0 Jun 15 10:14 usb8 ->
../../../devices/pci0000:00/0000:00:1d.2/usb8/

$ ls /sys//devices/pci0000:00/0000:00:1d.7/ | grep usb
usb2/

In other words, the global bus enumeration leaks its way into the device
path; which means at very least the sysfs device path is potentially
unstable across reboots even if you include the pci controller it's on.

>> I suppose it might be possible to specify <buspci,port> -- the pci
>> address of the root bus, and the topology from there.  In theory I
>> guess that should be stable?
> 
> Yes.  The whole point of paths like this is that they are stable if
> the physical topology doesn't change.  So on my netbook
> 
>   /dev/disk/by-path/pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0-part1
> 
> always refers to the 1st MBR partition on logical device 0 on the USB
> storage device plugged into the USB port physically on the front left
> of the computer.

That would be great if it were true, but I'm not convinced that the
above path doesn't include a globally-enumerated bus number, which might
change across reboots if it's enumerated in a different order.

It may be that the format above is *not* based on the sysfs path of the
device; that the '0' immediately after the USB means "the first (and
perhaps only) controller at this PCI address".  In which case, yes,
having a string like this might be a unique identifier for a particular
port that would be stable across reboots.  That needs some investigation.

>> In any case, at the moment you're essentially inventing from whole
>> cloth a new way of specifying USB devices that (as far as I know)
>> isn't supported by any other program that uses USB.
> 
> If you can't specify the device by hardware path, you can't specify it
> deterministically.
> 
> And as you can see it _is_ supported by other programs that use USB.
> "mount" can use it!

Mount doesn't know anything about USB devices; all it knows are block
devices.  You might as well say that 'ls' knows about USB devices
because it can read files on a filesystem that resides on a USB stick.

I'm talking about programs that explicitly manipulate USB devices -- in
particular, those that may pass them through to a guest or seize them,
like libvirt, qemu, virtualbox, &c.

I'm not opposed to doing something new if it really is better.  But when
you find that a dozen other projects before you have done things one
way, you should at least take care before you decide to do something
radically different, to make sure that it's because you actually have
something better, and not because you've just missed something.

> I think the hardware path to the controller, at least, should be
> treated as an opaque OS-specific string.  It might have a different
> format on BSD.

If we can make an actual path that's stable across reboots, that would
certainly be a good thing.  But if it's not stable across reboots, it
has no advantage over the bus-port[.port.port] interface.

 -George

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 11:25           ` Juergen Gross
  2015-06-16 11:45             ` George Dunlap
  2015-06-16 11:45             ` [PATCH V4 3/7] libxl: add pvusb API Ian Jackson
@ 2015-06-16 15:38             ` George Dunlap
  2 siblings, 0 replies; 88+ messages in thread
From: George Dunlap @ 2015-06-16 15:38 UTC (permalink / raw)
  To: Juergen Gross
  Cc: Wei Liu, Ian Campbell, Ian Jackson, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

On Tue, Jun 16, 2015 at 12:25 PM, Juergen Gross <jgross@suse.com> wrote:
> Yes, they have. The question is whether those are different on multiple
> instances? With "lsusb" I've found a device with serial number
> 0123456789ABCD. Do you really believe I'm just lucky owning the one with
> such a nice serial number? ;-)

FWIW apparently the spec for USB printers requires a unique serial
number; so there are probably cases where serial number is actually
useful.

 -George

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

* Re: [PATCH V4 3/7] libxl: add pvusb API [and 1 more messages]
  2015-06-16 14:41                     ` George Dunlap
@ 2015-06-16 15:58                       ` Sander Eikelenboom
  2015-06-16 15:59                       ` Ian Jackson
  1 sibling, 0 replies; 88+ messages in thread
From: Sander Eikelenboom @ 2015-06-16 15:58 UTC (permalink / raw)
  To: George Dunlap
  Cc: Jürgen Groß,
	Wei Liu, Ian Campbell, Ian Jackson, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao


Tuesday, June 16, 2015, 4:41:52 PM, you wrote:

> On 06/16/2015 02:37 PM, Ian Jackson wrote:
>> George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
>>> Remember that the path you gave in your previous e-mail isn't the path
>>> for the *usb device*, it's the path for the *block device*.  It
>>> contains a PCI address, but it looks like it also contains part of the
>>> USB topology.  Are you sure that's actually a stable interface, or
>>> does it just happen that on your hardware the discovery always happens
>>> in the same order?
>> 
>> The block device is (in path terms) underneath the usb device,
>> obviously.  Not all of that path is relevant to identifying the
>> USB device.
>> 
>>> On my system /sys/bus/usb/devices/2-3.3 is a link to
>>> /sys/devices/pci0000:00/0000:00:1d.7/usb2/2-3/2-3.3/.  This contains
>>> the pci bus address, but it also contains the bus number, which we've
>>> just said may be unstable across reboots.
>> 
>> You mean the 2 in `usb2' ?  I think that bus number is the bus number
>> within the controller, not globally.

> On the contrary:

> $ ls -l usb*
> lrwxrwxrwx 1 root root 0 Jun 15 10:14 usb1 ->
> ../../../devices/pci0000:00/0000:00:1a.7/usb1/
> lrwxrwxrwx 1 root root 0 Jun 15 10:14 usb2 ->
> ../../../devices/pci0000:00/0000:00:1d.7/usb2/
> lrwxrwxrwx 1 root root 0 Jun 15 10:14 usb3 ->
> ../../../devices/pci0000:00/0000:00:1a.0/usb3/
> lrwxrwxrwx 1 root root 0 Jun 15 10:14 usb4 ->
> ../../../devices/pci0000:00/0000:00:1a.1/usb4/
> lrwxrwxrwx 1 root root 0 Jun 15 10:14 usb5 ->
> ../../../devices/pci0000:00/0000:00:1a.2/usb5/
> lrwxrwxrwx 1 root root 0 Jun 15 10:14 usb6 ->
> ../../../devices/pci0000:00/0000:00:1d.0/usb6/
> lrwxrwxrwx 1 root root 0 Jun 15 10:14 usb7 ->
> ../../../devices/pci0000:00/0000:00:1d.1/usb7/
> lrwxrwxrwx 1 root root 0 Jun 15 10:14 usb8 ->
> ../../../devices/pci0000:00/0000:00:1d.2/usb8/

> $ ls /sys//devices/pci0000:00/0000:00:1d.7/ | grep usb
> usb2/

> In other words, the global bus enumeration leaks its way into the device
> path; which means at very least the sysfs device path is potentially
> unstable across reboots even if you include the pci controller it's on.

>>> I suppose it might be possible to specify <buspci,port> -- the pci
>>> address of the root bus, and the topology from there.  In theory I
>>> guess that should be stable?
>> 
>> Yes.  The whole point of paths like this is that they are stable if
>> the physical topology doesn't change.  So on my netbook
>> 
>>   /dev/disk/by-path/pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0-part1
>> 
>> always refers to the 1st MBR partition on logical device 0 on the USB
>> storage device plugged into the USB port physically on the front left
>> of the computer.

> That would be great if it were true, but I'm not convinced that the
> above path doesn't include a globally-enumerated bus number, which might
> change across reboots if it's enumerated in a different order.

> It may be that the format above is *not* based on the sysfs path of the
> device; that the '0' immediately after the USB means "the first (and
> perhaps only) controller at this PCI address".  In which case, yes,
> having a string like this might be a unique identifier for a particular
> port that would be stable across reboots.  That needs some investigation.

>>> In any case, at the moment you're essentially inventing from whole
>>> cloth a new way of specifying USB devices that (as far as I know)
>>> isn't supported by any other program that uses USB.
>> 
>> If you can't specify the device by hardware path, you can't specify it
>> deterministically.
>> 
>> And as you can see it _is_ supported by other programs that use USB.
>> "mount" can use it!

> Mount doesn't know anything about USB devices; all it knows are block
> devices.  You might as well say that 'ls' knows about USB devices
> because it can read files on a filesystem that resides on a USB stick.

> I'm talking about programs that explicitly manipulate USB devices -- in
> particular, those that may pass them through to a guest or seize them,
> like libvirt, qemu, virtualbox, &c.

> I'm not opposed to doing something new if it really is better.  But when
> you find that a dozen other projects before you have done things one
> way, you should at least take care before you decide to do something
> radically different, to make sure that it's because you actually have
> something better, and not because you've just missed something.

>> I think the hardware path to the controller, at least, should be
>> treated as an opaque OS-specific string.  It might have a different
>> format on BSD.

> If we can make an actual path that's stable across reboots, that would
> certainly be a good thing.  But if it's not stable across reboots, it
> has no advantage over the bus-port[.port.port] interface.
>  -George

Would a symlink to a sysfs or device node entry also be allowed ?

That way you can leverage the power of tools like udev or other device managers
and script the linkage based on a multitude of device properties 
(f.e. serial numbers, manufacturer id, device id, etc.).

Which can make it persistent across reboots or do other funky stuff with it,
according to ones needs.

--
Sander

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

* Re: [PATCH V4 3/7] libxl: add pvusb API [and 1 more messages]
  2015-06-16 14:41                     ` George Dunlap
  2015-06-16 15:58                       ` Sander Eikelenboom
@ 2015-06-16 15:59                       ` Ian Jackson
  2015-06-16 16:34                         ` George Dunlap
  1 sibling, 1 reply; 88+ messages in thread
From: Ian Jackson @ 2015-06-16 15:59 UTC (permalink / raw)
  To: George Dunlap
  Cc: Jürgen Groß,
	Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig,
	Simon Cao

George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API [and 1 more messages]"):
> On 06/16/2015 02:37 PM, Ian Jackson wrote:
> > George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"> >> /sys/devices/pci0000:00/0000:00:1d.7/usb2/2-3/2-3.3/.  This contains
> >> the pci bus address, but it also contains the bus number, which we've
> >> just said may be unstable across reboots.
> > 
> > You mean the 2 in `usb2' ?  I think that bus number is the bus number
> > within the controller, not globally.
> 
> On the contrary:
> [...]

Oh dear.

> In other words, the global bus enumeration leaks its way into the device
> path; which means at very least the sysfs device path is potentially
> unstable across reboots even if you include the pci controller it's on.

How unhelpful.

> > Yes.  The whole point of paths like this is that they are stable if
> > the physical topology doesn't change.  So on my netbook
> > 
> >   /dev/disk/by-path/pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0-part1
> > 
> > always refers to the 1st MBR partition on logical device 0 on the USB
> > storage device plugged into the USB port physically on the front left
> > of the computer.
> 
> That would be great if it were true, but I'm not convinced that the
> above path doesn't include a globally-enumerated bus number, which might
> change across reboots if it's enumerated in a different order.
> 
> It may be that the format above is *not* based on the sysfs path of the
> device; that the '0' immediately after the USB means "the first (and
> perhaps only) controller at this PCI address".  In which case, yes,
> having a string like this might be a unique identifier for a particular
> port that would be stable across reboots.  That needs some investigation.

That does seem to be the case:

zealot:~> ls -al /dev/disk/by-path/pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0-part1
lrwxrwxrwx 1 root root 10 Jun 16 16:45 /dev/disk/by-path/pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0-part1 -> ../../sdc1
zealot:~> ls -al /sys/class/block/sdc
lrwxrwxrwx 1 root root 0 Jun 16 16:45 /sys/class/block/sdc -> ../../devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0/host19/target19:0:0/19:0:0:0/block/sdc/
zealot:~>

Observe that the sysfs path contains not only `usb1' (which isn't
stable) but also `host19' which is also not stable.  If I unplug and
replug:

zealot:~> ls -al /dev/disk/by-path/pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0-part1
lrwxrwxrwx 1 root root 10 Jun 16 16:49 /dev/disk/by-path/pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0-part1 -> ../../sdc1
zealot:~> ls -al /sys/class/block/sdc
lrwxrwxrwx 1 root root 0 Jun 16 16:50 /sys/class/block/sdc -> ../../devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0/host20/target20:0:0/20:0:0:0/block/sdc/
zealot:~>

Looking at the output of udevadm monitor --property for sdc1 (on
another plug):

DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0/host22/target22:0:0/22:0:0:0/block/sdc/sdc1
ID_PATH=pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0
ID_PATH_TAG=pci-0000_00_1d_7-usb-0_1_1_0-scsi-0_0_0_0

I don't know where that ID_PATH comes from.

I can't seem to find anything relevant in my
/sys/devices/pci0000:00/0000:00:1d.7

> > I think the hardware path to the controller, at least, should be
> > treated as an opaque OS-specific string.  It might have a different
> > format on BSD.
> 
> If we can make an actual path that's stable across reboots, that would
> certainly be a good thing.  But if it's not stable across reboots, it
> has no advantage over the bus-port[.port.port] interface.

Yes.

Ian.

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 11:21           ` George Dunlap
@ 2015-06-16 16:32             ` Ian Jackson
  2015-06-16 16:39               ` George Dunlap
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Jackson @ 2015-06-16 16:32 UTC (permalink / raw)
  To: George Dunlap
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

I have just discovered that the value used in /dev/disk/by-path is not
from sysfs, or at least, not directly.

udev cobbles it together with a bunch of string mangling, from
information mostly from sysfs.  There is no corresponding thing for
usb devices.

So Linux, the kernel, does not actually provide a stable device name
string.  This is obviously absurd, but I think fixing it is out of
scope.

I suggest we provide a facility to allow a user to specify a fnmatch
glob pattern to be applied to the sysfs path.  That way when they see
their device is
  /devices/pci0000:00/0000:00:1d.7/usb1/1-1
they can write
  /devices/pci0000:00/0000:00:1d.7/usb*/*-1
which will match exactly and only the right thing.

Ian.

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

* Re: [PATCH V4 3/7] libxl: add pvusb API [and 1 more messages]
  2015-06-16 15:59                       ` Ian Jackson
@ 2015-06-16 16:34                         ` George Dunlap
  2015-06-17  3:59                           ` Juergen Gross
  0 siblings, 1 reply; 88+ messages in thread
From: George Dunlap @ 2015-06-16 16:34 UTC (permalink / raw)
  To: Ian Jackson
  Cc: Jürgen Groß,
	Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig,
	Simon Cao

On Tue, Jun 16, 2015 at 4:59 PM, Ian Jackson <Ian.Jackson@eu.citrix.com> wrote:
> George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API [and 1 more messages]"):
>> > Yes.  The whole point of paths like this is that they are stable if
>> > the physical topology doesn't change.  So on my netbook
>> >
>> >   /dev/disk/by-path/pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0-part1
>> >
>> > always refers to the 1st MBR partition on logical device 0 on the USB
>> > storage device plugged into the USB port physically on the front left
>> > of the computer.
>>
>> That would be great if it were true, but I'm not convinced that the
>> above path doesn't include a globally-enumerated bus number, which might
>> change across reboots if it's enumerated in a different order.
>>
>> It may be that the format above is *not* based on the sysfs path of the
>> device; that the '0' immediately after the USB means "the first (and
>> perhaps only) controller at this PCI address".  In which case, yes,
>> having a string like this might be a unique identifier for a particular
>> port that would be stable across reboots.  That needs some investigation.
>
> That does seem to be the case:

What seems to be the case -- that it contains the global bus, or not?

> Looking at the output of udevadm monitor --property for sdc1 (on
> another plug):
>
> DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0/host22/target22:0:0/22:0:0:0/block/sdc/sdc1
> ID_PATH=pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0
> ID_PATH_TAG=pci-0000_00_1d_7-usb-0_1_1_0-scsi-0_0_0_0
>
> I don't know where that ID_PATH comes from.

It looks like that's constructed in udev:

http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-path_id.c

See handle_usb() (line 542) in particular.

If I'm reading it right, what it basically does it take the
[bus]-[port], and replace it with usb-0:[port].  (IOW, the '0' is
hard-coded.)

Also, if I'm reading it right, this won't work properly for Juergen's
system that has two USB devices at the same pci address -- they'll
both end up resolving to [pciaddr]-usb-0:[whatever].

Juergen -- can you give this a try?  Run "udevadm info" on the two USB
busses that share the same PCI slot, and see if the ID_PATH is the
same for both?

 -George

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 16:32             ` Ian Jackson
@ 2015-06-16 16:39               ` George Dunlap
  2015-06-16 16:51                 ` Ross Philipson
  0 siblings, 1 reply; 88+ messages in thread
From: George Dunlap @ 2015-06-16 16:39 UTC (permalink / raw)
  To: Ian Jackson
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On 06/16/2015 05:32 PM, Ian Jackson wrote:
> I have just discovered that the value used in /dev/disk/by-path is not
> from sysfs, or at least, not directly.
> 
> udev cobbles it together with a bunch of string mangling, from
> information mostly from sysfs.  There is no corresponding thing for
> usb devices.
> 
> So Linux, the kernel, does not actually provide a stable device name
> string.  This is obviously absurd, but I think fixing it is out of
> scope.
> 
> I suggest we provide a facility to allow a user to specify a fnmatch
> glob pattern to be applied to the sysfs path.  That way when they see
> their device is
>   /devices/pci0000:00/0000:00:1d.7/usb1/1-1
> they can write
>   /devices/pci0000:00/0000:00:1d.7/usb*/*-1
> which will match exactly and only the right thing.

What about Juergen's system that has two usbN directories in a single
pci node?

Quoting:
---
Hmm, perhaps. On my system I've got:

/sys/devices/pci0000:00/0000:00:14.0/usb3/
/sys/devices/pci0000:00/0000:00:14.0/usb4/

So two busses on one pci bus address. Are usb3 and usb4 always in this
order or are they sometimes just numbered the other way round?
---

Assuming that usb3 and usb4 are actually distinct busses, and they might
both have something plugged into port; in which case a glob like this:

devices/pci0000:00/0000:00:14.0/usb*/*-1

Might match both of the following:

/sys/devices/pci0000:00/0000:00:14.0/usb3/3-1
/sys/devices/pci0000:00/0000:00:14.0/usb4/4-1

 -George

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 16:39               ` George Dunlap
@ 2015-06-16 16:51                 ` Ross Philipson
  2015-06-17  4:03                   ` Jürgen Groß
  0 siblings, 1 reply; 88+ messages in thread
From: Ross Philipson @ 2015-06-16 16:51 UTC (permalink / raw)
  To: George Dunlap, Ian Jackson
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On 06/16/2015 12:39 PM, George Dunlap wrote:
> On 06/16/2015 05:32 PM, Ian Jackson wrote:
>> I have just discovered that the value used in /dev/disk/by-path is not
>> from sysfs, or at least, not directly.
>>
>> udev cobbles it together with a bunch of string mangling, from
>> information mostly from sysfs.  There is no corresponding thing for
>> usb devices.
>>
>> So Linux, the kernel, does not actually provide a stable device name
>> string.  This is obviously absurd, but I think fixing it is out of
>> scope.
>>
>> I suggest we provide a facility to allow a user to specify a fnmatch
>> glob pattern to be applied to the sysfs path.  That way when they see
>> their device is
>>    /devices/pci0000:00/0000:00:1d.7/usb1/1-1
>> they can write
>>    /devices/pci0000:00/0000:00:1d.7/usb*/*-1
>> which will match exactly and only the right thing.
>
> What about Juergen's system that has two usbN directories in a single
> pci node?
>
> Quoting:
> ---
> Hmm, perhaps. On my system I've got:
>
> /sys/devices/pci0000:00/0000:00:14.0/usb3/
> /sys/devices/pci0000:00/0000:00:14.0/usb4/
>
> So two busses on one pci bus address. Are usb3 and usb4 always in this
> order or are they sometimes just numbered the other way round?
> ---
>
> Assuming that usb3 and usb4 are actually distinct busses, and they might
> both have something plugged into port; in which case a glob like this:
>
> devices/pci0000:00/0000:00:14.0/usb*/*-1
>
> Might match both of the following:
>
> /sys/devices/pci0000:00/0000:00:14.0/usb3/3-1
> /sys/devices/pci0000:00/0000:00:14.0/usb4/4-1

Is that an xHCI host controller? If so that might be how the system 
represents the 2 logical (USB2/USB3) root hubs - each as its own 
separate bus.

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


-- 
Ross Philipson

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

* Re: [PATCH V4 3/7] libxl: add pvusb API [and 1 more messages]
  2015-06-16 16:34                         ` George Dunlap
@ 2015-06-17  3:59                           ` Juergen Gross
  2015-06-17 10:27                             ` George Dunlap
  0 siblings, 1 reply; 88+ messages in thread
From: Juergen Gross @ 2015-06-17  3:59 UTC (permalink / raw)
  To: George Dunlap, Ian Jackson
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On 06/16/2015 06:34 PM, George Dunlap wrote:
> On Tue, Jun 16, 2015 at 4:59 PM, Ian Jackson <Ian.Jackson@eu.citrix.com> wrote:
>> George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API [and 1 more messages]"):
>>>> Yes.  The whole point of paths like this is that they are stable if
>>>> the physical topology doesn't change.  So on my netbook
>>>>
>>>>    /dev/disk/by-path/pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0-part1
>>>>
>>>> always refers to the 1st MBR partition on logical device 0 on the USB
>>>> storage device plugged into the USB port physically on the front left
>>>> of the computer.
>>>
>>> That would be great if it were true, but I'm not convinced that the
>>> above path doesn't include a globally-enumerated bus number, which might
>>> change across reboots if it's enumerated in a different order.
>>>
>>> It may be that the format above is *not* based on the sysfs path of the
>>> device; that the '0' immediately after the USB means "the first (and
>>> perhaps only) controller at this PCI address".  In which case, yes,
>>> having a string like this might be a unique identifier for a particular
>>> port that would be stable across reboots.  That needs some investigation.
>>
>> That does seem to be the case:
>
> What seems to be the case -- that it contains the global bus, or not?
>
>> Looking at the output of udevadm monitor --property for sdc1 (on
>> another plug):
>>
>> DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0/host22/target22:0:0/22:0:0:0/block/sdc/sdc1
>> ID_PATH=pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0
>> ID_PATH_TAG=pci-0000_00_1d_7-usb-0_1_1_0-scsi-0_0_0_0
>>
>> I don't know where that ID_PATH comes from.
>
> It looks like that's constructed in udev:
>
> http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-path_id.c
>
> See handle_usb() (line 542) in particular.
>
> If I'm reading it right, what it basically does it take the
> [bus]-[port], and replace it with usb-0:[port].  (IOW, the '0' is
> hard-coded.)
>
> Also, if I'm reading it right, this won't work properly for Juergen's
> system that has two USB devices at the same pci address -- they'll
> both end up resolving to [pciaddr]-usb-0:[whatever].
>
> Juergen -- can you give this a try?  Run "udevadm info" on the two USB
> busses that share the same PCI slot, and see if the ID_PATH is the
> same for both?

This was the correct question. :-)

The ID_PATH is the same, but:

It turns out that the two busses are for one physical hcd. One is the
bus for USB 3.0, the other one for USB 2.0. I guess the bus is just
selected by the capability of the plugged in device.

So the [port] in "usb-0:[port]" is unique across the two logical
busses.


Juergen

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 16:51                 ` Ross Philipson
@ 2015-06-17  4:03                   ` Jürgen Groß
  2015-06-17 13:48                     ` Ross Philipson
  0 siblings, 1 reply; 88+ messages in thread
From: Jürgen Groß @ 2015-06-17  4:03 UTC (permalink / raw)
  To: Ross Philipson, George Dunlap, Ian Jackson
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On 06/16/2015 06:51 PM, Ross Philipson wrote:
> On 06/16/2015 12:39 PM, George Dunlap wrote:
>> On 06/16/2015 05:32 PM, Ian Jackson wrote:
>>> I have just discovered that the value used in /dev/disk/by-path is not
>>> from sysfs, or at least, not directly.
>>>
>>> udev cobbles it together with a bunch of string mangling, from
>>> information mostly from sysfs.  There is no corresponding thing for
>>> usb devices.
>>>
>>> So Linux, the kernel, does not actually provide a stable device name
>>> string.  This is obviously absurd, but I think fixing it is out of
>>> scope.
>>>
>>> I suggest we provide a facility to allow a user to specify a fnmatch
>>> glob pattern to be applied to the sysfs path.  That way when they see
>>> their device is
>>>    /devices/pci0000:00/0000:00:1d.7/usb1/1-1
>>> they can write
>>>    /devices/pci0000:00/0000:00:1d.7/usb*/*-1
>>> which will match exactly and only the right thing.
>>
>> What about Juergen's system that has two usbN directories in a single
>> pci node?
>>
>> Quoting:
>> ---
>> Hmm, perhaps. On my system I've got:
>>
>> /sys/devices/pci0000:00/0000:00:14.0/usb3/
>> /sys/devices/pci0000:00/0000:00:14.0/usb4/
>>
>> So two busses on one pci bus address. Are usb3 and usb4 always in this
>> order or are they sometimes just numbered the other way round?
>> ---
>>
>> Assuming that usb3 and usb4 are actually distinct busses, and they might
>> both have something plugged into port; in which case a glob like this:
>>
>> devices/pci0000:00/0000:00:14.0/usb*/*-1
>>
>> Might match both of the following:
>>
>> /sys/devices/pci0000:00/0000:00:14.0/usb3/3-1
>> /sys/devices/pci0000:00/0000:00:14.0/usb4/4-1
>
> Is that an xHCI host controller? If so that might be how the system
> represents the 2 logical (USB2/USB3) root hubs - each as its own
> separate bus.

See my other reply: this is the case. So Ian's suggestion would still
work.


Juergen

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

* Re: [PATCH V4 3/7] libxl: add pvusb API [and 1 more messages]
  2015-06-17  3:59                           ` Juergen Gross
@ 2015-06-17 10:27                             ` George Dunlap
  2015-06-18  6:24                               ` Chun Yan Liu
  0 siblings, 1 reply; 88+ messages in thread
From: George Dunlap @ 2015-06-17 10:27 UTC (permalink / raw)
  To: Juergen Gross, Ian Jackson
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On 06/17/2015 04:59 AM, Juergen Gross wrote:
> On 06/16/2015 06:34 PM, George Dunlap wrote:
>> On Tue, Jun 16, 2015 at 4:59 PM, Ian Jackson
>> <Ian.Jackson@eu.citrix.com> wrote:
>>> George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add
>>> pvusb API [and 1 more messages]"):
>>>>> Yes.  The whole point of paths like this is that they are stable if
>>>>> the physical topology doesn't change.  So on my netbook
>>>>>
>>>>>    /dev/disk/by-path/pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0-part1
>>>>>
>>>>> always refers to the 1st MBR partition on logical device 0 on the USB
>>>>> storage device plugged into the USB port physically on the front left
>>>>> of the computer.
>>>>
>>>> That would be great if it were true, but I'm not convinced that the
>>>> above path doesn't include a globally-enumerated bus number, which
>>>> might
>>>> change across reboots if it's enumerated in a different order.
>>>>
>>>> It may be that the format above is *not* based on the sysfs path of the
>>>> device; that the '0' immediately after the USB means "the first (and
>>>> perhaps only) controller at this PCI address".  In which case, yes,
>>>> having a string like this might be a unique identifier for a particular
>>>> port that would be stable across reboots.  That needs some
>>>> investigation.
>>>
>>> That does seem to be the case:
>>
>> What seems to be the case -- that it contains the global bus, or not?
>>
>>> Looking at the output of udevadm monitor --property for sdc1 (on
>>> another plug):
>>>
>>> DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0/host22/target22:0:0/22:0:0:0/block/sdc/sdc1
>>>
>>> ID_PATH=pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0
>>> ID_PATH_TAG=pci-0000_00_1d_7-usb-0_1_1_0-scsi-0_0_0_0
>>>
>>> I don't know where that ID_PATH comes from.
>>
>> It looks like that's constructed in udev:
>>
>> http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-path_id.c
>>
>>
>> See handle_usb() (line 542) in particular.
>>
>> If I'm reading it right, what it basically does it take the
>> [bus]-[port], and replace it with usb-0:[port].  (IOW, the '0' is
>> hard-coded.)
>>
>> Also, if I'm reading it right, this won't work properly for Juergen's
>> system that has two USB devices at the same pci address -- they'll
>> both end up resolving to [pciaddr]-usb-0:[whatever].
>>
>> Juergen -- can you give this a try?  Run "udevadm info" on the two USB
>> busses that share the same PCI slot, and see if the ID_PATH is the
>> same for both?
> 
> This was the correct question. :-)
> 
> The ID_PATH is the same, but:
> 
> It turns out that the two busses are for one physical hcd. One is the
> bus for USB 3.0, the other one for USB 2.0. I guess the bus is just
> selected by the capability of the plugged in device.
> 
> So the [port] in "usb-0:[port]" is unique across the two logical
> busses.

Right -- I think I had come to the conclusion that would probably be the
case later yesterday evening.  Glad to  have it confirmed.

So in addition to our other identifiers, stealing udev's naming scheme
should work, and would be useful.

The next challenge would be how to implement it effectively.  It's
already udev's job to make sure that a string is unique -- as much as
possible we want to leverage their efforts, rather than re-implementing
our own.

One thing that Ian suggested was that we could add a udev rule that
would create links from the ID_PATH of the usb device into the sysfs
device node.  (Both seem to be available in the udev rule environment.)
 That would allow us to easily translate the ID_PATH into the other
things we might want (bus-port, bus.addr, &c) and vice versa.

But I think all that will certainly not be done by the feature freeze.

The core functionality of Chunyan's series, wrt the pvusb functionality
is complete; as with my HVM series before, it's mainly the interface
that is being discussed.

There are two options here: Chunyan could try to implement the interface
we've been discussing here (assuming that she doesn't have any
objections to what we've described); or, I could take Chunyan's series,
try to implement what we've been talking about, and then add in the HVM
functionality as well.

What does everyone think?

 -George

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 11:44                     ` Ian Jackson
@ 2015-06-17 11:24                       ` Ian Campbell
  2015-06-18 11:50                         ` George Dunlap
  2015-06-18 12:08                         ` George Dunlap
  0 siblings, 2 replies; 88+ messages in thread
From: Ian Campbell @ 2015-06-17 11:24 UTC (permalink / raw)
  To: Ian Jackson
  Cc: Juergen Gross, Wei Liu, George Dunlap, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

On Tue, 2015-06-16 at 12:44 +0100, Ian Jackson wrote:
> George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
> > On Tue, Jun 16, 2015 at 12:19 PM, Juergen Gross <jgross@suse.com> wrote:
> > > I'm pretty sure this is just a matter of timing during boot: the busses
> > > are all (or at least some of them) queried at the same time and the
> > > first answering gets number 1, the next 2, and so on. And timing seems
> > > to be different enough to result in unstable bus numbers.
> > 
> > Right -- I meant "stable in topology within one boot", but at least
> > two of you have now understood me to mean "across reboots" by default,
> > so that's obviously a detail that needs to be specified. :-)
> 
> I think "stable in topology within one boot" is nearly vacuous (or are
> we expecting buses or devices to spontaneously renumber themselves for
> no reason) and also nearly useless.
> 
> We definitely need _some_ way for a user to identify a specific device
> uniquely in a way that is reliable from one boot to the next.  vid:pid
> is one way to do this, but not always sufficient.

We should perhaps separate out the "end user" from the "libxl
user" (i.e. the toolstack application) in our deliberations here.

We have the option of settling on a single way of describing a device to
libxl in the libxl API but allowing the toolstack to choose to present
the user with multiple different ways to specify things by providing a
suitable set of helper functions (in either libxlu or libxl proper) from
a variety of schemes to the one true way of describing a device.

That sounds better to me than having the libxl API consist of the union
of all potentially useful ways to refer to a device.

I'm not sure whether that also gives us the freedom to use something
which is only stable for a given boot at the libxl API layer though.

Ian.

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-16 14:20                           ` Juergen Gross
  2015-06-16 14:37                             ` George Dunlap
@ 2015-06-17 11:34                             ` Ian Campbell
  2015-06-17 11:40                               ` Juergen Gross
  2015-06-18  6:20                               ` Chun Yan Liu
  1 sibling, 2 replies; 88+ messages in thread
From: Ian Campbell @ 2015-06-17 11:34 UTC (permalink / raw)
  To: Juergen Gross
  Cc: Wei Liu, George Dunlap, Ian Jackson, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

On Tue, 2015-06-16 at 16:20 +0200, Juergen Gross wrote:
> My point was to avoid the sysfs accesses in libxl in order to support
> BSD as well and to reduce the complexity.

As a slight aside to this, can't libxl use libusb for a lot of this
stuff and therefore avoid being Linux specific?

http://libusb.info/ claims to support "Linux, OS X, Windows, Windows CE,
Android, OpenBSD/NetBSD, Haiku.". Interestingly FreeBSD is missing there
but I don't think that need to be a blocker.

I don't see a problem with adding libusb to our set of dependencies, and
it's certainly got to be better than (re)implementing a bunch of sysfs
stuff (which I presume is what libusb does under the hood anyway).

Ian.

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-17 11:34                             ` Ian Campbell
@ 2015-06-17 11:40                               ` Juergen Gross
  2015-06-18  6:20                               ` Chun Yan Liu
  1 sibling, 0 replies; 88+ messages in thread
From: Juergen Gross @ 2015-06-17 11:40 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Wei Liu, George Dunlap, Ian Jackson, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

On 06/17/2015 01:34 PM, Ian Campbell wrote:
> On Tue, 2015-06-16 at 16:20 +0200, Juergen Gross wrote:
>> My point was to avoid the sysfs accesses in libxl in order to support
>> BSD as well and to reduce the complexity.
>
> As a slight aside to this, can't libxl use libusb for a lot of this
> stuff and therefore avoid being Linux specific?
>
> http://libusb.info/ claims to support "Linux, OS X, Windows, Windows CE,
> Android, OpenBSD/NetBSD, Haiku.". Interestingly FreeBSD is missing there
> but I don't think that need to be a blocker.
>
> I don't see a problem with adding libusb to our set of dependencies, and
> it's certainly got to be better than (re)implementing a bunch of sysfs
> stuff (which I presume is what libusb does under the hood anyway).

+1


Juergen

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-17  4:03                   ` Jürgen Groß
@ 2015-06-17 13:48                     ` Ross Philipson
  0 siblings, 0 replies; 88+ messages in thread
From: Ross Philipson @ 2015-06-17 13:48 UTC (permalink / raw)
  To: Jürgen Groß, George Dunlap, Ian Jackson
  Cc: Wei Liu, Ian Campbell, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On 06/17/2015 12:03 AM, Jürgen Groß wrote:
> On 06/16/2015 06:51 PM, Ross Philipson wrote:
>> On 06/16/2015 12:39 PM, George Dunlap wrote:
>>> On 06/16/2015 05:32 PM, Ian Jackson wrote:
>>>> I have just discovered that the value used in /dev/disk/by-path is not
>>>> from sysfs, or at least, not directly.
>>>>
>>>> udev cobbles it together with a bunch of string mangling, from
>>>> information mostly from sysfs.  There is no corresponding thing for
>>>> usb devices.
>>>>
>>>> So Linux, the kernel, does not actually provide a stable device name
>>>> string.  This is obviously absurd, but I think fixing it is out of
>>>> scope.
>>>>
>>>> I suggest we provide a facility to allow a user to specify a fnmatch
>>>> glob pattern to be applied to the sysfs path.  That way when they see
>>>> their device is
>>>>    /devices/pci0000:00/0000:00:1d.7/usb1/1-1
>>>> they can write
>>>>    /devices/pci0000:00/0000:00:1d.7/usb*/*-1
>>>> which will match exactly and only the right thing.
>>>
>>> What about Juergen's system that has two usbN directories in a single
>>> pci node?
>>>
>>> Quoting:
>>> ---
>>> Hmm, perhaps. On my system I've got:
>>>
>>> /sys/devices/pci0000:00/0000:00:14.0/usb3/
>>> /sys/devices/pci0000:00/0000:00:14.0/usb4/
>>>
>>> So two busses on one pci bus address. Are usb3 and usb4 always in this
>>> order or are they sometimes just numbered the other way round?
>>> ---
>>>
>>> Assuming that usb3 and usb4 are actually distinct busses, and they might
>>> both have something plugged into port; in which case a glob like this:
>>>
>>> devices/pci0000:00/0000:00:14.0/usb*/*-1
>>>
>>> Might match both of the following:
>>>
>>> /sys/devices/pci0000:00/0000:00:14.0/usb3/3-1
>>> /sys/devices/pci0000:00/0000:00:14.0/usb4/4-1
>>
>> Is that an xHCI host controller? If so that might be how the system
>> represents the 2 logical (USB2/USB3) root hubs - each as its own
>> separate bus.
>
> See my other reply: this is the case. So Ian's suggestion would still
> work.

Ack, saw it, thanks.

>
>
> Juergen
>


-- 
Ross Philipson

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-17 11:34                             ` Ian Campbell
  2015-06-17 11:40                               ` Juergen Gross
@ 2015-06-18  6:20                               ` Chun Yan Liu
  2015-06-18  7:02                                 ` Juergen Gross
  1 sibling, 1 reply; 88+ messages in thread
From: Chun Yan Liu @ 2015-06-18  6:20 UTC (permalink / raw)
  To: Ian Campbell, Juergen Gross
  Cc: Wei Liu, George Dunlap, Ian Jackson, xen-devel, Jim Fehlig, Simon Cao



>>> On 6/17/2015 at 07:34 PM, in message <1434540857.13744.334.camel@citrix.com>,
Ian Campbell <ian.campbell@citrix.com> wrote: 
> On Tue, 2015-06-16 at 16:20 +0200, Juergen Gross wrote: 
> > My point was to avoid the sysfs accesses in libxl in order to support 
> > BSD as well and to reduce the complexity. 
>  
> As a slight aside to this, can't libxl use libusb for a lot of this 
> stuff and therefore avoid being Linux specific? 
>  
> http://libusb.info/ claims to support "Linux, OS X, Windows, Windows CE, 
> Android, OpenBSD/NetBSD, Haiku.". Interestingly FreeBSD is missing there 
> but I don't think that need to be a blocker. 
>  
> I don't see a problem with adding libusb to our set of dependencies, and 
> it's certainly got to be better than (re)implementing a bunch of sysfs 
> stuff (which I presume is what libusb does under the hood anyway). 

Using libusb is certainly good and can save effort to implement things by
ourself. Only one concern: some functions require newer version of libusb.
For example, functions to get port (quite like busid) information
libusb_get_port_numbers or libusb_get_port_path need
libusb version >= 1.0.12. If libusb version is not satisfied, the whole pvusb
work might be blocked.

- Chunyan


>  
> Ian. 
>  
>  
>  

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

* Re: [PATCH V4 3/7] libxl: add pvusb API [and 1 more messages]
  2015-06-17 10:27                             ` George Dunlap
@ 2015-06-18  6:24                               ` Chun Yan Liu
  0 siblings, 0 replies; 88+ messages in thread
From: Chun Yan Liu @ 2015-06-18  6:24 UTC (permalink / raw)
  To: George Dunlap, Ian Jackson, Juergen Gross
  Cc: Jim Fehlig, Simon Cao, Wei Liu, Ian Campbell, xen-devel



>>> On 6/17/2015 at 06:27 PM, in message <55814B9F.6070909@eu.citrix.com>, George
Dunlap <george.dunlap@eu.citrix.com> wrote: 
> On 06/17/2015 04:59 AM, Juergen Gross wrote: 
> > On 06/16/2015 06:34 PM, George Dunlap wrote: 
> >> On Tue, Jun 16, 2015 at 4:59 PM, Ian Jackson 
> >> <Ian.Jackson@eu.citrix.com> wrote: 
> >>> George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add 
> >>> pvusb API [and 1 more messages]"): 
> >>>>> Yes.  The whole point of paths like this is that they are stable if 
> >>>>> the physical topology doesn't change.  So on my netbook 
> >>>>> 
> >>>>>    /dev/disk/by-path/pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0-part1 
> >>>>> 
> >>>>> always refers to the 1st MBR partition on logical device 0 on the USB 
> >>>>> storage device plugged into the USB port physically on the front left 
> >>>>> of the computer. 
> >>>> 
> >>>> That would be great if it were true, but I'm not convinced that the 
> >>>> above path doesn't include a globally-enumerated bus number, which 
> >>>> might 
> >>>> change across reboots if it's enumerated in a different order. 
> >>>> 
> >>>> It may be that the format above is *not* based on the sysfs path of the 
> >>>> device; that the '0' immediately after the USB means "the first (and 
> >>>> perhaps only) controller at this PCI address".  In which case, yes, 
> >>>> having a string like this might be a unique identifier for a particular 
> >>>> port that would be stable across reboots.  That needs some 
> >>>> investigation. 
> >>> 
> >>> That does seem to be the case: 
> >> 
> >> What seems to be the case -- that it contains the global bus, or not? 
> >> 
> >>> Looking at the output of udevadm monitor --property for sdc1 (on 
> >>> another plug): 
> >>> 
> >>>  
> DEVPATH=/devices/pci0000:00/0000:00:1d.7/usb1/1-1/1-1:1.0/host22/target22:0:0 
> /22:0:0:0/block/sdc/sdc1 
> >>> 
> >>> ID_PATH=pci-0000:00:1d.7-usb-0:1:1.0-scsi-0:0:0:0 
> >>> ID_PATH_TAG=pci-0000_00_1d_7-usb-0_1_1_0-scsi-0_0_0_0 
> >>> 
> >>> I don't know where that ID_PATH comes from. 
> >> 
> >> It looks like that's constructed in udev: 
> >> 
> >>  
> http://cgit.freedesktop.org/systemd/systemd/tree/src/udev/udev-builtin-path_i 
> d.c 
> >> 
> >> 
> >> See handle_usb() (line 542) in particular. 
> >> 
> >> If I'm reading it right, what it basically does it take the 
> >> [bus]-[port], and replace it with usb-0:[port].  (IOW, the '0' is 
> >> hard-coded.) 
> >> 
> >> Also, if I'm reading it right, this won't work properly for Juergen's 
> >> system that has two USB devices at the same pci address -- they'll 
> >> both end up resolving to [pciaddr]-usb-0:[whatever]. 
> >> 
> >> Juergen -- can you give this a try?  Run "udevadm info" on the two USB 
> >> busses that share the same PCI slot, and see if the ID_PATH is the 
> >> same for both? 
> >  
> > This was the correct question. :-) 
> >  
> > The ID_PATH is the same, but: 
> >  
> > It turns out that the two busses are for one physical hcd. One is the 
> > bus for USB 3.0, the other one for USB 2.0. I guess the bus is just 
> > selected by the capability of the plugged in device. 
> >  
> > So the [port] in "usb-0:[port]" is unique across the two logical 
> > busses. 
>  
> Right -- I think I had come to the conclusion that would probably be the 
> case later yesterday evening.  Glad to  have it confirmed. 
>  
> So in addition to our other identifiers, stealing udev's naming scheme 
> should work, and would be useful. 
>  
> The next challenge would be how to implement it effectively.  It's 
> already udev's job to make sure that a string is unique -- as much as 
> possible we want to leverage their efforts, rather than re-implementing 
> our own. 
>  
> One thing that Ian suggested was that we could add a udev rule that 
> would create links from the ID_PATH of the usb device into the sysfs 
> device node.  (Both seem to be available in the udev rule environment.) 
>  That would allow us to easily translate the ID_PATH into the other 
> things we might want (bus-port, bus.addr, &c) and vice versa. 
>  
> But I think all that will certainly not be done by the feature freeze. 
>  
> The core functionality of Chunyan's series, wrt the pvusb functionality 
> is complete; as with my HVM series before, it's mainly the interface 
> that is being discussed. 
>  
> There are two options here: Chunyan could try to implement the interface 
> we've been discussing here (assuming that she doesn't have any 
> objections to what we've described);

No, I don't have any objections. I can do that.

- Chunyan

> or, I could take Chunyan's series, 
> try to implement what we've been talking about, and then add in the HVM 
> functionality as well. 
>  
> What does everyone think? 
>  
>  -George 
>  
>  
>  
>  

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-18  6:20                               ` Chun Yan Liu
@ 2015-06-18  7:02                                 ` Juergen Gross
  2015-06-18  8:50                                   ` Ian Campbell
  0 siblings, 1 reply; 88+ messages in thread
From: Juergen Gross @ 2015-06-18  7:02 UTC (permalink / raw)
  To: Chun Yan Liu, Ian Campbell
  Cc: Wei Liu, George Dunlap, Ian Jackson, xen-devel, Jim Fehlig, Simon Cao

On 06/18/2015 08:20 AM, Chun Yan Liu wrote:
>
>
>>>> On 6/17/2015 at 07:34 PM, in message <1434540857.13744.334.camel@citrix.com>,
> Ian Campbell <ian.campbell@citrix.com> wrote:
>> On Tue, 2015-06-16 at 16:20 +0200, Juergen Gross wrote:
>>> My point was to avoid the sysfs accesses in libxl in order to support
>>> BSD as well and to reduce the complexity.
>>
>> As a slight aside to this, can't libxl use libusb for a lot of this
>> stuff and therefore avoid being Linux specific?
>>
>> http://libusb.info/ claims to support "Linux, OS X, Windows, Windows CE,
>> Android, OpenBSD/NetBSD, Haiku.". Interestingly FreeBSD is missing there
>> but I don't think that need to be a blocker.
>>
>> I don't see a problem with adding libusb to our set of dependencies, and
>> it's certainly got to be better than (re)implementing a bunch of sysfs
>> stuff (which I presume is what libusb does under the hood anyway).
>
> Using libusb is certainly good and can save effort to implement things by
> ourself. Only one concern: some functions require newer version of libusb.
> For example, functions to get port (quite like busid) information
> libusb_get_port_numbers or libusb_get_port_path need
> libusb version >= 1.0.12. If libusb version is not satisfied, the whole pvusb
> work might be blocked.

Is this really a problem? lubusb version 1.0.12 is out for three years
now. Would we really need to support pvUSB on dom0 not being capable
to install a more recent libusb?


Juergen

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-18  7:02                                 ` Juergen Gross
@ 2015-06-18  8:50                                   ` Ian Campbell
  2015-06-18 13:02                                     ` Juergen Gross
  0 siblings, 1 reply; 88+ messages in thread
From: Ian Campbell @ 2015-06-18  8:50 UTC (permalink / raw)
  To: Juergen Gross
  Cc: Wei Liu, George Dunlap, Ian Jackson, Chun Yan Liu, xen-devel,
	Jim Fehlig, Simon Cao

On Thu, 2015-06-18 at 09:02 +0200, Juergen Gross wrote:
> On 06/18/2015 08:20 AM, Chun Yan Liu wrote:
> >
> >
> >>>> On 6/17/2015 at 07:34 PM, in message <1434540857.13744.334.camel@citrix.com>,
> > Ian Campbell <ian.campbell@citrix.com> wrote:
> >> On Tue, 2015-06-16 at 16:20 +0200, Juergen Gross wrote:
> >>> My point was to avoid the sysfs accesses in libxl in order to support
> >>> BSD as well and to reduce the complexity.
> >>
> >> As a slight aside to this, can't libxl use libusb for a lot of this
> >> stuff and therefore avoid being Linux specific?
> >>
> >> http://libusb.info/ claims to support "Linux, OS X, Windows, Windows CE,
> >> Android, OpenBSD/NetBSD, Haiku.". Interestingly FreeBSD is missing there
> >> but I don't think that need to be a blocker.
> >>
> >> I don't see a problem with adding libusb to our set of dependencies, and
> >> it's certainly got to be better than (re)implementing a bunch of sysfs
> >> stuff (which I presume is what libusb does under the hood anyway).
> >
> > Using libusb is certainly good and can save effort to implement things by
> > ourself. Only one concern: some functions require newer version of libusb.
> > For example, functions to get port (quite like busid) information
> > libusb_get_port_numbers or libusb_get_port_path need
> > libusb version >= 1.0.12. If libusb version is not satisfied, the whole pvusb
> > work might be blocked.
> 
> Is this really a problem? lubusb version 1.0.12 is out for three years
> now. Would we really need to support pvUSB on dom0 not being capable
> to install a more recent libusb?

Of interest would be which distro versions have >= 1.0.12 i.e. for
common things like Debian, SuSE, SLE, Fedora etc.

Even that may not be an absolute blocker, I don't think it would be too
bad to say that for an older stable distro either an up to date libusb
is made available or the pvusb functionality is disabled at build time
(automatically, by configure.ac). The latter would be some faff to
arrange but I think saying that Xen doesn't build on older stable
distros unless you backport a libusb might be a step to far.

Ian.

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-17 11:24                       ` Ian Campbell
@ 2015-06-18 11:50                         ` George Dunlap
  2015-06-18 12:08                         ` George Dunlap
  1 sibling, 0 replies; 88+ messages in thread
From: George Dunlap @ 2015-06-18 11:50 UTC (permalink / raw)
  To: Ian Campbell, Ian Jackson
  Cc: Juergen Gross, Wei Liu, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On 06/17/2015 12:24 PM, Ian Campbell wrote:
> On Tue, 2015-06-16 at 12:44 +0100, Ian Jackson wrote:
>> George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
>>> On Tue, Jun 16, 2015 at 12:19 PM, Juergen Gross <jgross@suse.com> wrote:
>>>> I'm pretty sure this is just a matter of timing during boot: the busses
>>>> are all (or at least some of them) queried at the same time and the
>>>> first answering gets number 1, the next 2, and so on. And timing seems
>>>> to be different enough to result in unstable bus numbers.
>>>
>>> Right -- I meant "stable in topology within one boot", but at least
>>> two of you have now understood me to mean "across reboots" by default,
>>> so that's obviously a detail that needs to be specified. :-)
>>
>> I think "stable in topology within one boot" is nearly vacuous (or are
>> we expecting buses or devices to spontaneously renumber themselves for
>> no reason) and also nearly useless.
>>
>> We definitely need _some_ way for a user to identify a specific device
>> uniquely in a way that is reliable from one boot to the next.  vid:pid
>> is one way to do this, but not always sufficient.
> 
> We should perhaps separate out the "end user" from the "libxl
> user" (i.e. the toolstack application) in our deliberations here.
> 
> We have the option of settling on a single way of describing a device to
> libxl in the libxl API but allowing the toolstack to choose to present
> the user with multiple different ways to specify things by providing a
> suitable set of helper functions (in either libxlu or libxl proper) from
> a variety of schemes to the one true way of describing a device.
> 
> That sounds better to me than having the libxl API consist of the union
> of all potentially useful ways to refer to a device.
> 
> I'm not sure whether that also gives us the freedom to use something
> which is only stable for a given boot at the libxl API layer though.

[snip]

> As a slight aside to this, can't libxl use libusb for a lot of this
> stuff and therefore avoid being Linux specific?
>
> http://libusb.info/ claims to support "Linux, OS X, Windows, Windows CE,
> Android, OpenBSD/NetBSD, Haiku.". Interestingly FreeBSD is missing there
> but I don't think that need to be a blocker.
>
> I don't see a problem with adding libusb to our set of dependencies, and
> it's certainly got to be better than (re)implementing a bunch of sysfs
> stuff (which I presume is what libusb does under the hood anyway).

OK, so we have three interfaces:

* User <-> toolstack
* toolstack <-> libxl
* libxl <-> underlying functionality (Linux pvusbback and qemu, at the
moment)

And we're also now considering whether to do a "minimal interface" in
libxl (i.e., only accept one kind of specification and make the
toolstack do the conversion from a more useful spec) or do a "rich
interface" (i.e., accept many different kinds of specification, allowing
the toolstack to just pass things through).

qemu already uses libusb, and so can already do almost everything that
libxl could use libusb to accomplish.  The only things it doesn't do
that we've talked about doing are the bus-ports specification, and the
"vendorid:deviceid:serialno" specification; both of which would be
trivial (and probably useful) to add.

So for all the things libusb can be used to convert between, we don't
actually need to do any conversion when speaking to qemu (unless we want
to be backwards compatible with older versions).

The udev "id_path" specification isn't something that libusb can handle;
we'd have to mess around with sysfs and/or udev-created device nodes /
symbolic links into sysfs anyway.

So for the qemu side of things, libusb is mostly useless.

We can't get around using sysfs to talk to pvusbback -- that's how it
works.  At the moment, the pvusbback interface requires sysfs strings,
which happen to be described in the bus-ports:interface format.  So the
main reason we're messing around with sysfs at the moment is to convert
other specifications into the sysfs strings suitable for using with pvusb.

To convert into a sysfs string ourselves:
* readdir on /sys/bus/usb/devices
* for each entry, look inside to see if it matches the specification
(i.e., bus==busnum, addr==devnum, &c)
* take the directory name of the entry that matches
* look inside that directory for all the interfaces for that device (so
we can assign each one to pvusbback).
* Write the strings you read from sysfs into the appropriate "bind"
nodes in pvusbback

To convert bus.addr into a sysfs string with libusb:
* libusb_get_device_list [1]
* for each entry, call libusb_get_device_descriptor and see if it
matches the specification (i.e., bus==bus, addr==addr, &c)
* Call libusb_get_ports to get an array of the port numbers
* Construct a sysfs string from the bus number and the array of port
numbers (i.e., %d-%d[.%d.%d])
* Get information about all the interfaces, and construct sysfs strings
from those as well
* Write the constructed strings into the pciback sysfs nodes

A couple of points:
1. The second is certainly not simpler than the first
2. The only code that needs to do it is completely linux-specific at the
moment anyway (since it's talking to the linux driver)
3. The first uses strings that it pulled directly from sysfs; the second
relies on constructing strings
4. If we do a "minimal interface" in libxl, then the toolstack will also
have to link against libusb to convert from a more useful specification
to the libxl specification

So it seems to me that libusb doesn't actually have that much to offer
us.  For the only situation where it actually is cross-platform (i.e.,
qemu), it's not needed; for the one situation where it could be used
(converting to sysfs-style strings for pvusbback), it's not simpler,
probably less robust, and its cross-platform capability is moot (since
it's a Linux-only driver anyway).

 -George

[1] See http://libusb.sourceforge.net/api-1.0/group__dev.html and
http://libusb.sourceforge.net/api-1.0/group__desc.html

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-17 11:24                       ` Ian Campbell
  2015-06-18 11:50                         ` George Dunlap
@ 2015-06-18 12:08                         ` George Dunlap
  2015-06-18 13:03                           ` Juergen Gross
  2015-06-22 13:29                           ` Proposed plan for libxl USB interface (was Re: [PATCH V4 3/7] libxl: add pvusb API) George Dunlap
  1 sibling, 2 replies; 88+ messages in thread
From: George Dunlap @ 2015-06-18 12:08 UTC (permalink / raw)
  To: Ian Campbell, Ian Jackson
  Cc: Juergen Gross, Wei Liu, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On 06/17/2015 12:24 PM, Ian Campbell wrote:
> On Tue, 2015-06-16 at 12:44 +0100, Ian Jackson wrote:
>> George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
>>> On Tue, Jun 16, 2015 at 12:19 PM, Juergen Gross <jgross@suse.com> wrote:
>>>> I'm pretty sure this is just a matter of timing during boot: the busses
>>>> are all (or at least some of them) queried at the same time and the
>>>> first answering gets number 1, the next 2, and so on. And timing seems
>>>> to be different enough to result in unstable bus numbers.
>>>
>>> Right -- I meant "stable in topology within one boot", but at least
>>> two of you have now understood me to mean "across reboots" by default,
>>> so that's obviously a detail that needs to be specified. :-)
>>
>> I think "stable in topology within one boot" is nearly vacuous (or are
>> we expecting buses or devices to spontaneously renumber themselves for
>> no reason) and also nearly useless.
>>
>> We definitely need _some_ way for a user to identify a specific device
>> uniquely in a way that is reliable from one boot to the next.  vid:pid
>> is one way to do this, but not always sufficient.
> 
> We should perhaps separate out the "end user" from the "libxl
> user" (i.e. the toolstack application) in our deliberations here.
> 
> We have the option of settling on a single way of describing a device to
> libxl in the libxl API but allowing the toolstack to choose to present
> the user with multiple different ways to specify things by providing a
> suitable set of helper functions (in either libxlu or libxl proper) from
> a variety of schemes to the one true way of describing a device.
> 
> That sounds better to me than having the libxl API consist of the union
> of all potentially useful ways to refer to a device.

This was my original design.  :-)

> I'm not sure whether that also gives us the freedom to use something
> which is only stable for a given boot at the libxl API layer though.

I'm not sure why it doesn't -- as long as things don't change between
the time the toostack converts a "stable name" into a specification and
the time libxl uses it, it should be fine.

One advantage of having a richer interface that Juergen pointed out
previously was the ability to specify attaching devices automatically
when they show yp; i.e., "If a device with this
vendorid:deviceid:serialnumber shows up, please attach it to this VM".

But we don't have that functionality now; and there's no reason we
couldn't add extra ways of specifying devices in the future.

This usb interface stuff is really becoming a morass.  The core
functionality is fairly independent of the interface.  I'm inclined to
say that we should start with a simple specification (only bus.addr),
and try to get both pvusb and hvmusb in.  Then we can talk about where
to add additional specifications (including cross-boot stable
specifcations).

 -George

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-18  8:50                                   ` Ian Campbell
@ 2015-06-18 13:02                                     ` Juergen Gross
  0 siblings, 0 replies; 88+ messages in thread
From: Juergen Gross @ 2015-06-18 13:02 UTC (permalink / raw)
  To: Ian Campbell
  Cc: Wei Liu, George Dunlap, Ian Jackson, Chun Yan Liu, xen-devel,
	Jim Fehlig, Simon Cao

On 06/18/2015 10:50 AM, Ian Campbell wrote:
> On Thu, 2015-06-18 at 09:02 +0200, Juergen Gross wrote:
>> On 06/18/2015 08:20 AM, Chun Yan Liu wrote:
>>>
>>>
>>>>>> On 6/17/2015 at 07:34 PM, in message <1434540857.13744.334.camel@citrix.com>,
>>> Ian Campbell <ian.campbell@citrix.com> wrote:
>>>> On Tue, 2015-06-16 at 16:20 +0200, Juergen Gross wrote:
>>>>> My point was to avoid the sysfs accesses in libxl in order to support
>>>>> BSD as well and to reduce the complexity.
>>>>
>>>> As a slight aside to this, can't libxl use libusb for a lot of this
>>>> stuff and therefore avoid being Linux specific?
>>>>
>>>> http://libusb.info/ claims to support "Linux, OS X, Windows, Windows CE,
>>>> Android, OpenBSD/NetBSD, Haiku.". Interestingly FreeBSD is missing there
>>>> but I don't think that need to be a blocker.
>>>>
>>>> I don't see a problem with adding libusb to our set of dependencies, and
>>>> it's certainly got to be better than (re)implementing a bunch of sysfs
>>>> stuff (which I presume is what libusb does under the hood anyway).
>>>
>>> Using libusb is certainly good and can save effort to implement things by
>>> ourself. Only one concern: some functions require newer version of libusb.
>>> For example, functions to get port (quite like busid) information
>>> libusb_get_port_numbers or libusb_get_port_path need
>>> libusb version >= 1.0.12. If libusb version is not satisfied, the whole pvusb
>>> work might be blocked.
>>
>> Is this really a problem? lubusb version 1.0.12 is out for three years
>> now. Would we really need to support pvUSB on dom0 not being capable
>> to install a more recent libusb?
>
> Of interest would be which distro versions have >= 1.0.12 i.e. for
> common things like Debian, SuSE, SLE, Fedora etc.

openSUSE since 13.2 (13.1 has 1.0.9)
SLE since 12


Juergen

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-18 12:08                         ` George Dunlap
@ 2015-06-18 13:03                           ` Juergen Gross
  2015-06-22 13:29                           ` Proposed plan for libxl USB interface (was Re: [PATCH V4 3/7] libxl: add pvusb API) George Dunlap
  1 sibling, 0 replies; 88+ messages in thread
From: Juergen Gross @ 2015-06-18 13:03 UTC (permalink / raw)
  To: George Dunlap, Ian Campbell, Ian Jackson
  Cc: Jim Fehlig, Simon Cao, Wei Liu, Chunyan Liu, xen-devel

On 06/18/2015 02:08 PM, George Dunlap wrote:
> On 06/17/2015 12:24 PM, Ian Campbell wrote:
>> On Tue, 2015-06-16 at 12:44 +0100, Ian Jackson wrote:
>>> George Dunlap writes ("Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API"):
>>>> On Tue, Jun 16, 2015 at 12:19 PM, Juergen Gross <jgross@suse.com> wrote:
>>>>> I'm pretty sure this is just a matter of timing during boot: the busses
>>>>> are all (or at least some of them) queried at the same time and the
>>>>> first answering gets number 1, the next 2, and so on. And timing seems
>>>>> to be different enough to result in unstable bus numbers.
>>>>
>>>> Right -- I meant "stable in topology within one boot", but at least
>>>> two of you have now understood me to mean "across reboots" by default,
>>>> so that's obviously a detail that needs to be specified. :-)
>>>
>>> I think "stable in topology within one boot" is nearly vacuous (or are
>>> we expecting buses or devices to spontaneously renumber themselves for
>>> no reason) and also nearly useless.
>>>
>>> We definitely need _some_ way for a user to identify a specific device
>>> uniquely in a way that is reliable from one boot to the next.  vid:pid
>>> is one way to do this, but not always sufficient.
>>
>> We should perhaps separate out the "end user" from the "libxl
>> user" (i.e. the toolstack application) in our deliberations here.
>>
>> We have the option of settling on a single way of describing a device to
>> libxl in the libxl API but allowing the toolstack to choose to present
>> the user with multiple different ways to specify things by providing a
>> suitable set of helper functions (in either libxlu or libxl proper) from
>> a variety of schemes to the one true way of describing a device.
>>
>> That sounds better to me than having the libxl API consist of the union
>> of all potentially useful ways to refer to a device.
>
> This was my original design.  :-)
>
>> I'm not sure whether that also gives us the freedom to use something
>> which is only stable for a given boot at the libxl API layer though.
>
> I'm not sure why it doesn't -- as long as things don't change between
> the time the toostack converts a "stable name" into a specification and
> the time libxl uses it, it should be fine.
>
> One advantage of having a richer interface that Juergen pointed out
> previously was the ability to specify attaching devices automatically
> when they show yp; i.e., "If a device with this
> vendorid:deviceid:serialnumber shows up, please attach it to this VM".
>
> But we don't have that functionality now; and there's no reason we
> couldn't add extra ways of specifying devices in the future.
>
> This usb interface stuff is really becoming a morass.  The core
> functionality is fairly independent of the interface.  I'm inclined to
> say that we should start with a simple specification (only bus.addr),
> and try to get both pvusb and hvmusb in.  Then we can talk about where
> to add additional specifications (including cross-boot stable
> specifcations).

+1


Juergen

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

* Proposed plan for libxl USB interface (was Re: [PATCH V4 3/7] libxl: add pvusb API)
  2015-06-18 12:08                         ` George Dunlap
  2015-06-18 13:03                           ` Juergen Gross
@ 2015-06-22 13:29                           ` George Dunlap
  2015-06-22 14:14                             ` Juergen Gross
                                               ` (4 more replies)
  1 sibling, 5 replies; 88+ messages in thread
From: George Dunlap @ 2015-06-22 13:29 UTC (permalink / raw)
  To: Ian Campbell, Ian Jackson
  Cc: Juergen Gross, Wei Liu, Chunyan Liu, xen-devel, Jim Fehlig, Simon Cao

On 06/18/2015 01:08 PM, George Dunlap wrote:
> This usb interface stuff is really becoming a morass.  The core
> functionality is fairly independent of the interface.  I'm inclined to
> say that we should start with a simple specification (only bus.addr),
> and try to get both pvusb and hvmusb in.  Then we can talk about where
> to add additional specifications (including cross-boot stable
> specifcations).

So Ian J, Ian C, Wei and I chatted face-to-face about what to do going
forward; below are some key points we discussed and the conclusion we
came to.  Decisions are only official when they've been discussed on the
list, so please consider this a proposal and give your feedback. :-)

(Also, Ian/Ian/Wei, let me know if I've misremembered or forgotten
something.)

Points of discussion:

* We would ideally like to be able to have the released interface work
both for both PV and HVM; for one so that we don't have to have separate
#defines for that functionality; but also to make sure that the
interface is suitable for both functionalities.

* It's difficult at the moment to actually do collaborative development
on the libxl USB feature, because the code is not yet in the tree.

* Regarding user-facing interfaces (like xl, as opposed to libxl): the
interface cannot be half-baked; it should not provide functionality
which works most of the time but sometimes will fail.

Having only "bus-ports" or "vendorid:deviceid" is not sufficient,
because it will lure the user into thinking that they can put those
numbers into a config file and get repeatable results every time.  But
since bus numbers change, and vendorid:deviceid is not unique, either of
these would be a false promise.

Udevs ID_PATH naming scheme seems like a sensible thing to adopt, at
least for Linux.  We could consider making an OS-specific string for
identifying the same device across reboots.

On the other hand, bus.address is very obviously unstable; nobody in
their right mind would use it for anything they wanted to persist across
reboots.  So including bus.address as a temporary measure to be able to
test the underlying library until we get a more reliable naming scheme
in place would be OK, as long as the UI interface could be extended
going forward.

* We should avoid adding complexity to the libxl interface until it's
needed; accepting one way of specifying USB devices, and letting the
toolstack do translation into that way of specifying it (perhaps
providing helper libraries to do so), should be enough for now.  The way
of specifying USB devices does not need to be stable across reboots, as
long as it won't change between the time the toolstack does the
translation and the time the device is plugged in.

bus.address is the best specification from that point of view: it's
unique (unlike device:vendorid), and if a device is unplugged and
another one plugged in between the time the translation happens and the
time libxl gets around to doing something, the old bus.address won't
exist anymore and the command will fail.

* There may be a point in the future when we want to be able provide
device auto-plug functionality at the libxl layer.  (i.e., "When device
X shows up, please plug it into VM Y.")  For this we will need a
reliable way of specifying devices; bus.address will not do.

But that functionality doesn't exist yet; so for now we should stick
with bus.address, but design the interface such that it can be extended
with more options for specifying a device when such functionality is neede.

With all that in mind, here is a proposal:

1. For the moment, only use bus.address at the libxl layer to specify a
device.

2. Let's check in the libxl part of Chunyan's PVUSB series as soon as
the 4.7 development window opens (assuming the coding style issues have
all been addressed).  We can also check in the xl functionality with
minimal bus.address support for testing.

3. I will the port the HVM USB series and submit them as soon as possible.

4. We work on a set of helper functions that a toolstack can use to
translate other ways of specifying a device, much like the disk
specification helper functions that we provide.  One of these should be
something which is reliably stable over reboots, such as the udev
ID_PATH specification.

Thoughts?

 -George

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

* Re: Proposed plan for libxl USB interface (was Re: [PATCH V4 3/7] libxl: add pvusb API)
  2015-06-22 13:29                           ` Proposed plan for libxl USB interface (was Re: [PATCH V4 3/7] libxl: add pvusb API) George Dunlap
@ 2015-06-22 14:14                             ` Juergen Gross
  2015-06-22 14:22                             ` Ian Jackson
                                               ` (3 subsequent siblings)
  4 siblings, 0 replies; 88+ messages in thread
From: Juergen Gross @ 2015-06-22 14:14 UTC (permalink / raw)
  To: George Dunlap, Ian Campbell, Ian Jackson
  Cc: Jim Fehlig, Simon Cao, Wei Liu, Chunyan Liu, xen-devel

On 06/22/2015 03:29 PM, George Dunlap wrote:
> On 06/18/2015 01:08 PM, George Dunlap wrote:
>> This usb interface stuff is really becoming a morass.  The core
>> functionality is fairly independent of the interface.  I'm inclined to
>> say that we should start with a simple specification (only bus.addr),
>> and try to get both pvusb and hvmusb in.  Then we can talk about where
>> to add additional specifications (including cross-boot stable
>> specifcations).
>
> So Ian J, Ian C, Wei and I chatted face-to-face about what to do going
> forward; below are some key points we discussed and the conclusion we
> came to.  Decisions are only official when they've been discussed on the
> list, so please consider this a proposal and give your feedback. :-)
>
> (Also, Ian/Ian/Wei, let me know if I've misremembered or forgotten
> something.)
>
> Points of discussion:
>
> * We would ideally like to be able to have the released interface work
> both for both PV and HVM; for one so that we don't have to have separate
> #defines for that functionality; but also to make sure that the
> interface is suitable for both functionalities.
>
> * It's difficult at the moment to actually do collaborative development
> on the libxl USB feature, because the code is not yet in the tree.
>
> * Regarding user-facing interfaces (like xl, as opposed to libxl): the
> interface cannot be half-baked; it should not provide functionality
> which works most of the time but sometimes will fail.
>
> Having only "bus-ports" or "vendorid:deviceid" is not sufficient,
> because it will lure the user into thinking that they can put those
> numbers into a config file and get repeatable results every time.  But
> since bus numbers change, and vendorid:deviceid is not unique, either of
> these would be a false promise.
>
> Udevs ID_PATH naming scheme seems like a sensible thing to adopt, at
> least for Linux.  We could consider making an OS-specific string for
> identifying the same device across reboots.
>
> On the other hand, bus.address is very obviously unstable; nobody in
> their right mind would use it for anything they wanted to persist across
> reboots.  So including bus.address as a temporary measure to be able to
> test the underlying library until we get a more reliable naming scheme
> in place would be OK, as long as the UI interface could be extended
> going forward.
>
> * We should avoid adding complexity to the libxl interface until it's
> needed; accepting one way of specifying USB devices, and letting the
> toolstack do translation into that way of specifying it (perhaps
> providing helper libraries to do so), should be enough for now.  The way
> of specifying USB devices does not need to be stable across reboots, as
> long as it won't change between the time the toolstack does the
> translation and the time the device is plugged in.
>
> bus.address is the best specification from that point of view: it's
> unique (unlike device:vendorid), and if a device is unplugged and
> another one plugged in between the time the translation happens and the
> time libxl gets around to doing something, the old bus.address won't
> exist anymore and the command will fail.
>
> * There may be a point in the future when we want to be able provide
> device auto-plug functionality at the libxl layer.  (i.e., "When device
> X shows up, please plug it into VM Y.")  For this we will need a
> reliable way of specifying devices; bus.address will not do.
>
> But that functionality doesn't exist yet; so for now we should stick
> with bus.address, but design the interface such that it can be extended
> with more options for specifying a device when such functionality is neede.
>
> With all that in mind, here is a proposal:
>
> 1. For the moment, only use bus.address at the libxl layer to specify a
> device.
>
> 2. Let's check in the libxl part of Chunyan's PVUSB series as soon as
> the 4.7 development window opens (assuming the coding style issues have
> all been addressed).  We can also check in the xl functionality with
> minimal bus.address support for testing.
>
> 3. I will the port the HVM USB series and submit them as soon as possible.
>
> 4. We work on a set of helper functions that a toolstack can use to
> translate other ways of specifying a device, much like the disk
> specification helper functions that we provide.  One of these should be
> something which is reliably stable over reboots, such as the udev
> ID_PATH specification.
>
> Thoughts?

I'm absolutely fine with this proposal.


Juergen

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

* Proposed plan for libxl USB interface (was Re: [PATCH V4 3/7] libxl: add pvusb API)
  2015-06-22 13:29                           ` Proposed plan for libxl USB interface (was Re: [PATCH V4 3/7] libxl: add pvusb API) George Dunlap
  2015-06-22 14:14                             ` Juergen Gross
@ 2015-06-22 14:22                             ` Ian Jackson
  2015-06-23  2:42                             ` Chun Yan Liu
                                               ` (2 subsequent siblings)
  4 siblings, 0 replies; 88+ messages in thread
From: Ian Jackson @ 2015-06-22 14:22 UTC (permalink / raw)
  To: George Dunlap
  Cc: Juergen Gross, Wei Liu, Ian Campbell, Chunyan Liu, xen-devel,
	Jim Fehlig, Simon Cao

George Dunlap writes ("Proposed plan for libxl USB interface (was Re: [Xen-devel] [PATCH V4 3/7] libxl: add pvusb API)"):
> With all that in mind, here is a proposal:

FAOD, this all sounds good.  I have one comment on this:

> 4. We work on a set of helper functions that a toolstack can use to
> translate other ways of specifying a device, much like the disk
> specification helper functions that we provide.  One of these should be
> something which is reliably stable over reboots, such as the udev
> ID_PATH specification.

We should invent, similar to the disk specification, a specification
for how to interpret a string referring to a usb device.  That can be
used by xl but also by libvirt and anyone else that wants to.

If we don't know right away how this will work, then we should come up
with a temporary arrangement which encodes bus.address in a region of
the string syntax space which we are confident we won't need in the
future for something else.

Ian.

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

* Proposed plan for libxl USB interface (was Re: [PATCH V4 3/7] libxl: add pvusb API)
  2015-06-22 13:29                           ` Proposed plan for libxl USB interface (was Re: [PATCH V4 3/7] libxl: add pvusb API) George Dunlap
  2015-06-22 14:14                             ` Juergen Gross
  2015-06-22 14:22                             ` Ian Jackson
@ 2015-06-23  2:42                             ` Chun Yan Liu
  2015-06-23  2:43                             ` Chun Yan Liu
  2015-06-23  2:44                             ` Chun Yan Liu
  4 siblings, 0 replies; 88+ messages in thread
From: Chun Yan Liu @ 2015-06-23  2:42 UTC (permalink / raw)
  To: Ian Campbell, George Dunlap, Ian Jackson
  Cc: Juergen Gross, Jim Fehlig, Simon Cao, Wei Liu, xen-devel



>>> On 6/22/2015 at 09:29 PM, in message <55880DCC.6070902@eu.citrix.com>, George
Dunlap <george.dunlap@eu.citrix.com> wrote: 
> On 06/18/2015 01:08 PM, George Dunlap wrote: 
> > This usb interface stuff is really becoming a morass.  The core 
> > functionality is fairly independent of the interface.  I'm inclined to 
> > say that we should start with a simple specification (only bus.addr), 
> > and try to get both pvusb and hvmusb in.  Then we can talk about where 
> > to add additional specifications (including cross-boot stable 
> > specifcations). 
>  
> So Ian J, Ian C, Wei and I chatted face-to-face about what to do going 
> forward; below are some key points we discussed and the conclusion we 
> came to.  Decisions are only official when they've been discussed on the 
> list, so please consider this a proposal and give your feedback. :-) 
>  
> (Also, Ian/Ian/Wei, let me know if I've misremembered or forgotten 
> something.) 
>  
> Points of discussion: 
>  
> * We would ideally like to be able to have the released interface work 
> both for both PV and HVM; for one so that we don't have to have separate 
> #defines for that functionality; but also to make sure that the 
> interface is suitable for both functionalities. 
>  
> * It's difficult at the moment to actually do collaborative development 
> on the libxl USB feature, because the code is not yet in the tree. 
>  
> * Regarding user-facing interfaces (like xl, as opposed to libxl): the 
> interface cannot be half-baked; it should not provide functionality 
> which works most of the time but sometimes will fail. 
>  
> Having only "bus-ports" or "vendorid:deviceid" is not sufficient, 
> because it will lure the user into thinking that they can put those 
> numbers into a config file and get repeatable results every time.  But 
> since bus numbers change, and vendorid:deviceid is not unique, either of 
> these would be a false promise. 
>  
> Udevs ID_PATH naming scheme seems like a sensible thing to adopt, at 
> least for Linux.  We could consider making an OS-specific string for 
> identifying the same device across reboots. 
>  
> On the other hand, bus.address is very obviously unstable; nobody in 
> their right mind would use it for anything they wanted to persist across 
> reboots.  So including bus.address as a temporary measure to be able to 
> test the underlying library until we get a more reliable naming scheme 
> in place would be OK, as long as the UI interface could be extended 
> going forward. 
>  
> * We should avoid adding complexity to the libxl interface until it's 
> needed; accepting one way of specifying USB devices, and letting the 
> toolstack do translation into that way of specifying it (perhaps 
> providing helper libraries to do so), should be enough for now.  The way 
> of specifying USB devices does not need to be stable across reboots, as 
> long as it won't change between the time the toolstack does the 
> translation and the time the device is plugged in. 
>  
> bus.address is the best specification from that point of view: it's 
> unique (unlike device:vendorid), and if a device is unplugged and 
> another one plugged in between the time the translation happens and the 
> time libxl gets around to doing something, the old bus.address won't 
> exist anymore and the command will fail. 
>  
> * There may be a point in the future when we want to be able provide 
> device auto-plug functionality at the libxl layer.  (i.e., "When device 
> X shows up, please plug it into VM Y.")  For this we will need a 
> reliable way of specifying devices; bus.address will not do. 
>  
> But that functionality doesn't exist yet; so for now we should stick 
> with bus.address, but design the interface such that it can be extended 
> with more options for specifying a device when such functionality is neede. 
>  
> With all that in mind, here is a proposal: 
>  
> 1. For the moment, only use bus.address at the libxl layer to specify a 
> device. 
>  
> 2. Let's check in the libxl part of Chunyan's PVUSB series as soon as 
> the 4.7 development window opens (assuming the coding style issues have 
> all been addressed).  We can also check in the xl functionality with 
> minimal bus.address support for testing. 
>  
> 3. I will the port the HVM USB series and submit them as soon as possible. 
>  
> 4. We work on a set of helper functions that a toolstack can use to 
> translate other ways of specifying a device, much like the disk 
> specification helper functions that we provide.  One of these should be 
> something which is reliably stable over reboots, such as the udev 
> ID_PATH specification. 
>  
> Thoughts? 

Fine to me.

>  
>  -George 
>  
>  

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

* Proposed plan for libxl USB interface (was Re: [PATCH V4 3/7] libxl: add pvusb API)
  2015-06-22 13:29                           ` Proposed plan for libxl USB interface (was Re: [PATCH V4 3/7] libxl: add pvusb API) George Dunlap
                                               ` (2 preceding siblings ...)
  2015-06-23  2:42                             ` Chun Yan Liu
@ 2015-06-23  2:43                             ` Chun Yan Liu
  2015-06-23  2:44                             ` Chun Yan Liu
  4 siblings, 0 replies; 88+ messages in thread
From: Chun Yan Liu @ 2015-06-23  2:43 UTC (permalink / raw)
  To: Ian Campbell, George Dunlap, Ian Jackson
  Cc: Juergen Gross, Jim Fehlig, Simon Cao, Wei Liu, xen-devel



>>> On 6/22/2015 at 09:29 PM, in message <55880DCC.6070902@eu.citrix.com>, George
Dunlap <george.dunlap@eu.citrix.com> wrote: 
> On 06/18/2015 01:08 PM, George Dunlap wrote: 
> > This usb interface stuff is really becoming a morass.  The core 
> > functionality is fairly independent of the interface.  I'm inclined to 
> > say that we should start with a simple specification (only bus.addr), 
> > and try to get both pvusb and hvmusb in.  Then we can talk about where 
> > to add additional specifications (including cross-boot stable 
> > specifcations). 
>  
> So Ian J, Ian C, Wei and I chatted face-to-face about what to do going 
> forward; below are some key points we discussed and the conclusion we 
> came to.  Decisions are only official when they've been discussed on the 
> list, so please consider this a proposal and give your feedback. :-) 
>  
> (Also, Ian/Ian/Wei, let me know if I've misremembered or forgotten 
> something.) 
>  
> Points of discussion: 
>  
> * We would ideally like to be able to have the released interface work 
> both for both PV and HVM; for one so that we don't have to have separate 
> #defines for that functionality; but also to make sure that the 
> interface is suitable for both functionalities. 
>  
> * It's difficult at the moment to actually do collaborative development 
> on the libxl USB feature, because the code is not yet in the tree. 
>  
> * Regarding user-facing interfaces (like xl, as opposed to libxl): the 
> interface cannot be half-baked; it should not provide functionality 
> which works most of the time but sometimes will fail. 
>  
> Having only "bus-ports" or "vendorid:deviceid" is not sufficient, 
> because it will lure the user into thinking that they can put those 
> numbers into a config file and get repeatable results every time.  But 
> since bus numbers change, and vendorid:deviceid is not unique, either of 
> these would be a false promise. 
>  
> Udevs ID_PATH naming scheme seems like a sensible thing to adopt, at 
> least for Linux.  We could consider making an OS-specific string for 
> identifying the same device across reboots. 
>  
> On the other hand, bus.address is very obviously unstable; nobody in 
> their right mind would use it for anything they wanted to persist across 
> reboots.  So including bus.address as a temporary measure to be able to 
> test the underlying library until we get a more reliable naming scheme 
> in place would be OK, as long as the UI interface could be extended 
> going forward. 
>  
> * We should avoid adding complexity to the libxl interface until it's 
> needed; accepting one way of specifying USB devices, and letting the 
> toolstack do translation into that way of specifying it (perhaps 
> providing helper libraries to do so), should be enough for now.  The way 
> of specifying USB devices does not need to be stable across reboots, as 
> long as it won't change between the time the toolstack does the 
> translation and the time the device is plugged in. 
>  
> bus.address is the best specification from that point of view: it's 
> unique (unlike device:vendorid), and if a device is unplugged and 
> another one plugged in between the time the translation happens and the 
> time libxl gets around to doing something, the old bus.address won't 
> exist anymore and the command will fail. 
>  
> * There may be a point in the future when we want to be able provide 
> device auto-plug functionality at the libxl layer.  (i.e., "When device 
> X shows up, please plug it into VM Y.")  For this we will need a 
> reliable way of specifying devices; bus.address will not do. 
>  
> But that functionality doesn't exist yet; so for now we should stick 
> with bus.address, but design the interface such that it can be extended 
> with more options for specifying a device when such functionality is neede. 
>  
> With all that in mind, here is a proposal: 
>  
> 1. For the moment, only use bus.address at the libxl layer to specify a 
> device. 
>  
> 2. Let's check in the libxl part of Chunyan's PVUSB series as soon as 
> the 4.7 development window opens (assuming the coding style issues have 
> all been addressed).  We can also check in the xl functionality with 
> minimal bus.address support for testing. 
>  
> 3. I will the port the HVM USB series and submit them as soon as possible. 
>  
> 4. We work on a set of helper functions that a toolstack can use to 
> translate other ways of specifying a device, much like the disk 
> specification helper functions that we provide.  One of these should be 
> something which is reliably stable over reboots, such as the udev 
> ID_PATH specification. 
>  
> Thoughts? 

Fine to me.

>  
>  -George 
>  
>  

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

* Proposed plan for libxl USB interface (was Re: [PATCH V4 3/7] libxl: add pvusb API)
  2015-06-22 13:29                           ` Proposed plan for libxl USB interface (was Re: [PATCH V4 3/7] libxl: add pvusb API) George Dunlap
                                               ` (3 preceding siblings ...)
  2015-06-23  2:43                             ` Chun Yan Liu
@ 2015-06-23  2:44                             ` Chun Yan Liu
  4 siblings, 0 replies; 88+ messages in thread
From: Chun Yan Liu @ 2015-06-23  2:44 UTC (permalink / raw)
  To: Ian Campbell, George Dunlap, Ian Jackson
  Cc: Juergen Gross, Jim Fehlig, Simon Cao, Wei Liu, xen-devel



>>> On 6/22/2015 at 09:29 PM, in message <55880DCC.6070902@eu.citrix.com>, George
Dunlap <george.dunlap@eu.citrix.com> wrote: 
> On 06/18/2015 01:08 PM, George Dunlap wrote: 
> > This usb interface stuff is really becoming a morass.  The core 
> > functionality is fairly independent of the interface.  I'm inclined to 
> > say that we should start with a simple specification (only bus.addr), 
> > and try to get both pvusb and hvmusb in.  Then we can talk about where 
> > to add additional specifications (including cross-boot stable 
> > specifcations). 
>  
> So Ian J, Ian C, Wei and I chatted face-to-face about what to do going 
> forward; below are some key points we discussed and the conclusion we 
> came to.  Decisions are only official when they've been discussed on the 
> list, so please consider this a proposal and give your feedback. :-) 
>  
> (Also, Ian/Ian/Wei, let me know if I've misremembered or forgotten 
> something.) 
>  
> Points of discussion: 
>  
> * We would ideally like to be able to have the released interface work 
> both for both PV and HVM; for one so that we don't have to have separate 
> #defines for that functionality; but also to make sure that the 
> interface is suitable for both functionalities. 
>  
> * It's difficult at the moment to actually do collaborative development 
> on the libxl USB feature, because the code is not yet in the tree. 
>  
> * Regarding user-facing interfaces (like xl, as opposed to libxl): the 
> interface cannot be half-baked; it should not provide functionality 
> which works most of the time but sometimes will fail. 
>  
> Having only "bus-ports" or "vendorid:deviceid" is not sufficient, 
> because it will lure the user into thinking that they can put those 
> numbers into a config file and get repeatable results every time.  But 
> since bus numbers change, and vendorid:deviceid is not unique, either of 
> these would be a false promise. 
>  
> Udevs ID_PATH naming scheme seems like a sensible thing to adopt, at 
> least for Linux.  We could consider making an OS-specific string for 
> identifying the same device across reboots. 
>  
> On the other hand, bus.address is very obviously unstable; nobody in 
> their right mind would use it for anything they wanted to persist across 
> reboots.  So including bus.address as a temporary measure to be able to 
> test the underlying library until we get a more reliable naming scheme 
> in place would be OK, as long as the UI interface could be extended 
> going forward. 
>  
> * We should avoid adding complexity to the libxl interface until it's 
> needed; accepting one way of specifying USB devices, and letting the 
> toolstack do translation into that way of specifying it (perhaps 
> providing helper libraries to do so), should be enough for now.  The way 
> of specifying USB devices does not need to be stable across reboots, as 
> long as it won't change between the time the toolstack does the 
> translation and the time the device is plugged in. 
>  
> bus.address is the best specification from that point of view: it's 
> unique (unlike device:vendorid), and if a device is unplugged and 
> another one plugged in between the time the translation happens and the 
> time libxl gets around to doing something, the old bus.address won't 
> exist anymore and the command will fail. 
>  
> * There may be a point in the future when we want to be able provide 
> device auto-plug functionality at the libxl layer.  (i.e., "When device 
> X shows up, please plug it into VM Y.")  For this we will need a 
> reliable way of specifying devices; bus.address will not do. 
>  
> But that functionality doesn't exist yet; so for now we should stick 
> with bus.address, but design the interface such that it can be extended 
> with more options for specifying a device when such functionality is neede. 
>  
> With all that in mind, here is a proposal: 
>  
> 1. For the moment, only use bus.address at the libxl layer to specify a 
> device. 
>  
> 2. Let's check in the libxl part of Chunyan's PVUSB series as soon as 
> the 4.7 development window opens (assuming the coding style issues have 
> all been addressed).  We can also check in the xl functionality with 
> minimal bus.address support for testing. 
>  
> 3. I will the port the HVM USB series and submit them as soon as possible. 
>  
> 4. We work on a set of helper functions that a toolstack can use to 
> translate other ways of specifying a device, much like the disk 
> specification helper functions that we provide.  One of these should be 
> something which is reliably stable over reboots, such as the udev 
> ID_PATH specification. 
>  
> Thoughts? 

Fine to me.

>  
>  -George 
>  
>  

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-15 17:47   ` George Dunlap
@ 2015-06-23 10:18     ` Chun Yan Liu
  2015-06-23 11:29       ` George Dunlap
  0 siblings, 1 reply; 88+ messages in thread
From: Chun Yan Liu @ 2015-06-23 10:18 UTC (permalink / raw)
  To: George Dunlap, xen-devel; +Cc: Ian.Jackson, Simon Cao, wei.liu2, ian.campbell



>>> On 6/16/2015 at 01:47 AM, in message <557F0FA7.2060402@eu.citrix.com>, George
Dunlap <george.dunlap@eu.citrix.com> wrote: 
> On 06/10/2015 04:20 AM, Chunyan Liu wrote: 
> > Add pvusb APIs, including: 
> >  - attach/detach (create/destroy) virtual usb controller. 
> >  - attach/detach usb device 
> >  - list usb controller and usb devices 
> >  - some other helper functions 
> >  
> > Signed-off-by: Chunyan Liu <cyliu@suse.com> 
> > Signed-off-by: Simon Cao <caobosimon@gmail.com> 
> >  
> > --- 
> > changes: 
> >   - make libxl_device_usbctrl_add async, to be consistent with 
> >     libxl_device_usbctrl_remove, using MACROs DEFINE_DEVICE_ADD 
> >     and DEFINE_DEVICES_ADD, adjusting related codes. 
> >   - correct update_json related processing. 
> >   - use libxl__* helper functions instead of calloc, realloc 
> >     and strdup, etc. whereever possible. 
> >   - merge protocol definition pv|qemu in this patch 
> >   - treat it as warning at rebind failure instead of error in usb_remove 
> >   - add documentation docs/misc/pvusb.txt to describe pvusb 
> >     details (toolstack design, libxl design, xenstore info, etc.) 
> >   - other fixes addring Wei and George's comments 
> >  
> >  docs/misc/pvusb.txt                  |  243 +++++++ 
> >  tools/libxl/Makefile                 |    2 +- 
> >  tools/libxl/libxl.c                  |    6 + 
> >  tools/libxl/libxl.h                  |   65 ++ 
> >  tools/libxl/libxl_internal.h         |   16 +- 
> >  tools/libxl/libxl_osdeps.h           |   13 + 
> >  tools/libxl/libxl_pvusb.c            | 1249  
> ++++++++++++++++++++++++++++++++++ 
> >  tools/libxl/libxl_types.idl          |   52 ++ 
> >  tools/libxl/libxl_types_internal.idl |    1 + 
> >  tools/libxl/libxl_utils.c            |   16 + 
> >  10 files changed, 1661 insertions(+), 2 deletions(-) 
> >  create mode 100644 docs/misc/pvusb.txt 
> >  create mode 100644 tools/libxl/libxl_pvusb.c 
> >  
> > diff --git a/docs/misc/pvusb.txt b/docs/misc/pvusb.txt 
> > new file mode 100644 
> > index 0000000..4cdf965 
> > --- /dev/null 
> > +++ b/docs/misc/pvusb.txt 
> > @@ -0,0 +1,243 @@ 
> > +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). 
> > + 
> > +Additionally, for easy use of PVUSB, you need support in the toolstack 
> > +to get the two sides to talk to each other. 
>  
> I think this paragraph is probably unnecessary.  By the time this is 
> checked in, the toolstack will have the necessary support. 
>  
> > +2. Specifying a host USB device 
> > + 
> > +QEMU hmp commands allows USB devices to be specified either by their 
>  
> s/hmp/qmp/; ? 
>  
> > +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. 
>  
> This paragraph comparing the different ways of specifying devices makes 
> sense to include in the 0/N series summary, but not so much in a file 
> we're checking in. 
>  
> > + 
> > +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 Hub could not be assigned to guest. 
>  
> "USB hubs cannot be assigned to a guest." 
>  
> [snip] 
>  
> > +int libxl_device_usbctrl_getinfo(libxl_ctx *ctx, uint32_t domid, 
> > +                                libxl_device_usbctrl *usbctrl, 
> > +                                libxl_usbctrlinfo *usbctrlinfo) 
> > +{ 
> > +    GC_INIT(ctx); 
> > +    char *dompath, *usbctrlpath; 
> > +    char *val; 
> > +    int rc = 0; 
> > + 
> > +    usbctrlinfo->devid = usbctrl->devid; 
> > +    usbctrlinfo->ports = usbctrl->ports; 
> > +    usbctrlinfo->version = usbctrl->version; 
> > +    usbctrlinfo->protocol = usbctrl->protocol; 
>  
> You seem to have missed my message about this -- the only thing you are 
> allowed to read from usbctrl in this function is the devid. Everything 
> else you have to look up and give back to the user. That's the point of 
> the function -- the user has the devid and is asking *you* how many 
> ports there are, what usb version it is, &c. 

Agree. Will update.

>  
> [snip] 
> > +/* get usb devices under certain usb controller */ 
> > +static int 
> > +libxl__device_usb_list_per_usbctrl(libxl__gc *gc, uint32_t domid, int  
> usbctrl, 
>  
> Should usbctrl be of type libxl_devid?
 
To be strict, it should be libxl_devid. But libxl_devid is actually 'int'. I see most
current APIs also uses 'int'. Like libxl_devid_to_device_vtpm API, devid also uses
'int'. Anyway, I can update :)

>  
>  
> > +static int libxl__device_usb_setdefault(libxl__gc *gc, uint32_t domid, 
> > +                                        libxl_device_usb *usb, 
> > +                                        bool update_json) 
> > +{ 
> > +    char *be_path, *tmp; 
> > + 
> > +    if (usb->ctrl == -1) { 
> > +        int ret = libxl__device_usb_set_default_usbctrl(gc, domid, usb); 
> > +        /* If no existing ctrl to host this usb device, setup a new one */ 
> > +        if (ret) { 
> > +            libxl_device_usbctrl usbctrl; 
> > +            libxl_device_usbctrl_init(&usbctrl); 
> > +            if (libxl_device_usbctrl_add_common(CTX, domid, &usbctrl, 
> > +                                                0, update_json)) { 
> > +                LOG(ERROR, "Failed to create usb controller"); 
> > +                return ERROR_INVAL; 
> > +            } 
> > +            usb->ctrl = usbctrl.devid; 
> > +            usb->port = 1; 
> > +            libxl_device_usbctrl_dispose(&usbctrl); 
> > +        } 
> > +    } 
>  
> Sorry for not noticing this before -- it  looks like if you set 
> usb->ctrl to -1, it will automatically choose both a controller and a 
> port number.  But what if you want to specify that you want a particular 
> controller (for example, if you want to specify the PV controller rather 
> than the emulated one, or vice versa), but didn't want to have to 
> manually keep track of which ports were free?

That is libxl__device_usb_set_default_usbctrl's work, it will try to find
an available port for USB device. If there is no available port, then it will
create a new USB controller and by default uses its first port.
>  
> It seems like it would be better to have the code treat port 0 as 
> "automatically choose a port for me". 

Here we set port=1 because port number is starting from 1. Like, if there
are 4 ports, port number will be 1, 2, 3, 4 (not 0,1 ,2, 3). Since xend, it
behaves like this. I think that's what pvusb driver needs. Juergen, right?

>  
> (If this were the only thing holding it up I would say this wouldn't be 
> a blocker to going in.) 
>  
> > +static int libxl__device_usb_remove(libxl__gc *gc, uint32_t domid, 
> > +                                    libxl_device_usb *usb) 
> > +{ 
> > +    libxl_device_usb *usbs = NULL; 
> > +    libxl_device_usb *usb_find = NULL; 
> > +    int i, num = 0, rc; 
> > + 
> > +    assert(usb->busid || (usb->hostbus > 0 && usb->hostaddr > 0)); 
> > + 
> > +    if (!usb->busid) { 
> > +        usb->busid = usb_busaddr_to_busid(gc, usb->hostbus, usb->hostaddr); 
> > +        if (!usb->busid) { 
> > +            LOG(ERROR, "USB device doesn't exist in sysfs"); 
> > +            return ERROR_INVAL; 
> > +        } 
> > +    } 
>  
> So here you're keying the removal on the *host* idea of what the device 
> is.  But the standard would be to key this on the *guest* idea of what 
> the device is.  When you're doing disk removal, you don't say 
>  
> "xl block-detach 1 /images/foo.img" 
>  
> that is, the path to the disk image; you say 
>  
> "xl block-detach 1 xvda" 
>  
> that is, the image as seen from the guest. 
>  
> Since there is no devid, you should make it possible to remove by 
> <ctrl,port>.  Removing also by hostbus:hostaddr seems like useful 
> functionality, so it's probably not bad to keep it; but the <ctrl,port> 
> should be the main functionality. 

Do you think <ctrl,port> is better? That means in qemu emulated way,
user also need to know the <ctrl, port> info of the USB device. In the past,
for usb-add or usb-delete, <ctrl, port> info is hidden to user, it used
bus.addr or verndorid.deviceid.

>  
> > +int libxl_device_usb_getinfo(libxl_ctx *ctx, libxl_device_usb *usb, 
> > +                             libxl_usbinfo *usbinfo) 
> > +{ 
> > +    GC_INIT(ctx); 
> > +    char *filename; 
> > +    void *buf = NULL; 
> > + 
> > +    usbinfo->ctrl = usb->ctrl; 
> > +    usbinfo->port = usb->port; 
> > + 
> > +    if (usb->busid) 
> > +        usbinfo->busid = libxl__strdup(NOGC, usb->busid); 
> > +    else if (usb->hostbus > 0 && usb->hostaddr > 0) 
> > +        usbinfo->busid = usb_busaddr_to_busid(gc, usb->hostbus, usb->hostaddr); 
>  
> Similar to my libxl_device_usbctrl_getinfo() comment -- the purpose of 
> this function is to specify a minimal amount of information, and have 
> the library return and look up everything else.  Since libxl_device_usb 
> doesn't have a devid, the "key" for this should probably be <ctrl,port>. 
>  Which means, you are only allowed to read usb->{ctrl,port}; everything 
> else you have to look up. 

Agree. Will update.

Thanks,
Chunyan

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

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-23 10:18     ` Chun Yan Liu
@ 2015-06-23 11:29       ` George Dunlap
  2015-06-24  2:26         ` Chun Yan Liu
  0 siblings, 1 reply; 88+ messages in thread
From: George Dunlap @ 2015-06-23 11:29 UTC (permalink / raw)
  To: Chun Yan Liu, xen-devel; +Cc: Ian.Jackson, Simon Cao, wei.liu2, ian.campbell

On 06/23/2015 11:18 AM, Chun Yan Liu wrote:
>>>> On 6/16/2015 at 01:47 AM, in message <557F0FA7.2060402@eu.citrix.com>, George
> Dunlap <george.dunlap@eu.citrix.com> wrote: 
>>> +static int libxl__device_usb_setdefault(libxl__gc *gc, uint32_t domid, 
>>> +                                        libxl_device_usb *usb, 
>>> +                                        bool update_json) 
>>> +{ 
>>> +    char *be_path, *tmp; 
>>> + 
>>> +    if (usb->ctrl == -1) { 
>>> +        int ret = libxl__device_usb_set_default_usbctrl(gc, domid, usb); 
>>> +        /* If no existing ctrl to host this usb device, setup a new one */ 
>>> +        if (ret) { 
>>> +            libxl_device_usbctrl usbctrl; 
>>> +            libxl_device_usbctrl_init(&usbctrl); 
>>> +            if (libxl_device_usbctrl_add_common(CTX, domid, &usbctrl, 
>>> +                                                0, update_json)) { 
>>> +                LOG(ERROR, "Failed to create usb controller"); 
>>> +                return ERROR_INVAL; 
>>> +            } 
>>> +            usb->ctrl = usbctrl.devid; 
>>> +            usb->port = 1; 
>>> +            libxl_device_usbctrl_dispose(&usbctrl); 
>>> +        } 
>>> +    } 
>>  
>> Sorry for not noticing this before -- it  looks like if you set 
>> usb->ctrl to -1, it will automatically choose both a controller and a 
>> port number.  But what if you want to specify that you want a particular 
>> controller (for example, if you want to specify the PV controller rather 
>> than the emulated one, or vice versa), but didn't want to have to 
>> manually keep track of which ports were free?
> 
> That is libxl__device_usb_set_default_usbctrl's work, it will try to find
> an available port for USB device. If there is no available port, then it will
> create a new USB controller and by default uses its first port.
>>  
>> It seems like it would be better to have the code treat port 0 as 
>> "automatically choose a port for me". 
> 
> Here we set port=1 because port number is starting from 1. Like, if there
> are 4 ports, port number will be 1, 2, 3, 4 (not 0,1 ,2, 3). Since xend, it
> behaves like this. I think that's what pvusb driver needs. Juergen, right?

I think you misunderstood what I was saying.

There are three cases I think we want to consider:

1. The caller knows both the controller and the port number they want to
assign it to.

2. The caller knows what controller they want to assign it to, but they
want libxl to choose the port number automatically.

3. The caller wants libxl to choose both the controller and the port
automatically.
  3a. A controller already exists with a free port
  3b. No controllers with free ports exist.

Your code handles #1 properly -- if both controller and port number are
set, it will try to add the USB device to that specific controller and
port number.

Your code also handles #3a properly -- if the controller is not set, it
will automatically choose a controller and a port number.  It also
handles #3b properly -- if there are no controllers, or if the
controllers have no ports available, then it will create a new one and
assign it to port 1.

Your code does not, however, handle the second case -- where the user
knows they want to plug it into a specific controller (for instance, the
PVUSB one rather than the emulated one), but don't want to keep track of
which ports are available.

Since ports start as 1, then '0' is an invalid number for a port (just
as -1 is an invalid id for a controller).  I was suggesting that you
could use '0' as a magic number meaning, "Please choose a port for me."

However, after our discussion here about providing "helpers" to
translate stuff for the libxl interface, if the other maintainers will
like the "automatically create a controller" functionality at all; or if
they would rather we (again) provide helper functions so that the
toolstack can do this work.

>>> +static int libxl__device_usb_remove(libxl__gc *gc, uint32_t domid, 
>>> +                                    libxl_device_usb *usb) 
>>> +{ 
>>> +    libxl_device_usb *usbs = NULL; 
>>> +    libxl_device_usb *usb_find = NULL; 
>>> +    int i, num = 0, rc; 
>>> + 
>>> +    assert(usb->busid || (usb->hostbus > 0 && usb->hostaddr > 0)); 
>>> + 
>>> +    if (!usb->busid) { 
>>> +        usb->busid = usb_busaddr_to_busid(gc, usb->hostbus, usb->hostaddr); 
>>> +        if (!usb->busid) { 
>>> +            LOG(ERROR, "USB device doesn't exist in sysfs"); 
>>> +            return ERROR_INVAL; 
>>> +        } 
>>> +    } 
>>  
>> So here you're keying the removal on the *host* idea of what the device 
>> is.  But the standard would be to key this on the *guest* idea of what 
>> the device is.  When you're doing disk removal, you don't say 
>>  
>> "xl block-detach 1 /images/foo.img" 
>>  
>> that is, the path to the disk image; you say 
>>  
>> "xl block-detach 1 xvda" 
>>  
>> that is, the image as seen from the guest. 
>>  
>> Since there is no devid, you should make it possible to remove by 
>> <ctrl,port>.  Removing also by hostbus:hostaddr seems like useful 
>> functionality, so it's probably not bad to keep it; but the <ctrl,port> 
>> should be the main functionality. 
> 
> Do you think <ctrl,port> is better? That means in qemu emulated way,
> user also need to know the <ctrl, port> info of the USB device. In the past,
> for usb-add or usb-delete, <ctrl, port> info is hidden to user, it used
> bus.addr or verndorid.deviceid.

Hmm -- you know, you're right.  For vif, vfb, and vkb it seems to use
devid (which is libxl specific, but indexed per vm); disk uses vdev
(which is indexed per vm); but pci pass-through uses BDF, which is based
on the host.  (And that's what my HVM series from last year did as well.)

BTW, to remove a device over qmp, you need the name you gave the device
when you assigned it.  But at least as of a year ago, there was no way
to query qemu to see which devices you had assigned; so you have to
store that information away in xenstore somewhere anyway.  So from a
qemu perspective, having a devid or guest <ctrl,port> mapping isn't a
big deal.

Also, from a UI perspective: it should be easy for xl to translate host
bus.addr into guest <ctrl,port>, so I don't think that's as big a deal.

The main reason I have for wanting to do it at the guest level is so
that we can use the same interface for things which have no host handle
-- i.e., plugging or unplugging a virtual tablet, or maybe a USB disk.

 -George

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

* Re: [PATCH V4 3/7] libxl: add pvusb API
  2015-06-23 11:29       ` George Dunlap
@ 2015-06-24  2:26         ` Chun Yan Liu
  0 siblings, 0 replies; 88+ messages in thread
From: Chun Yan Liu @ 2015-06-24  2:26 UTC (permalink / raw)
  To: George Dunlap, xen-devel; +Cc: Ian.Jackson, Simon Cao, wei.liu2, ian.campbell



>>> On 6/23/2015 at 07:29 PM, in message <558942FF.5060702@eu.citrix.com>, George
Dunlap <george.dunlap@eu.citrix.com> wrote: 
> On 06/23/2015 11:18 AM, Chun Yan Liu wrote: 
>>>>> On 6/16/2015 at 01:47 AM, in message <557F0FA7.2060402@eu.citrix.com>, George 
> > Dunlap <george.dunlap@eu.citrix.com> wrote:  
> >>> +static int libxl__device_usb_setdefault(libxl__gc *gc, uint32_t domid,  
> >>> +                                        libxl_device_usb *usb,  
> >>> +                                        bool update_json)  
> >>> +{  
> >>> +    char *be_path, *tmp;  
> >>> +  
> >>> +    if (usb->ctrl == -1) {  
> >>> +        int ret = libxl__device_usb_set_default_usbctrl(gc, domid, usb);  
> >>> +        /* If no existing ctrl to host this usb device, setup a new one */  
>  
> >>> +        if (ret) {  
> >>> +            libxl_device_usbctrl usbctrl;  
> >>> +            libxl_device_usbctrl_init(&usbctrl);  
> >>> +            if (libxl_device_usbctrl_add_common(CTX, domid, &usbctrl,  
> >>> +                                                0, update_json)) {  
> >>> +                LOG(ERROR, "Failed to create usb controller");  
> >>> +                return ERROR_INVAL;  
> >>> +            }  
> >>> +            usb->ctrl = usbctrl.devid;  
> >>> +            usb->port = 1;  
> >>> +            libxl_device_usbctrl_dispose(&usbctrl);  
> >>> +        }  
> >>> +    }  
> >>   
> >> Sorry for not noticing this before -- it  looks like if you set  
> >> usb->ctrl to -1, it will automatically choose both a controller and a  
> >> port number.  But what if you want to specify that you want a particular  
> >> controller (for example, if you want to specify the PV controller rather  
> >> than the emulated one, or vice versa), but didn't want to have to  
> >> manually keep track of which ports were free? 
> >  
> > That is libxl__device_usb_set_default_usbctrl's work, it will try to find 
> > an available port for USB device. If there is no available port, then it  
> will 
> > create a new USB controller and by default uses its first port. 
> >>   
> >> It seems like it would be better to have the code treat port 0 as  
> >> "automatically choose a port for me".  
> >  
> > Here we set port=1 because port number is starting from 1. Like, if there 
> > are 4 ports, port number will be 1, 2, 3, 4 (not 0,1 ,2, 3). Since xend, it 
> > behaves like this. I think that's what pvusb driver needs. Juergen, right? 
>  
> I think you misunderstood what I was saying. 
>  
> There are three cases I think we want to consider: 
>  
> 1. The caller knows both the controller and the port number they want to 
> assign it to. 
>  
> 2. The caller knows what controller they want to assign it to, but they 
> want libxl to choose the port number automatically. 
>  
> 3. The caller wants libxl to choose both the controller and the port 
> automatically. 
>   3a. A controller already exists with a free port 
>   3b. No controllers with free ports exist. 
>  
> Your code handles #1 properly -- if both controller and port number are 
> set, it will try to add the USB device to that specific controller and 
> port number. 
>  
> Your code also handles #3a properly -- if the controller is not set, it 
> will automatically choose a controller and a port number.  It also 
> handles #3b properly -- if there are no controllers, or if the 
> controllers have no ports available, then it will create a new one and 
> assign it to port 1. 
>  
> Your code does not, however, handle the second case -- where the user 
> knows they want to plug it into a specific controller (for instance, the 
> PVUSB one rather than the emulated one), but don't want to keep track of 
> which ports are available. 
>  
> Since ports start as 1, then '0' is an invalid number for a port (just 
> as -1 is an invalid id for a controller).  I was suggesting that you 
> could use '0' as a magic number meaning, "Please choose a port for me." 

Oh, I see. Thanks for explanation. This IS what we didn't cover, currently only
support either specifying both controller and port, or both not. If user specifies
controller and port, then we will use that controller and port, if it's not available,
we just report error, but won't choose a default available one for it. Choosing
a port or creating a new controller only happens when use doesn't specify
controller and port.

I think case 2 is very useful. I will update code to cover.

>  
> However, after our discussion here about providing "helpers" to 
> translate stuff for the libxl interface, if the other maintainers will 
> like the "automatically create a controller" functionality at all; or if 
> they would rather we (again) provide helper functions so that the 
> toolstack can do this work. 
>  
> >>> +static int libxl__device_usb_remove(libxl__gc *gc, uint32_t domid,  
> >>> +                                    libxl_device_usb *usb)  
> >>> +{  
> >>> +    libxl_device_usb *usbs = NULL;  
> >>> +    libxl_device_usb *usb_find = NULL;  
> >>> +    int i, num = 0, rc;  
> >>> +  
> >>> +    assert(usb->busid || (usb->hostbus > 0 && usb->hostaddr > 0));  
> >>> +  
> >>> +    if (!usb->busid) {  
> >>> +        usb->busid = usb_busaddr_to_busid(gc, usb->hostbus, usb->hostaddr);  
> >>> +        if (!usb->busid) {  
> >>> +            LOG(ERROR, "USB device doesn't exist in sysfs");  
> >>> +            return ERROR_INVAL;  
> >>> +        }  
> >>> +    }  
> >>   
> >> So here you're keying the removal on the *host* idea of what the device  
> >> is.  But the standard would be to key this on the *guest* idea of what  
> >> the device is.  When you're doing disk removal, you don't say  
> >>   
> >> "xl block-detach 1 /images/foo.img"  
> >>   
> >> that is, the path to the disk image; you say  
> >>   
> >> "xl block-detach 1 xvda"  
> >>   
> >> that is, the image as seen from the guest.  
> >>   
> >> Since there is no devid, you should make it possible to remove by  
> >> <ctrl,port>.  Removing also by hostbus:hostaddr seems like useful  
> >> functionality, so it's probably not bad to keep it; but the <ctrl,port>  
> >> should be the main functionality.  
> >  
> > Do you think <ctrl,port> is better? That means in qemu emulated way, 
> > user also need to know the <ctrl, port> info of the USB device. In the past, 
> > for usb-add or usb-delete, <ctrl, port> info is hidden to user, it used 
> > bus.addr or verndorid.deviceid. 
>  
> Hmm -- you know, you're right.  For vif, vfb, and vkb it seems to use 
> devid (which is libxl specific, but indexed per vm); disk uses vdev 
> (which is indexed per vm); but pci pass-through uses BDF, which is based 
> on the host.  (And that's what my HVM series from last year did as well.) 
>  
> BTW, to remove a device over qmp, you need the name you gave the device 
> when you assigned it.  But at least as of a year ago, there was no way 
> to query qemu to see which devices you had assigned; so you have to 
> store that information away in xenstore somewhere anyway.  So from a 
> qemu perspective, having a devid or guest <ctrl,port> mapping isn't a 
> big deal.

OK. If qemu side has no problem, I'll change the interface to be <ctrl, port>.

Thanks,
Chunyan

 >  
> Also, from a UI perspective: it should be easy for xl to translate host 
> bus.addr into guest <ctrl,port>, so I don't think that's as big a deal. 
>  
> The main reason I have for wanting to do it at the guest level is so 
> that we can use the same interface for things which have no host handle 
> -- i.e., plugging or unplugging a virtual tablet, or maybe a USB disk. 
>  
>  -George 
>  
>  
>  

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

end of thread, other threads:[~2015-06-24  2:26 UTC | newest]

Thread overview: 88+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-10  3:20 [PATCH V4 0/7] xen pvusb toolstack work Chunyan Liu
2015-06-10  3:20 ` [PATCH V4 1/7] libxl: export some functions for pvusb use Chunyan Liu
2015-06-11 16:08   ` Ian Jackson
2015-06-11 16:28     ` Wei Liu
2015-06-12 15:14       ` Ian Jackson
2015-06-10  3:20 ` [PATCH V4 2/7] libxl_read_file_contents: add new entry to read sysfs file Chunyan Liu
2015-06-11 16:16   ` Ian Jackson
2015-06-12  7:00     ` Chun Yan Liu
2015-06-12 15:11       ` Ian Jackson
2015-06-10  3:20 ` [PATCH V4 3/7] libxl: add pvusb API Chunyan Liu
2015-06-11 15:00   ` Juergen Gross
2015-06-11 16:07     ` Ian Jackson
2015-06-11 16:42   ` Ian Jackson
2015-06-12  7:39     ` Chun Yan Liu
2015-06-12  8:06       ` Chun Yan Liu
2015-06-12 11:22       ` Ian Jackson
2015-06-15 14:17   ` George Dunlap
2015-06-15 14:25     ` Jürgen Groß
2015-06-15 14:34       ` George Dunlap
2015-06-15 18:26         ` Juergen Gross
2015-06-16 10:30           ` George Dunlap
2015-06-16 10:51             ` Juergen Gross
2015-06-16 11:11               ` George Dunlap
2015-06-16 11:19                 ` Juergen Gross
2015-06-16 11:23                   ` George Dunlap
2015-06-16 11:44                     ` Ian Jackson
2015-06-17 11:24                       ` Ian Campbell
2015-06-18 11:50                         ` George Dunlap
2015-06-18 12:08                         ` George Dunlap
2015-06-18 13:03                           ` Juergen Gross
2015-06-22 13:29                           ` Proposed plan for libxl USB interface (was Re: [PATCH V4 3/7] libxl: add pvusb API) George Dunlap
2015-06-22 14:14                             ` Juergen Gross
2015-06-22 14:22                             ` Ian Jackson
2015-06-23  2:42                             ` Chun Yan Liu
2015-06-23  2:43                             ` Chun Yan Liu
2015-06-23  2:44                             ` Chun Yan Liu
2015-06-16 10:41     ` [PATCH V4 3/7] libxl: add pvusb API Ian Jackson
2015-06-16 10:56       ` Jürgen Groß
2015-06-16 11:03         ` George Dunlap
2015-06-16 11:10         ` Ian Jackson
2015-06-16 11:25           ` Juergen Gross
2015-06-16 11:45             ` George Dunlap
2015-06-16 12:02               ` Ian Jackson
2015-06-16 13:19                 ` George Dunlap
2015-06-16 13:32                   ` Juergen Gross
2015-06-16 13:37                   ` [PATCH V4 3/7] libxl: add pvusb API [and 1 more messages] Ian Jackson
2015-06-16 14:41                     ` George Dunlap
2015-06-16 15:58                       ` Sander Eikelenboom
2015-06-16 15:59                       ` Ian Jackson
2015-06-16 16:34                         ` George Dunlap
2015-06-17  3:59                           ` Juergen Gross
2015-06-17 10:27                             ` George Dunlap
2015-06-18  6:24                               ` Chun Yan Liu
2015-06-16 11:45             ` [PATCH V4 3/7] libxl: add pvusb API Ian Jackson
2015-06-16 13:06               ` Juergen Gross
2015-06-16 13:09                 ` George Dunlap
2015-06-16 13:23                   ` Juergen Gross
2015-06-16 13:29                     ` George Dunlap
2015-06-16 13:49                       ` Juergen Gross
2015-06-16 14:06                         ` George Dunlap
2015-06-16 14:20                           ` Juergen Gross
2015-06-16 14:37                             ` George Dunlap
2015-06-17 11:34                             ` Ian Campbell
2015-06-17 11:40                               ` Juergen Gross
2015-06-18  6:20                               ` Chun Yan Liu
2015-06-18  7:02                                 ` Juergen Gross
2015-06-18  8:50                                   ` Ian Campbell
2015-06-18 13:02                                     ` Juergen Gross
2015-06-16 15:38             ` George Dunlap
2015-06-16 11:01       ` George Dunlap
2015-06-16 11:12         ` Ian Jackson
2015-06-16 11:21           ` George Dunlap
2015-06-16 16:32             ` Ian Jackson
2015-06-16 16:39               ` George Dunlap
2015-06-16 16:51                 ` Ross Philipson
2015-06-17  4:03                   ` Jürgen Groß
2015-06-17 13:48                     ` Ross Philipson
2015-06-15 17:47   ` George Dunlap
2015-06-23 10:18     ` Chun Yan Liu
2015-06-23 11:29       ` George Dunlap
2015-06-24  2:26         ` Chun Yan Liu
2015-06-10  3:20 ` [PATCH V4 4/7] libxl: add libxl_device_usb_assignable_list API Chunyan Liu
2015-06-10  3:20 ` [PATCH V4 5/7] xl: add pvusb commands Chunyan Liu
2015-06-12  7:37   ` Juergen Gross
2015-06-12  8:03     ` Chun Yan Liu
2015-06-12  8:22       ` Juergen Gross
2015-06-10  3:20 ` [PATCH V4 6/7] xl: add usb-assignable-list command Chunyan Liu
2015-06-10  3:20 ` [PATCH V4 7/7] domcreate: support pvusb in configuration file Chunyan Liu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).