[libvirt] [PATCH 9/9] qemu_hotplug: Support interface type of vhost-user hotplug

Michal Privoznik mprivozn at redhat.com
Tue Aug 16 15:41:22 UTC 2016


https://bugzilla.redhat.com/show_bug.cgi?id=1366108

So far, the hotplug of vhost-user "worked" by pure chance. Well,
qemu would error on our commands, but nevertheless. Now that we
have everything prepare, We should support hotplugging og
vhost-user. Firstly, we need to plug in chardev (through which
qemu talks to OpenVSwitch), then netdev and only after that we
can plug in the virtio-net-pci device.

Signed-off-by: Michal Privoznik <mprivozn at redhat.com>
---
 src/qemu/qemu_hotplug.c | 49 +++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 45 insertions(+), 4 deletions(-)

diff --git a/src/qemu/qemu_hotplug.c b/src/qemu/qemu_hotplug.c
index feb1f44..0bcb411 100644
--- a/src/qemu/qemu_hotplug.c
+++ b/src/qemu/qemu_hotplug.c
@@ -933,6 +933,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
     virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
     virDomainCCWAddressSetPtr ccwaddrs = NULL;
     size_t i;
+    char *charDevAlias = NULL;
 
     /* preallocate new slot for device */
     if (VIR_REALLOC_N(vm->def->nets, vm->def->nnets + 1) < 0)
@@ -954,11 +955,11 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
     case VIR_DOMAIN_NET_TYPE_DIRECT:
     case VIR_DOMAIN_NET_TYPE_BRIDGE:
     case VIR_DOMAIN_NET_TYPE_HOSTDEV:
+    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
         /* These types are supported. */
         break;
 
     case VIR_DOMAIN_NET_TYPE_USER:
-    case VIR_DOMAIN_NET_TYPE_VHOSTUSER:
     case VIR_DOMAIN_NET_TYPE_SERVER:
     case VIR_DOMAIN_NET_TYPE_CLIENT:
     case VIR_DOMAIN_NET_TYPE_MCAST:
@@ -1148,6 +1149,26 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
             goto cleanup;
     }
 
+    if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
+        if (!qemuDomainSupportsNetdev(vm->def, priv->qemuCaps, net)) {
+            virReportError(VIR_ERR_INTERNAL_ERROR,
+                           "%s", _("Netdev support unavailable"));
+            goto cleanup;
+        }
+
+        if (virAsprintf(&charDevAlias, "char%s", net->info.alias) < 0)
+            goto cleanup;
+
+        qemuDomainObjEnterMonitor(driver, vm);
+        if (qemuMonitorAttachCharDev(priv->mon, charDevAlias, net->data.vhostuser) < 0) {
+            ignore_value(qemuDomainObjExitMonitor(driver, vm));
+            virDomainAuditNet(vm, NULL, net, "attach", false);
+            goto cleanup;
+        }
+        if (qemuDomainObjExitMonitor(driver, vm) < 0)
+            goto cleanup;
+    }
+
     qemuDomainObjEnterMonitor(driver, vm);
     if (qemuDomainSupportsNetdev(vm->def, priv->qemuCaps, net)) {
         if (qemuMonitorAddNetdev(priv->mon, netstr,
@@ -1268,6 +1289,7 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
     }
     VIR_FREE(vhostfd);
     VIR_FREE(vhostfdName);
+    VIR_FREE(charDevAlias);
     virObjectUnref(cfg);
     virDomainCCWAddressSetFree(ccwaddrs);
 
@@ -1283,6 +1305,9 @@ qemuDomainAttachNetDevice(virQEMUDriverPtr driver,
             if (virAsprintf(&netdev_name, "host%s", net->info.alias) < 0)
                 goto cleanup;
             qemuDomainObjEnterMonitor(driver, vm);
+            if (charDevAlias &&
+                qemuMonitorDetachCharDev(priv->mon, charDevAlias) < 0)
+                VIR_WARN("Failed to remove associated chardev %s", charDevAlias);
             if (qemuMonitorRemoveNetdev(priv->mon, netdev_name) < 0)
                 VIR_WARN("Failed to remove network backend for netdev %s",
                          netdev_name);
@@ -3309,10 +3334,12 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
     virNetDevVPortProfilePtr vport;
     virObjectEventPtr event;
     char *hostnet_name = NULL;
+    char *charDevAlias = NULL;
     size_t i;
     int ret = -1;
+    int actualType = virDomainNetGetActualType(net);
 
-    if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
+    if (actualType == VIR_DOMAIN_NET_TYPE_HOSTDEV) {
         /* this function handles all hostdev and netdev cleanup */
         ret = qemuDomainRemoveHostDevice(driver, vm,
                                          virDomainNetGetActualHostdev(net));
@@ -3322,9 +3349,11 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
     VIR_DEBUG("Removing network interface %s from domain %p %s",
               net->info.alias, vm, vm->def->name);
 
-    if (virAsprintf(&hostnet_name, "host%s", net->info.alias) < 0)
+    if (virAsprintf(&hostnet_name, "host%s", net->info.alias) < 0 ||
+        virAsprintf(&charDevAlias, "char%s", net->info.alias) < 0)
         goto cleanup;
 
+
     qemuDomainObjEnterMonitor(driver, vm);
     if (qemuDomainSupportsNetdev(vm->def, priv->qemuCaps, net)) {
         if (qemuMonitorRemoveNetdev(priv->mon, hostnet_name) < 0) {
@@ -3347,6 +3376,17 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
             goto cleanup;
         }
     }
+
+    if (actualType == VIR_DOMAIN_NET_TYPE_VHOSTUSER) {
+        /* vhostuser has a chardev too */
+        if (qemuMonitorDetachCharDev(priv->mon, charDevAlias) < 0) {
+            /* well, this is a messy situation. Guest visible PCI device has
+             * been removed, netdev too but chardev not. The best seems to be
+             * to just ignore the error and carry on.
+             */
+        }
+    }
+
     if (qemuDomainObjExitMonitor(driver, vm) < 0)
         goto cleanup;
 
@@ -3371,7 +3411,7 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
                                                   &net->mac));
     }
 
-    if (virDomainNetGetActualType(net) == VIR_DOMAIN_NET_TYPE_DIRECT) {
+    if (actualType == VIR_DOMAIN_NET_TYPE_DIRECT) {
         ignore_value(virNetDevMacVLanDeleteWithVPortProfile(
                          net->ifname, &net->mac,
                          virDomainNetGetActualDirectDev(net),
@@ -3397,6 +3437,7 @@ qemuDomainRemoveNetDevice(virQEMUDriverPtr driver,
 
  cleanup:
     virObjectUnref(cfg);
+    VIR_FREE(charDevAlias);
     VIR_FREE(hostnet_name);
     return ret;
 }
-- 
2.8.4




More information about the libvir-list mailing list