[libvirt] [PATCH v3 01/12] conf: add replug option for usb hostdev

Jonathon Jongsma jjongsma at redhat.com
Wed Oct 9 17:02:18 UTC 2019


On Tue, 2019-09-17 at 16:47 +0300, Nikolay Shirokovskiy wrote:
> If usb device attached to a domain is unplugged from host and
> then plugged back then it will no longer be available in guest.
> We are going to support this case so that device will be detached
> from qemu on unplug and attached back on replug. As sometimes
> this behaviour is not desirable and for backcompat too let's
> add 'replug' option for usb hostdev.
> 
> Signed-off-by: Nikolay Shirokovskiy <nshirokovskiy at virtuozzo.com>
> ---
>  docs/formatdomain.html.in                     | 10 ++++-
>  docs/schemas/domaincommon.rng                 |  5 +++
>  src/conf/domain_conf.c                        | 30 ++++++++++++++
>  src/conf/domain_conf.h                        |  2 +
>  tests/qemuxml2argvdata/hostdev-usb-replug.xml | 36 +++++++++++++++++
>  .../qemuxml2xmloutdata/hostdev-usb-replug.xml | 40
> +++++++++++++++++++
>  tests/qemuxml2xmltest.c                       |  1 +
>  7 files changed, 122 insertions(+), 2 deletions(-)
>  create mode 100644 tests/qemuxml2argvdata/hostdev-usb-replug.xml
>  create mode 100644 tests/qemuxml2xmloutdata/hostdev-usb-replug.xml
> 
> diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
> index 86a5261e47..5b0d41760b 100644
> --- a/docs/formatdomain.html.in
> +++ b/docs/formatdomain.html.in
> @@ -4678,7 +4678,7 @@
>  <pre>
>  ...
>  <devices>
> -  <hostdev mode='subsystem' type='usb'>
> +  <hostdev mode='subsystem' type='usb' replug='yes'>
>      <source startupPolicy='optional'>
>        <vendor id='0x1234'/>
>        <product id='0xbeef'/>
> @@ -4777,7 +4777,13 @@
>            <dt><code>usb</code></dt>
>            <dd>USB devices are detached from the host on guest
> startup
>              and reattached after the guest exits or the device is
> -            hot-unplugged.
> +            hot-unplugged. If optional <code>replug</code>
> +            (<span class="since">since 5.8.0</span>) is "yes" then
> libvirt
> +            tracks USB device unplug/plug on host. On unplug the
> correspondent

"corresponding" is a bit better here

> +            QEMU device will be be deleted but device stays in
> libvirt config.

Do we want to mention qemu explicitly here? Presumably this
configuration option could be hypervisor indepedendant? Maybe it's
better to refer generically to the "guest" or "hypervisor" rather than
qemu?

> +            On plug the device will be added back to QEMU. This
> applies only
> +            for USB devices with product/vendor pair specified.
> Default value
> +            is "no".
>            </dd>
>            <dt><code>pci</code></dt>
>            <dd>For PCI devices, when <code>managed</code> is "yes" it
> is
> diff --git a/docs/schemas/domaincommon.rng
> b/docs/schemas/domaincommon.rng
> index cae3be639e..8afce21deb 100644
> --- a/docs/schemas/domaincommon.rng
> +++ b/docs/schemas/domaincommon.rng
> @@ -4644,6 +4644,11 @@
>      <attribute name="type">
>        <value>usb</value>
>      </attribute>
> +    <optional>
> +      <attribute name="replug">
> +        <ref name="virYesNo"/>
> +      </attribute>
> +    </optional>
>      <element name="source">
>        <optional>
>          <ref name="startupPolicy"/>
> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
> index 848c831330..db065f6a5b 100644
> --- a/src/conf/domain_conf.c
> +++ b/src/conf/domain_conf.c
> @@ -7660,6 +7660,13 @@
> virDomainHostdevSubsysUSBDefParseXML(xmlNodePtr node,
>          goto out;
>      }
>  
> +    if (usbsrc->replug && (!got_vendor || !got_product)) {
> +        virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
> +                       _("replug is only possible if vendor/product
> "
> +                         "pair is specified"));
> +        goto out;
> +    }
> +
>      ret = 0;
>   out:
>      return ret;
> @@ -8113,12 +8120,14 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr
> node,
>      virDomainHostdevSubsysSCSIPtr scsisrc = &def-
> >source.subsys.u.scsi;
>      virDomainHostdevSubsysSCSIVHostPtr scsihostsrc = &def-
> >source.subsys.u.scsi_host;
>      virDomainHostdevSubsysMediatedDevPtr mdevsrc = &def-
> >source.subsys.u.mdev;
> +    virDomainHostdevSubsysUSBPtr usbsrc = &def->source.subsys.u.usb;
>      VIR_AUTOFREE(char *) managed = NULL;
>      VIR_AUTOFREE(char *) sgio = NULL;
>      VIR_AUTOFREE(char *) rawio = NULL;
>      VIR_AUTOFREE(char *) backendStr = NULL;
>      VIR_AUTOFREE(char *) model = NULL;
>      VIR_AUTOFREE(char *) display = NULL;
> +    VIR_AUTOFREE(char *) replug = NULL;
>  
>      /* @managed can be read from the xml document - it is always an
>       * attribute of the toplevel element, no matter what type of
> @@ -8134,6 +8143,7 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr
> node,
>      rawio = virXMLPropString(node, "rawio");
>      model = virXMLPropString(node, "model");
>      display = virXMLPropString(node, "display");
> +    replug = virXMLPropString(node, "replug");
>  
>      /* @type is passed in from the caller rather than read from the
>       * xml document, because it is specified in different places for
> @@ -8200,6 +8210,20 @@ virDomainHostdevDefParseXMLSubsys(xmlNodePtr
> node,
>          }
>      }
>  
> +    if (replug) {
> +        if (def->source.subsys.type !=
> VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) {
> +            virReportError(VIR_ERR_XML_ERROR, "%s",
> +                           _("replug is only supported for usb host
> device"));
> +            return -1;
> +        }
> +
> +        if ((usbsrc->replug = virTristateBoolTypeFromString(replug))
> <= 0) {
> +            virReportError(VIR_ERR_XML_ERROR,
> +                           _("unknown hostdev replug setting '%s'"),
> rawio);
> +            return -1;
> +        }
> +    }
> +
>      if (def->source.subsys.type !=
> VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_MDEV &&
>          def->source.subsys.type !=
> VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_SCSI_HOST) {
>          if (model) {
> @@ -27139,6 +27163,7 @@ virDomainHostdevDefFormat(virBufferPtr buf,
>      virDomainHostdevSubsysSCSIPtr scsisrc = &def-
> >source.subsys.u.scsi;
>      virDomainHostdevSubsysMediatedDevPtr mdevsrc = &def-
> >source.subsys.u.mdev;
>      virDomainHostdevSubsysSCSIVHostPtr scsihostsrc = &def-
> >source.subsys.u.scsi_host;
> +    virDomainHostdevSubsysUSBPtr usbsrc = &def->source.subsys.u.usb;
>      const char *type;
>  
>      if (!mode) {
> @@ -27203,6 +27228,11 @@ virDomainHostdevDefFormat(virBufferPtr buf,
>                                    virTristateSwitchTypeToString(mdev
> src->display));
>          }
>  
> +        if (def->source.subsys.type ==
> VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB &&
> +            usbsrc->replug) {
> +            virBufferAsprintf(buf, " replug='%s'",
> +                              virTristateBoolTypeToString(usbsrc-
> >replug));
> +        }
>      }
>      virBufferAddLit(buf, ">\n");
>      virBufferAdjustIndent(buf, 2);
> diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
> index b688ee2b83..44a339ab0c 100644
> --- a/src/conf/domain_conf.h
> +++ b/src/conf/domain_conf.h
> @@ -230,6 +230,8 @@ struct _virDomainHostdevSubsysUSB {
>  
>      unsigned vendor;
>      unsigned product;
> +
> +    bool replug;
>  };
>  
>  struct _virDomainHostdevSubsysPCI {
> diff --git a/tests/qemuxml2argvdata/hostdev-usb-replug.xml
> b/tests/qemuxml2argvdata/hostdev-usb-replug.xml
> new file mode 100644
> index 0000000000..9647385667
> --- /dev/null
> +++ b/tests/qemuxml2argvdata/hostdev-usb-replug.xml
> @@ -0,0 +1,36 @@
> +<domain type='qemu'>
> +  <name>QEMUGuest1</name>
> +  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
> +  <memory unit='KiB'>219136</memory>
> +  <currentMemory unit='KiB'>219136</currentMemory>
> +  <vcpu placement='static'>1</vcpu>
> +  <os>
> +    <type arch='i686' machine='pc'>hvm</type>
> +    <boot dev='hd'/>
> +  </os>
> +  <clock offset='utc'/>
> +  <on_poweroff>destroy</on_poweroff>
> +  <on_reboot>restart</on_reboot>
> +  <on_crash>destroy</on_crash>
> +  <devices>
> +    <emulator>/usr/bin/qemu-system-i686</emulator>
> +    <disk type='block' device='disk'>
> +      <driver name='qemu' type='raw'/>
> +      <source dev='/dev/HostVG/QEMUGuest1'/>
> +      <target dev='hda' bus='ide'/>
> +      <address type='drive' controller='0' bus='0' target='0'
> unit='0'/>
> +    </disk>
> +    <controller type='usb' index='0'/>
> +    <controller type='ide' index='0'/>
> +    <controller type='pci' index='0' model='pci-root'/>
> +    <input type='mouse' bus='ps2'/>
> +    <input type='keyboard' bus='ps2'/>
> +    <hostdev mode='subsystem' type='usb' managed='no' replug='yes'>
> +      <source>
> +        <vendor id='0x1234'/>
> +        <product id='0xbeef'/>
> +      </source>
> +    </hostdev>
> +    <memballoon model='none'/>
> +  </devices>
> +</domain>
> diff --git a/tests/qemuxml2xmloutdata/hostdev-usb-replug.xml
> b/tests/qemuxml2xmloutdata/hostdev-usb-replug.xml
> new file mode 100644
> index 0000000000..5f4e39e2c4
> --- /dev/null
> +++ b/tests/qemuxml2xmloutdata/hostdev-usb-replug.xml
> @@ -0,0 +1,40 @@
> +<domain type='qemu'>
> +  <name>QEMUGuest1</name>
> +  <uuid>c7a5fdbd-edaf-9455-926a-d65c16db1809</uuid>
> +  <memory unit='KiB'>219136</memory>
> +  <currentMemory unit='KiB'>219136</currentMemory>
> +  <vcpu placement='static'>1</vcpu>
> +  <os>
> +    <type arch='i686' machine='pc'>hvm</type>
> +    <boot dev='hd'/>
> +  </os>
> +  <clock offset='utc'/>
> +  <on_poweroff>destroy</on_poweroff>
> +  <on_reboot>restart</on_reboot>
> +  <on_crash>destroy</on_crash>
> +  <devices>
> +    <emulator>/usr/bin/qemu-system-i686</emulator>
> +    <disk type='block' device='disk'>
> +      <driver name='qemu' type='raw'/>
> +      <source dev='/dev/HostVG/QEMUGuest1'/>
> +      <target dev='hda' bus='ide'/>
> +      <address type='drive' controller='0' bus='0' target='0'
> unit='0'/>
> +    </disk>
> +    <controller type='usb' index='0'>
> +      <address type='pci' domain='0x0000' bus='0x00' slot='0x01'
> function='0x2'/>
> +    </controller>
> +    <controller type='ide' index='0'>
> +      <address type='pci' domain='0x0000' bus='0x00' slot='0x01'
> function='0x1'/>
> +    </controller>
> +    <controller type='pci' index='0' model='pci-root'/>
> +    <input type='mouse' bus='ps2'/>
> +    <input type='keyboard' bus='ps2'/>
> +    <hostdev mode='subsystem' type='usb' managed='no' replug='yes'>
> +      <source>
> +        <vendor id='0x1234'/>
> +        <product id='0xbeef'/>
> +      </source>
> +    </hostdev>
> +    <memballoon model='none'/>
> +  </devices>
> +</domain>
> diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
> index d5c66d8791..14b94321b0 100644
> --- a/tests/qemuxml2xmltest.c
> +++ b/tests/qemuxml2xmltest.c
> @@ -439,6 +439,7 @@ mymain(void)
>      DO_TEST("channel-unix-source-path", NONE);
>  
>      DO_TEST("hostdev-usb-address", NONE);
> +    DO_TEST("hostdev-usb-replug", NONE);
>      DO_TEST("hostdev-pci-address", NONE);
>      DO_TEST("hostdev-pci-multifunction", NONE);
>      DO_TEST("hostdev-vfio", NONE);




More information about the libvir-list mailing list