]> xenbits.xensource.com Git - libvirt.git/commitdiff
Allocate virtio-serial addresses when starting a domain
authorJán Tomko <jtomko@redhat.com>
Mon, 2 Mar 2015 09:58:48 +0000 (10:58 +0100)
committerJán Tomko <jtomko@redhat.com>
Thu, 2 Apr 2015 13:00:13 +0000 (15:00 +0200)
Instead of always using controller 0 and incrementing port number,
respect the maximum port numbers of controllers and use all of them.

Ports for virtio consoles are quietly reserved, but not formatted
(neither in XML nor on QEMU command line).

Also rejects duplicate virtio-serial addresses.
https://bugzilla.redhat.com/show_bug.cgi?id=890606
https://bugzilla.redhat.com/show_bug.cgi?id=1076708

Test changes:
* virtio-auto.args
  Filling out the port when just the controller is specified.
  switched from using
    maxport + 1
  to:
    first free port on the controller
* virtio-autoassign.args
  Filling out the address when no <address> is specified.
  Started using all the controllers instead of 0, also discards
  the bus value.
* xml -> xml output of virtio-auto
  The port assignment is no longer done as a part of XML parsing,
  so the unspecified values stay 0.

src/conf/domain_conf.c
src/conf/domain_conf.h
src/libvirt_private.syms
src/qemu/qemu_command.c
src/qemu/qemu_domain.c
src/qemu/qemu_domain.h
src/qemu/qemu_process.c
tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args
tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-autoassign.args
tests/qemuxml2xmloutdata/qemuxml2xmlout-channel-virtio-auto.xml

index 4e5c538a3f258222f8931c8985e28d68da683e56..1763305e648a0910bf42fd19114a8c2c62b59055 100644 (file)
@@ -3512,21 +3512,6 @@ virDomainDeviceDefPostParseInternal(virDomainDeviceDefPtr dev,
 
             chr->target.port = maxport + 1;
         }
-
-        if (chr->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL &&
-            chr->info.addr.vioserial.port == 0) {
-            int maxport = 0;
-
-            for (i = 0; i < cnt; i++) {
-                const virDomainChrDef *thischr = arrPtr[i];
-                if (thischr->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL &&
-                    thischr->info.addr.vioserial.controller == chr->info.addr.vioserial.controller &&
-                    thischr->info.addr.vioserial.bus == chr->info.addr.vioserial.bus &&
-                    (int)thischr->info.addr.vioserial.port > maxport)
-                    maxport = thischr->info.addr.vioserial.port;
-            }
-            chr->info.addr.vioserial.port = maxport + 1;
-        }
     }
 
     /* set default path for virtio-rng "random" backend to /dev/random */
@@ -12499,6 +12484,20 @@ virDomainControllerFind(virDomainDefPtr def,
     return -1;
 }
 
+int
+virDomainControllerFindByType(virDomainDefPtr def,
+                              int type)
+{
+    size_t i;
+
+    for (i = 0; i < def->ncontrollers; i++) {
+        if (def->controllers[i]->type == type)
+            return i;
+    }
+
+    return -1;
+}
+
 int
 virDomainControllerFindByPCIAddress(virDomainDefPtr def,
                                     virDevicePCIAddressPtr addr)
@@ -14935,25 +14934,6 @@ virDomainDefParseXML(xmlDocPtr xml,
             goto error;
 
         def->channels[def->nchannels++] = chr;
-
-        if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
-            chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
-            chr->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
-            chr->info.type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL;
-
-        if (chr->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL &&
-            chr->info.addr.vioserial.port == 0) {
-            int maxport = 0;
-            for (j = 0; j < i; j++) {
-                virDomainChrDefPtr thischr = def->channels[j];
-                if (thischr->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL &&
-                    thischr->info.addr.vioserial.controller == chr->info.addr.vioserial.controller &&
-                    thischr->info.addr.vioserial.bus == chr->info.addr.vioserial.bus &&
-                    (int)thischr->info.addr.vioserial.port > maxport)
-                    maxport = thischr->info.addr.vioserial.port;
-            }
-            chr->info.addr.vioserial.port = maxport + 1;
-        }
     }
     VIR_FREE(nodes);
 
index 33200846a2f605bf414c7f9780179083db1d05c1..0b2f1c9bf055da727958c0b3a2c058cad1566177 100644 (file)
@@ -2717,6 +2717,7 @@ int virDomainControllerInsert(virDomainDefPtr def,
 void virDomainControllerInsertPreAlloced(virDomainDefPtr def,
                                          virDomainControllerDefPtr controller);
 int virDomainControllerFind(virDomainDefPtr def, int type, int idx);
+int virDomainControllerFindByType(virDomainDefPtr def, int type);
 int virDomainControllerFindByPCIAddress(virDomainDefPtr def,
                                         virDevicePCIAddressPtr addr);
 virDomainControllerDefPtr virDomainControllerRemove(virDomainDefPtr def, size_t i);
index 5201416c4e059721bcd754fffb21c1f9b42e4041..36797c55b5e221dfc6f9897d12431f6452f13f89 100644 (file)
@@ -184,6 +184,7 @@ virDomainClockOffsetTypeToString;
 virDomainConfigFile;
 virDomainControllerDefFree;
 virDomainControllerFind;
+virDomainControllerFindByType;
 virDomainControllerInsert;
 virDomainControllerInsertPreAlloced;
 virDomainControllerModelPCITypeToString;
index bcb54fae4bb2c2d3016d2b1a51809b88f1e0271f..85d2f4d040bf94f31dd9932f69b177c116c6d823 100644 (file)
@@ -1403,6 +1403,65 @@ qemuAssignSpaprVIOAddress(virDomainDefPtr def, virDomainDeviceInfoPtr info,
     return 0;
 }
 
+
+static int
+qemuDomainAssignVirtioSerialAddresses(virDomainDefPtr def,
+                                      virDomainObjPtr obj)
+{
+    int ret = -1;
+    size_t i;
+    virDomainVirtioSerialAddrSetPtr addrs = NULL;
+    qemuDomainObjPrivatePtr priv = NULL;
+
+    if (virDomainControllerFindByType(def, VIR_DOMAIN_CONTROLLER_TYPE_VIRTIO_SERIAL) == -1)
+        return 0;
+
+    if (!(addrs = virDomainVirtioSerialAddrSetCreate()))
+        goto cleanup;
+
+    if (virDomainVirtioSerialAddrSetAddControllers(addrs, def) < 0)
+        goto cleanup;
+
+    if (virDomainDeviceInfoIterate(def, virDomainVirtioSerialAddrReserve,
+                                   addrs) < 0)
+        goto cleanup;
+
+    VIR_DEBUG("Finished reserving existing ports");
+
+    for (i = 0; i < def->nconsoles; i++) {
+        virDomainChrDefPtr chr = def->consoles[i];
+        if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CONSOLE &&
+            chr->targetType == VIR_DOMAIN_CHR_CONSOLE_TARGET_TYPE_VIRTIO &&
+            !virDomainVirtioSerialAddrIsComplete(&chr->info) &&
+            virDomainVirtioSerialAddrAutoAssign(addrs, &chr->info, true) < 0)
+            goto cleanup;
+    }
+
+    for (i = 0; i < def->nchannels; i++) {
+        virDomainChrDefPtr chr = def->channels[i];
+        if (chr->deviceType == VIR_DOMAIN_CHR_DEVICE_TYPE_CHANNEL &&
+            chr->targetType == VIR_DOMAIN_CHR_CHANNEL_TARGET_TYPE_VIRTIO &&
+            !virDomainVirtioSerialAddrIsComplete(&chr->info) &&
+            virDomainVirtioSerialAddrAutoAssign(addrs, &chr->info, false) < 0)
+            goto cleanup;
+    }
+
+    if (obj && obj->privateData) {
+        priv = obj->privateData;
+        /* if this is the live domain object, we persist the addresses */
+        virDomainVirtioSerialAddrSetFree(priv->vioserialaddrs);
+        priv->persistentAddrs = 1;
+        priv->vioserialaddrs = addrs;
+        addrs = NULL;
+    }
+    ret = 0;
+
+ cleanup:
+    virDomainVirtioSerialAddrSetFree(addrs);
+    return ret;
+}
+
+
 int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def,
                                       virQEMUCapsPtr qemuCaps)
 {
@@ -1649,6 +1708,10 @@ int qemuDomainAssignAddresses(virDomainDefPtr def,
 {
     int rc;
 
+    rc = qemuDomainAssignVirtioSerialAddresses(def, obj);
+    if (rc)
+        return rc;
+
     rc = qemuDomainAssignSpaprVIOAddresses(def, qemuCaps);
     if (rc)
         return rc;
index d1be66e54818d5e77f578da112b00acdbc9c6500..786e0b8da165581ea246325b694bd683b6552ae6 100644 (file)
@@ -436,6 +436,7 @@ qemuDomainObjPrivateFree(void *data)
     virCgroupFree(&priv->cgroup);
     virDomainPCIAddressSetFree(priv->pciaddrs);
     virDomainCCWAddressSetFree(priv->ccwaddrs);
+    virDomainVirtioSerialAddrSetFree(priv->vioserialaddrs);
     virDomainChrSourceDefFree(priv->monConfig);
     qemuDomainObjFreeJob(priv);
     VIR_FREE(priv->vcpupids);
index e4140d8c58a137e8f2ca497dac2bf91855223e55..0ea6d2f49a58ebeeae527d732ead3fc2372ec579 100644 (file)
@@ -163,6 +163,7 @@ struct _qemuDomainObjPrivate {
 
     virDomainPCIAddressSetPtr pciaddrs;
     virDomainCCWAddressSetPtr ccwaddrs;
+    virDomainVirtioSerialAddrSetPtr vioserialaddrs;
     int persistentAddrs;
 
     virQEMUCapsPtr qemuCaps;
index 93768993490c08fbe485d038b6992cb67e9c3f35..ed8f65a5870d436c42e292e6e870b203dbcd7b70 100644 (file)
@@ -5188,6 +5188,8 @@ void qemuProcessStop(virQEMUDriverPtr driver,
         virDomainDefClearCCWAddresses(vm->def);
         virDomainCCWAddressSetFree(priv->ccwaddrs);
         priv->ccwaddrs = NULL;
+        virDomainVirtioSerialAddrSetFree(priv->vioserialaddrs);
+        priv->vioserialaddrs = NULL;
     }
 
     qemuDomainReAttachHostDevices(driver, vm->def);
index f7d7409708513bb611bd36a6d9b8b07f854012ca..1806b20d382557997374f9957a8edbfa45ee5a97 100644 (file)
@@ -15,7 +15,7 @@ virtserialport,bus=virtio-serial1.0,nr=3,chardev=charchannel2,id=channel2,\
 name=org.linux-kvm.port.bar -chardev pty,id=charchannel3 -device \
 virtserialport,bus=virtio-serial0.0,nr=2,chardev=charchannel3,id=channel3,\
 name=org.linux-kvm.port.wizz -chardev pty,id=charchannel4 -device \
-virtserialport,bus=virtio-serial1.0,nr=4,chardev=charchannel4,id=channel4,\
+virtserialport,bus=virtio-serial1.0,nr=2,chardev=charchannel4,id=channel4,\
 name=org.linux-kvm.port.ooh -chardev pty,id=charchannel5 -device \
 virtserialport,bus=virtio-serial2.0,nr=1,chardev=charchannel5,id=channel5,\
 name=org.linux-kvm.port.lla -device virtio-balloon-pci,id=balloon0,\
index f7f7b8da579577ea925da6223d762585a506fa98..f11039dcd44691e1369c62e05eceb86d785e6f7c 100644 (file)
@@ -5,16 +5,16 @@ LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
 -device virtio-serial-pci,id=virtio-serial0,max_ports=4,vectors=4,bus=pci.0\
 ,addr=0x3 -device virtio-serial-pci,id=virtio-serial1,bus=pci.0,addr=0xa \
 -usb -hda /dev/HostVG/QEMUGuest1 \
--chardev pty,id=charchannel0 -device virtserialport,bus=virtio-serial0.0,nr=1,\
+-chardev pty,id=charchannel0 -device virtserialport,bus=virtio-serial0.0,nr=2,\
 chardev=charchannel0,id=channel0,name=org.linux-kvm.port.0 \
--chardev pty,id=charchannel1 -device virtserialport,bus=virtio-serial0.2,nr=1,\
+-chardev pty,id=charchannel1 -device virtserialport,bus=virtio-serial0.0,nr=3,\
 chardev=charchannel1,id=channel1,name=org.linux-kvm.port.foo \
 -chardev pty,id=charchannel2 -device virtserialport,bus=virtio-serial0.0,nr=1,\
 chardev=charchannel2,id=channel2,name=org.linux-kvm.port.bar \
--chardev pty,id=charchannel3 -device virtserialport,bus=virtio-serial0.0,nr=2,\
+-chardev pty,id=charchannel3 -device virtserialport,bus=virtio-serial1.0,nr=1,\
 chardev=charchannel3,id=channel3,name=org.linux-kvm.port.wizz \
--chardev pty,id=charchannel4 -device virtserialport,bus=virtio-serial0.0,nr=3,\
+-chardev pty,id=charchannel4 -device virtserialport,bus=virtio-serial1.0,nr=2,\
 chardev=charchannel4,id=channel4,name=org.linux-kvm.port.ooh \
--chardev pty,id=charchannel5 -device virtserialport,bus=virtio-serial0.0,nr=4,\
+-chardev pty,id=charchannel5 -device virtserialport,bus=virtio-serial1.0,nr=3,\
 chardev=charchannel5,id=channel5,name=org.linux-kvm.port.lla \
 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4
index fd6b8524e84773158a880f4262ba922f28259986..7a608a86b209097711903786a6f386ae46eec0dd 100644 (file)
     <controller type='virtio-serial' index='2'/>
     <channel type='pty'>
       <target type='virtio' name='org.linux-kvm.port.0'/>
-      <address type='virtio-serial' controller='0' bus='0' port='1'/>
     </channel>
     <channel type='pty'>
       <target type='virtio' name='org.linux-kvm.port.foo'/>
-      <address type='virtio-serial' controller='1' bus='0' port='1'/>
+      <address type='virtio-serial' controller='1' bus='0' port='0'/>
     </channel>
     <channel type='pty'>
       <target type='virtio' name='org.linux-kvm.port.bar'/>
     </channel>
     <channel type='pty'>
       <target type='virtio' name='org.linux-kvm.port.wizz'/>
-      <address type='virtio-serial' controller='0' bus='0' port='2'/>
+      <address type='virtio-serial' controller='0' bus='0' port='0'/>
     </channel>
     <channel type='pty'>
       <target type='virtio' name='org.linux-kvm.port.ooh'/>
-      <address type='virtio-serial' controller='1' bus='0' port='4'/>
+      <address type='virtio-serial' controller='1' bus='0' port='0'/>
     </channel>
     <channel type='pty'>
       <target type='virtio' name='org.linux-kvm.port.lla'/>
-      <address type='virtio-serial' controller='2' bus='0' port='1'/>
+      <address type='virtio-serial' controller='2' bus='0' port='0'/>
     </channel>
     <memballoon model='virtio'/>
   </devices>