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 | 48 +++++------------
src/conf/domain_conf.h | 1 +
src/libvirt_private.syms | 1 +
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 | 2 +-
.../qemuxml2argv-channel-virtio-autoassign.args | 10 ++--
.../qemuxml2xmlout-channel-virtio-auto.xml | 9 ++--
10 files changed, 93 insertions(+), 45 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index d633f93..e777f5f 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -3498,21 +3498,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 */
@@ -12471,6 +12456,20 @@ virDomainControllerFind(virDomainDefPtr def,
}
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)
{
@@ -14906,25 +14905,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);
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index bceb2d7..b756b40 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2701,6 +2701,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);
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index fe8aee3..e6e5da2 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -184,6 +184,7 @@ virDomainClockOffsetTypeToString;
virDomainConfigFile;
virDomainControllerDefFree;
virDomainControllerFind;
+virDomainControllerFindByType;
virDomainControllerInsert;
virDomainControllerInsertPreAlloced;
virDomainControllerModelPCITypeToString;
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index 7e6b95c..2af5dbf 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -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;
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 655afb9..7879afc 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 28eefac..08279e0 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 59eae1c..45f1bcd 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -5217,6 +5217,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..1806b20 100644
--- a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args
+++ b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-auto.args
@@ -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,\
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-autoassign.args
b/tests/qemuxml2argvdata/qemuxml2argv-channel-virtio-autoassign.args
index f7f7b8d..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.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
diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-channel-virtio-auto.xml
b/tests/qemuxml2xmloutdata/qemuxml2xmlout-channel-virtio-auto.xml
index fd6b852..7a608a8 100644
--- a/tests/qemuxml2xmloutdata/qemuxml2xmlout-channel-virtio-auto.xml
+++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-channel-virtio-auto.xml
@@ -29,11 +29,10 @@
<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'/>
@@ -41,15 +40,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