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
---
src/conf/domain_conf.c | 29 ----------
src/qemu/qemu_command.c | 63 ++++++++++++++++++++++
src/qemu/qemu_domain.c | 1 +
src/qemu/qemu_domain.h | 1 +
src/qemu/qemu_process.c | 2 +
.../qemuxml2argv-channel-virtio-auto.args | 8 +--
.../qemuxml2argv-channel-virtio-autoassign.args | 10 ++--
.../qemuxml2xmlout-channel-virtio-auto.xml | 10 ++--
8 files changed, 81 insertions(+), 43 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 6da02b0..6b308cf 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -3349,21 +3349,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 */
@@ -14353,20 +14338,6 @@ virDomainDefParseXML(xmlDocPtr xml,
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);
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index c112619..654fba1 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -1347,6 +1347,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 (!(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) {
+ if (virDomainVirtioSerialAddrAssign(addrs, &chr->info, true) < 0)
+ goto cleanup;
+ }
+ }
+
+ for (i = 0; i < def->nchannels; i++) {
+ virDomainChrDefPtr chr = def->channels[i];
+ if (chr->info.type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_VIRTIO_SERIAL &&
+ chr->info.addr.vioserial.port == 0 &&
+ virDomainVirtioSerialAddrAssign(addrs, &chr->info, false) < 0)
+ goto cleanup;
+ }
+
+ if (obj && obj->privateData) {
+ priv = obj->privateData;
+ if (addrs) {
+ /* if this is the live domain object, we persist the CCW addresses*/
+ virDomainVirtioSerialAddrSetFree(priv->vioserialaddrs);
+ priv->persistentAddrs = 1;
+ priv->vioserialaddrs = addrs;
+ addrs = NULL;
+ } else {
+ priv->persistentAddrs = 0;
+ }
+ }
+ ret = 0;
+
+ cleanup:
+ virDomainVirtioSerialAddrSetFree(addrs);
+ return ret;
+}
+
+
int qemuDomainAssignSpaprVIOAddresses(virDomainDefPtr def,
virQEMUCapsPtr qemuCaps)
{
@@ -1593,6 +1652,10 @@ int qemuDomainAssignAddresses(virDomainDefPtr def,
{
int rc;
+ rc = qemuDomainAssignVirtioSerialAddresses(def, obj);
+ if (rc)
+ return rc;
+
rc = qemuDomainAssignSpaprVIOAddresses(def, qemuCaps);
if (rc)
return rc;
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index d8a2087..27af7f9 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -431,6 +431,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);
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index fe3e2b1..521c5ec 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -159,6 +159,7 @@ struct _qemuDomainObjPrivate {
virDomainPCIAddressSetPtr pciaddrs;
virDomainCCWAddressSetPtr ccwaddrs;
+ virDomainVirtioSerialAddrSetPtr vioserialaddrs;
int persistentAddrs;
virQEMUCapsPtr qemuCaps;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index d1f089d..97523b3 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5286,6 +5286,8 @@ void qemuProcessStop(virQEMUDriverPtr driver,
virDomainDefClearCCWAddresses(vm->def);
virDomainCCWAddressSetFree(priv->ccwaddrs);
priv->ccwaddrs = NULL;
+ virDomainVirtioSerialAddrSetFree(priv->vioserialaddrs);
+ priv->vioserialaddrs = NULL;
}
qemuDomainReAttachHostDevices(driver, vm->def);
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args
b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args
index f7d7409..71edfae 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args
@@ -9,14 +9,14 @@ virtio-serial-pci,id=virtio-serial2,bus=pci.0,addr=0x4 -usb -hda \
/dev/HostVG/QEMUGuest1 -chardev pty,id=charchannel0 -device virtserialport,\
bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,\
name=org.linux-kvm.port.0 -chardev pty,id=charchannel1 -device virtserialport,\
-bus=virtio-serial1.0,nr=1,chardev=charchannel1,id=channel1,\
+bus=virtio-serial0.0,nr=2,chardev=charchannel1,id=channel1,\
name=org.linux-kvm.port.foo -chardev pty,id=charchannel2 -device \
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,\
+virtserialport,bus=virtio-serial0.0,nr=3,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-serial0.0,nr=4,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,\
+virtserialport,bus=virtio-serial0.0,nr=5,chardev=charchannel5,id=channel5,\
name=org.linux-kvm.port.lla -device virtio-balloon-pci,id=balloon0,\
bus=pci.0,addr=0x5
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-autoassign.args
b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-autoassign.args
index d64a228..f11039d 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-autoassign.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-autoassign.args
@@ -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.0,nr=2,\
+-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.2,nr=1,\
+-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
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-channel-virtio-auto.xml
b/tests/qemuxml2xmloutdata/qemuxml2xmlout-channel-virtio-auto.xml
index fd6b852..afe41cf 100644
--- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-channel-virtio-auto.xml
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-channel-virtio-auto.xml
@@ -29,11 +29,11 @@
<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'/>
+ <address type='virtio-serial' controller='0' bus='0'
port='0'/>
</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'/>
@@ -41,15 +41,15 @@
</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>
--
2.0.5