[libvirt] [PATCH] qemu: Support to detach redirdev device

Osier Yang osier at yunify.com
Sat Feb 27 09:50:44 UTC 2016


Attaching redirdev device has been supported for a while, but detaching
is not never implemented.

Simple procedure to test:

% lsusb
Bus 001 Device 014: ID 0781:5567 SanDisk Corp. Cruzer Blade

% usbredirserver -p 4000 0781:5567

% virsh attach-device test usb.xml

  % cat usb.xml
  <redirdev bus='usb' type='tcp'>
    <source mode='connect' host='192.168.84.6' service='4000'/>
  </redirdev>

% virsh detach-device test usb.xml

% virsh qemu-monitor-command test --pretty '{"execute": "query-chardev"}' | grep 4000

On success, the chardev should not seen in output of above command.
---
 src/conf/domain_conf.c   | 67 +++++++++++++++++++++++++++++++++
 src/conf/domain_conf.h   |  4 ++
 src/libvirt_private.syms |  3 ++
 src/qemu/qemu_driver.c   |  4 +-
 src/qemu/qemu_hotplug.c  | 97 +++++++++++++++++++++++++++++++++++++++++++++++-
 src/qemu/qemu_hotplug.h  |  3 ++
 6 files changed, 176 insertions(+), 2 deletions(-)

diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 3b15cb4..d304232 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -13825,6 +13825,73 @@ virDomainMemoryRemove(virDomainDefPtr def,
     return ret;
 }
 
+ssize_t
+virDomainRedirdevFind(virDomainDefPtr def,
+                      virDomainRedirdevDefPtr redirdev)
+{
+    size_t i;
+
+    for (i = 0; i < def->nredirdevs; i++) {
+        virDomainRedirdevDefPtr tmp = def->redirdevs[i];
+
+        if (redirdev->bus != tmp->bus)
+            continue;
+
+        virDomainChrSourceDef source_chr = redirdev->source.chr;
+        virDomainChrSourceDef tmp_chr = tmp->source.chr;
+
+        if (source_chr.type != tmp_chr.type)
+            continue;
+
+        switch (source_chr.type) {
+        case VIR_DOMAIN_CHR_TYPE_TCP:
+            if (STRNEQ_NULLABLE(source_chr.data.tcp.host,
+                                tmp_chr.data.tcp.host))
+                continue;
+            if (STRNEQ_NULLABLE(source_chr.data.tcp.service,
+                                tmp_chr.data.tcp.service))
+                continue;
+            if (source_chr.data.tcp.listen != tmp_chr.data.tcp.listen)
+                continue;
+            if (source_chr.data.tcp.protocol != tmp_chr.data.tcp.protocol)
+                continue;
+            break;
+
+        case VIR_DOMAIN_CHR_TYPE_SPICEVMC:
+            if (source_chr.data.spicevmc != tmp_chr.data.spicevmc)
+                continue;
+            break;
+
+        default:
+            /* Unlikely, currently redirdev only supports character device of
+             * type "tcp" and "spicevmc".
+             */
+            break;
+        }
+
+        if (redirdev->info.type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE &&
+            !virDomainDeviceInfoAddressIsEqual(&redirdev->info, &tmp->info))
+            continue;
+
+        break;
+    }
+
+    if (i < def->nredirdevs)
+        return i;
+
+    return -1;
+}
+
+virDomainRedirdevDefPtr
+virDomainRedirdevRemove(virDomainDefPtr def,
+                        size_t idx)
+{
+    virDomainRedirdevDefPtr ret = def->redirdevs[idx];
+
+    VIR_DELETE_ELEMENT(def->redirdevs, idx, def->nredirdevs);
+
+    return ret;
+}
 
 char *
 virDomainDefGetDefaultEmulator(virDomainDefPtr def,
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 1de3be3..03c0155 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2538,6 +2538,10 @@ void virDomainHostdevDefClear(virDomainHostdevDefPtr def);
 void virDomainHostdevDefFree(virDomainHostdevDefPtr def);
 void virDomainHubDefFree(virDomainHubDefPtr def);
 void virDomainRedirdevDefFree(virDomainRedirdevDefPtr def);
+ssize_t virDomainRedirdevFind(virDomainDefPtr def,
+                              virDomainRedirdevDefPtr redirdev);
+virDomainRedirdevDefPtr virDomainRedirdevRemove(virDomainDefPtr def,
+                                                size_t idx);
 void virDomainRedirFilterDefFree(virDomainRedirFilterDefPtr def);
 void virDomainShmemDefFree(virDomainShmemDefPtr def);
 void virDomainDeviceDefFree(virDomainDeviceDefPtr def);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 4b40612..ad7d82c 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -423,6 +423,9 @@ virDomainPMSuspendedReasonTypeFromString;
 virDomainPMSuspendedReasonTypeToString;
 virDomainRedirdevBusTypeFromString;
 virDomainRedirdevBusTypeToString;
+virDomainRedirdevDefFree;
+virDomainRedirdevFind;
+virDomainRedirdevRemove;
 virDomainRNGBackendTypeToString;
 virDomainRNGDefFree;
 virDomainRNGFind;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 45ff3c0..8905af6 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -7736,6 +7736,9 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm,
     case VIR_DOMAIN_DEVICE_MEMORY:
         ret = qemuDomainDetachMemoryDevice(driver, vm, dev->data.memory);
         break;
+    case VIR_DOMAIN_DEVICE_REDIRDEV:
+        ret = qemuDomainDetachRedirdevDevice(driver, vm, dev->data.redirdev);
+        break;
 
     case VIR_DOMAIN_DEVICE_FS:
     case VIR_DOMAIN_DEVICE_INPUT:
@@ -7748,7 +7751,6 @@ qemuDomainDetachDeviceLive(virDomainObjPtr vm,
     case VIR_DOMAIN_DEVICE_MEMBALLOON:
     case VIR_DOMAIN_DEVICE_NVRAM:
     case VIR_DOMAIN_DEVICE_SHMEM:
-    case VIR_DOMAIN_DEVICE_REDIRDEV:
     case VIR_DOMAIN_DEVICE_NONE:
     case VIR_DOMAIN_DEVICE_TPM:
     case VIR_DOMAIN_DEVICE_PANIC:
diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index dc76268..bbe8aa7 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -3287,6 +3287,49 @@ qemuDomainRemoveRNGDevice(virQEMUDriverPtr driver,
 }
 
 
+static int
+qemuDomainRemoveRedirdevDevice(virQEMUDriverPtr driver,
+                               virDomainObjPtr vm,
+                               virDomainRedirdevDefPtr redirdev)
+{
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    virObjectEventPtr event;
+    char *charAlias = NULL;
+    ssize_t idx;
+    int rc;
+    int ret = -1;
+
+    VIR_DEBUG("Removing redirdev device %s from domain %p %s",
+              redirdev->info.alias, vm, vm->def->name);
+
+    if (virAsprintf(&charAlias, "char%s", redirdev->info.alias) < 0)
+        return -1;
+
+    qemuDomainObjEnterMonitor(driver, vm);
+    rc = qemuMonitorDetachCharDev(priv->mon, charAlias);
+    if (qemuDomainObjExitMonitor(driver, vm) < 0)
+        goto cleanup;
+
+    virDomainAuditRedirdev(vm, redirdev, "detach", rc == 0);
+
+    if (rc < 0)
+        goto cleanup;
+
+    event = virDomainEventDeviceRemovedNewFromObj(vm, redirdev->info.alias);
+    qemuDomainEventQueue(driver, event);
+
+    if ((idx = virDomainRedirdevFind(vm->def, redirdev)) >= 0)
+        virDomainRedirdevRemove(vm->def, idx);
+    qemuDomainReleaseDeviceAddress(vm, &redirdev->info, NULL);
+    virDomainRedirdevDefFree(redirdev);
+
+    ret = 0;
+
+ cleanup:
+    VIR_FREE(charAlias);
+    return ret;
+}
+
 int
 qemuDomainRemoveDevice(virQEMUDriverPtr driver,
                        virDomainObjPtr vm,
@@ -3318,6 +3361,10 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver,
         ret = qemuDomainRemoveMemoryDevice(driver, vm, dev->data.memory);
         break;
 
+    case VIR_DOMAIN_DEVICE_REDIRDEV:
+         ret = qemuDomainRemoveRedirdevDevice(driver, vm, dev->data.redirdev);
+         break;
+
     case VIR_DOMAIN_DEVICE_NONE:
     case VIR_DOMAIN_DEVICE_LEASE:
     case VIR_DOMAIN_DEVICE_FS:
@@ -3327,7 +3374,6 @@ qemuDomainRemoveDevice(virQEMUDriverPtr driver,
     case VIR_DOMAIN_DEVICE_WATCHDOG:
     case VIR_DOMAIN_DEVICE_GRAPHICS:
     case VIR_DOMAIN_DEVICE_HUB:
-    case VIR_DOMAIN_DEVICE_REDIRDEV:
     case VIR_DOMAIN_DEVICE_SMARTCARD:
     case VIR_DOMAIN_DEVICE_MEMBALLOON:
     case VIR_DOMAIN_DEVICE_NVRAM:
@@ -4318,3 +4364,52 @@ qemuDomainDetachMemoryDevice(virQEMUDriverPtr driver,
     qemuDomainResetDeviceRemoval(vm);
     return ret;
 }
+
+int
+qemuDomainDetachRedirdevDevice(virQEMUDriverPtr driver,
+                               virDomainObjPtr vm,
+                               virDomainRedirdevDefPtr redirdev)
+{
+    qemuDomainObjPrivatePtr priv = vm->privateData;
+    virDomainRedirdevDefPtr tmp;
+    ssize_t idx;
+    int rc;
+    int ret = -1;
+
+    if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_DEVICE)) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("qemu does not support -device"));
+        return -1;
+    }
+
+    if ((idx = virDomainRedirdevFind(vm->def, redirdev)) < 0) {
+        virReportError(VIR_ERR_OPERATION_INVALID, "%s",
+                       _("device not present in domain configuration"));
+        return -1;
+    }
+
+    tmp = vm->def->redirdevs[idx];
+
+    if (!tmp->info.alias) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("alias not set for redirdev device"));
+        return -1;
+    }
+
+    qemuDomainMarkDeviceForRemoval(vm, &tmp->info);
+
+    qemuDomainObjEnterMonitor(driver, vm);
+    rc = qemuMonitorDelDevice(priv->mon, tmp->info.alias);
+    if (qemuDomainObjExitMonitor(driver, vm) || rc < 0)
+        goto cleanup;
+
+    rc = qemuDomainWaitForDeviceRemoval(vm);
+    if (rc == 0 || rc == 1)
+        ret = qemuDomainRemoveRedirdevDevice(driver, vm, tmp);
+    else
+        ret = 0;
+
+ cleanup:
+    qemuDomainResetDeviceRemoval(vm);
+    return ret;
+}
diff --git a/src/qemu/qemu_hotplug.h b/src/qemu/qemu_hotplug.h
index 4140da3..4ef42e9 100644
--- a/src/qemu/qemu_hotplug.h
+++ b/src/qemu/qemu_hotplug.h
@@ -51,6 +51,9 @@ int qemuDomainAttachNetDevice(virConnectPtr conn,
 int qemuDomainAttachRedirdevDevice(virQEMUDriverPtr driver,
                                    virDomainObjPtr vm,
                                    virDomainRedirdevDefPtr hostdev);
+int qemuDomainDetachRedirdevDevice(virQEMUDriverPtr driver,
+                                   virDomainObjPtr vm,
+                                   virDomainRedirdevDefPtr redirdev);
 int qemuDomainAttachHostDevice(virConnectPtr conn,
                                virQEMUDriverPtr driver,
                                virDomainObjPtr vm,
-- 
2.1.4




More information about the libvir-list mailing list