diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 28a003e87e..c7966a47a9 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -2060,6 +2060,7 @@ typedef virDomainIOThreadIDDef *virDomainIOThreadIDDefPtr;
struct _virDomainIOThreadIDDef {
bool autofill;
unsigned int iothread_id;
+ int thread_id;
};
void virDomainIOThreadIDDefFree(virDomainIOThreadIDDefPtr def);
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index bf0621f7f5..8e63011db4 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -802,8 +802,9 @@ qemuRestoreCgroupState(virDomainObjPtr vm)
virCgroupFree(&cgroup_temp);
}
- for (i = 0; i < priv->niothreadpids; i++) {
- if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD, i + 1,
+ for (i = 0; i < vm->def->niothreadids; i++) {
+ if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
+ vm->def->iothreadids[i]->iothread_id,
false, &cgroup_temp) < 0 ||
virCgroupSetCpusetMemoryMigrate(cgroup_temp, true) < 0 ||
virCgroupGetCpusetMems(cgroup_temp, &nodeset) < 0 ||
@@ -1175,11 +1176,6 @@ qemuSetupCgroupForIOThreads(virDomainObjPtr vm)
if (priv->cgroup == NULL)
return 0;
- if (def->iothreads && priv->niothreadpids == 0) {
- VIR_WARN("Unable to get iothreads' pids.");
- return 0;
- }
-
if (virDomainNumatuneGetMode(vm->def->numa, -1) ==
VIR_DOMAIN_NUMATUNE_MEM_STRICT &&
virDomainNumatuneMaybeFormatNodeset(vm->def->numa,
@@ -1187,16 +1183,18 @@ qemuSetupCgroupForIOThreads(virDomainObjPtr vm)
&mem_mask, -1) < 0)
goto cleanup;
- for (i = 0; i < priv->niothreadpids; i++) {
+ for (i = 0; i < def->niothreadids; i++) {
/* IOThreads are numbered 1..n, although the array is 0..n-1,
* so we will account for that here
*/
- if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD, i + 1,
+ if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
+ def->iothreadids[i]->iothread_id,
true, &cgroup_iothread) < 0)
goto cleanup;
/* move the thread for iothread to sub dir */
- if (virCgroupAddTask(cgroup_iothread, priv->iothreadpids[i]) < 0)
+ if (virCgroupAddTask(cgroup_iothread,
+ def->iothreadids[i]->thread_id) < 0)
goto cleanup;
if (period || quota) {
@@ -1221,8 +1219,8 @@ qemuSetupCgroupForIOThreads(virDomainObjPtr vm)
/* specific cpu mask */
for (j = 0; j < def->cputune.niothreadspin; j++) {
- /* IOThreads are numbered/named 1..n */
- if (def->cputune.iothreadspin[j]->id == i + 1) {
+ if (def->cputune.iothreadspin[j]->id ==
+ def->iothreadids[i]->iothread_id) {
cpumask = def->cputune.iothreadspin[j]->cpumask;
break;
}
diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c
index a54f3a3230..247954fe2b 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -677,6 +677,24 @@ qemuOpenVhostNet(virDomainDefPtr def,
return -1;
}
+int
+qemuDomainParseIOThreadAlias(char *alias,
+ unsigned int *iothread_id)
+{
+ unsigned int idval;
+
+ if (virStrToLong_ui(alias + strlen("iothread"),
+ NULL, 10, &idval) < 0) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("failed to find iothread id for '%s'"),
+ alias);
+ return -1;
+ }
+
+ *iothread_id = idval;
+ return 0;
+}
+
int
qemuNetworkPrepareDevices(virDomainDefPtr def)
{
@@ -3985,11 +4003,11 @@ qemuCheckIOThreads(virDomainDefPtr def,
return false;
}
- /* Value larger than iothreads available? */
- if (disk->iothread > def->iothreads) {
+ /* Can we find the disk iothread in the iothreadid list? */
+ if (!virDomainIOThreadIDFind(def, disk->iothread)) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED,
- _("Disk iothread '%u' invalid only %u IOThreads"),
- disk->iothread, def->iothreads);
+ _("Disk iothread '%u' not defined in iothreadid"),
+ disk->iothread);
return false;
}
@@ -8794,14 +8812,15 @@ qemuBuildCommandLine(virConnectPtr conn,
if (def->iothreads > 0 &&
virQEMUCapsGet(qemuCaps, QEMU_CAPS_OBJECT_IOTHREAD)) {
- /* Create named iothread objects starting with 1. These may be used
+ /* Create iothread objects using the defined iothreadids list
+ * and the defined id and name from the list. These may be used
* by a disk definition which will associate to an iothread by
- * supplying a value of 1 up to the number of iothreads available
- * (since 0 would indicate to not use the feature).
+ * supplying a value of an id from the list
*/
- for (i = 1; i <= def->iothreads; i++) {
+ for (i = 0; i < def->niothreadids; i++) {
virCommandAddArg(cmd, "-object");
- virCommandAddArgFormat(cmd, "iothread,id=iothread%zu", i);
+ virCommandAddArgFormat(cmd, "iothread,id=iothread%u",
+ def->iothreadids[i]->iothread_id);
}
}
diff --git a/src/qemu/qemu_command.h b/src/qemu/qemu_command.h
index a29db41d1e..538ccdf550 100644
--- a/src/qemu/qemu_command.h
+++ b/src/qemu/qemu_command.h
@@ -238,6 +238,9 @@ int qemuOpenVhostNet(virDomainDefPtr def,
int *vhostfd,
size_t *vhostfdSize);
+int qemuDomainParseIOThreadAlias(char *alias,
+ unsigned int *iothread_id);
+
int qemuNetworkPrepareDevices(virDomainDefPtr def);
/*
diff --git a/src/qemu/qemu_domain.c b/src/qemu/qemu_domain.c
index 154a81ea71..2478ad7eef 100644
--- a/src/qemu/qemu_domain.c
+++ b/src/qemu/qemu_domain.c
@@ -455,7 +455,6 @@ qemuDomainObjPrivateFree(void *data)
virDomainChrSourceDefFree(priv->monConfig);
qemuDomainObjFreeJob(priv);
VIR_FREE(priv->vcpupids);
- VIR_FREE(priv->iothreadpids);
VIR_FREE(priv->lockState);
VIR_FREE(priv->origname);
@@ -516,18 +515,6 @@ qemuDomainObjPrivateXMLFormat(virBufferPtr buf, void *data)
virBufferAddLit(buf, "\n");
}
- if (priv->niothreadpids) {
- size_t i;
- virBufferAddLit(buf, "\n");
- virBufferAdjustIndent(buf, 2);
- for (i = 0; i < priv->niothreadpids; i++) {
- virBufferAsprintf(buf, "\n",
- priv->iothreadpids[i]);
- }
- virBufferAdjustIndent(buf, -2);
- virBufferAddLit(buf, "\n");
- }
-
if (priv->qemuCaps) {
size_t i;
virBufferAddLit(buf, "\n");
@@ -648,29 +635,6 @@ qemuDomainObjPrivateXMLParse(xmlXPathContextPtr ctxt, void *data)
VIR_FREE(nodes);
}
- n = virXPathNodeSet("./iothreads/iothread", ctxt, &nodes);
- if (n < 0)
- goto error;
- if (n) {
- priv->niothreadpids = n;
- if (VIR_REALLOC_N(priv->iothreadpids, priv->niothreadpids) < 0)
- goto error;
-
- for (i = 0; i < n; i++) {
- char *pidstr = virXMLPropString(nodes[i], "pid");
- if (!pidstr)
- goto error;
-
- if (virStrToLong_i(pidstr, NULL, 10,
- &(priv->iothreadpids[i])) < 0) {
- VIR_FREE(pidstr);
- goto error;
- }
- VIR_FREE(pidstr);
- }
- VIR_FREE(nodes);
- }
-
if ((n = virXPathNodeSet("./qemuCaps/flag", ctxt, &nodes)) < 0) {
virReportError(VIR_ERR_INTERNAL_ERROR,
"%s", _("failed to parse qemu capabilities flags"));
diff --git a/src/qemu/qemu_domain.h b/src/qemu/qemu_domain.h
index 1d3c77a330..bc426834f5 100644
--- a/src/qemu/qemu_domain.h
+++ b/src/qemu/qemu_domain.h
@@ -162,9 +162,6 @@ struct _qemuDomainObjPrivate {
int nvcpupids;
int *vcpupids;
- int niothreadpids;
- int *iothreadpids;
-
virDomainPCIAddressSetPtr pciaddrs;
virDomainCCWAddressSetPtr ccwaddrs;
virDomainVirtioSerialAddrSetPtr vioserialaddrs;
diff --git a/src/qemu/qemu_driver.c b/src/qemu/qemu_driver.c
index 31cbccb16e..1807058511 100644
--- a/src/qemu/qemu_driver.c
+++ b/src/qemu/qemu_driver.c
@@ -5926,14 +5926,16 @@ qemuDomainGetIOThreadsLive(virQEMUDriverPtr driver,
goto endjob;
for (i = 0; i < niothreads; i++) {
+ unsigned int iothread_id;
virBitmapPtr map = NULL;
+ if (qemuDomainParseIOThreadAlias(iothreads[i]->name,
+ &iothread_id) < 0)
+ goto endjob;
+
if (VIR_ALLOC(info_ret[i]) < 0)
goto endjob;
-
- if (virStrToLong_ui(iothreads[i]->name + strlen("iothread"), NULL, 10,
- &info_ret[i]->iothread_id) < 0)
- goto endjob;
+ info_ret[i]->iothread_id = iothread_id;
if (virProcessGetAffinity(iothreads[i]->thread_id, &map, hostcpus) < 0)
goto endjob;
@@ -5988,19 +5990,19 @@ qemuDomainGetIOThreadsConfig(virDomainDefPtr targetDef,
if (VIR_ALLOC_N(info_ret, targetDef->iothreads) < 0)
goto cleanup;
- for (i = 0; i < targetDef->iothreads; i++) {
+ for (i = 0; i < targetDef->niothreadids; i++) {
virDomainPinDefPtr pininfo;
if (VIR_ALLOC(info_ret[i]) < 0)
goto cleanup;
- /* IOThreads being counting at 1 */
- info_ret[i]->iothread_id = i + 1;
+ /* IOThread ID's are taken from the iothreadids list */
+ info_ret[i]->iothread_id = targetDef->iothreadids[i]->iothread_id;
/* Initialize the cpumap */
pininfo = virDomainPinFind(targetDef->cputune.iothreadspin,
targetDef->cputune.niothreadspin,
- i + 1);
+ targetDef->iothreadids[i]->iothread_id);
if (!pininfo) {
if (targetDef->cpumask) {
cpumask = targetDef->cpumask;
@@ -6144,16 +6146,11 @@ qemuDomainPinIOThread(virDomainPtr dom,
if (flags & VIR_DOMAIN_AFFECT_LIVE) {
- if (priv->iothreadpids == NULL) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- "%s", _("IOThread affinity is not supported"));
- goto endjob;
- }
+ virDomainIOThreadIDDefPtr iothrid;
- if (iothread_id > priv->niothreadpids) {
+ if (!(iothrid = virDomainIOThreadIDFind(vm->def, iothread_id))) {
virReportError(VIR_ERR_INVALID_ARG,
- _("iothread value out of range %d > %d"),
- iothread_id, priv->niothreadpids);
+ _("iothread value %d not found"), iothread_id);
goto endjob;
}
@@ -6191,8 +6188,7 @@ qemuDomainPinIOThread(virDomainPtr dom,
goto endjob;
}
} else {
- if (virProcessSetAffinity(priv->iothreadpids[iothread_id - 1],
- pcpumap) < 0) {
+ if (virProcessSetAffinity(iothrid->thread_id, pcpumap) < 0) {
virReportError(VIR_ERR_SYSTEM_ERROR,
_("failed to set cpu affinity for IOThread %d"),
iothread_id);
@@ -10163,8 +10159,9 @@ qemuDomainSetNumaParamsLive(virDomainObjPtr vm,
virCgroupFree(&cgroup_temp);
}
- for (i = 0; i < priv->niothreadpids; i++) {
- if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD, i + 1,
+ for (i = 0; i < vm->def->niothreadids; i++) {
+ if (virCgroupNewThread(priv->cgroup, VIR_CGROUP_THREAD_IOTHREAD,
+ vm->def->iothreadids[i]->iothread_id,
false, &cgroup_temp) < 0 ||
virCgroupSetCpusetMems(cgroup_temp, nodeset_str) < 0)
goto cleanup;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index bf1ba69f63..6c1fea94c0 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -2247,12 +2247,21 @@ qemuProcessDetectIOThreadPIDs(virQEMUDriverPtr driver,
goto cleanup;
}
- if (VIR_ALLOC_N(priv->iothreadpids, niothreads) < 0)
- goto cleanup;
- priv->niothreadpids = niothreads;
+ for (i = 0; i < niothreads; i++) {
+ unsigned int iothread_id;
+ virDomainIOThreadIDDefPtr iothrid;
- for (i = 0; i < priv->niothreadpids; i++)
- priv->iothreadpids[i] = iothreads[i]->thread_id;
+ if (qemuDomainParseIOThreadAlias(iothreads[i]->name,
+ &iothread_id) < 0)
+ goto cleanup;
+
+ if (!(iothrid = virDomainIOThreadIDFind(vm->def, iothread_id))) {
+ virReportError(VIR_ERR_INTERNAL_ERROR,
+ _("iothread %d not found"), iothread_id);
+ goto cleanup;
+ }
+ iothrid->thread_id = iothreads[i]->thread_id;
+ }
ret = 0;
@@ -2433,7 +2442,6 @@ qemuProcessSetEmulatorAffinity(virDomainObjPtr vm)
static int
qemuProcessSetIOThreadsAffinity(virDomainObjPtr vm)
{
- qemuDomainObjPrivatePtr priv = vm->privateData;
virDomainDefPtr def = vm->def;
virDomainPinDefPtr pininfo;
size_t i;
@@ -2442,20 +2450,15 @@ qemuProcessSetIOThreadsAffinity(virDomainObjPtr vm)
if (!def->cputune.niothreadspin)
return 0;
- if (priv->iothreadpids == NULL) {
- virReportError(VIR_ERR_OPERATION_INVALID,
- "%s", _("IOThread affinity is not supported"));
- return -1;
- }
-
- for (i = 0; i < def->iothreads; i++) {
- /* set affinity only for existing vcpus */
+ for (i = 0; i < def->niothreadids; i++) {
+ /* set affinity only for existing iothreads */
if (!(pininfo = virDomainPinFind(def->cputune.iothreadspin,
def->cputune.niothreadspin,
- i + 1)))
+ def->iothreadids[i]->iothread_id)))
continue;
- if (virProcessSetAffinity(priv->iothreadpids[i], pininfo->cpumask) < 0)
+ if (virProcessSetAffinity(def->iothreadids[i]->thread_id,
+ pininfo->cpumask) < 0)
goto cleanup;
}
ret = 0;
@@ -2505,8 +2508,9 @@ qemuProcessSetSchedulers(virDomainObjPtr vm)
return -1;
}
- for (i = 0; i < priv->niothreadpids; i++) {
- if (qemuProcessSetSchedParams(i + 1, priv->iothreadpids[i],
+ for (i = 0; i < vm->def->niothreadids; i++) {
+ if (qemuProcessSetSchedParams(vm->def->iothreadids[i]->iothread_id,
+ vm->def->iothreadids[i]->thread_id,
vm->def->cputune.niothreadsched,
vm->def->cputune.iothreadsched) < 0)
return -1;
@@ -5294,8 +5298,8 @@ void qemuProcessStop(virQEMUDriverPtr driver,
virDomainObjSetState(vm, VIR_DOMAIN_SHUTOFF, reason);
VIR_FREE(priv->vcpupids);
priv->nvcpupids = 0;
- VIR_FREE(priv->iothreadpids);
- priv->niothreadpids = 0;
+ for (i = 0; i < vm->def->niothreadids; i++)
+ vm->def->iothreadids[i]->thread_id = 0;
virObjectUnref(priv->qemuCaps);
priv->qemuCaps = NULL;
VIR_FREE(priv->pidfile);
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-iothreads-ids-partial.args b/tests/qemuxml2argvdata/qemuxml2argv-iothreads-ids-partial.args
new file mode 100644
index 0000000000..444cd17f43
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-iothreads-ids-partial.args
@@ -0,0 +1,10 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
+/usr/bin/qemu -S -M \
+pc -m 214 -smp 2 \
+-object iothread,id=iothread5 \
+-object iothread,id=iothread6 \
+-object iothread,id=iothread1 \
+-object iothread,id=iothread2 \
+-nographic -monitor \
+unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb -hda \
+/dev/HostVG/QEMUGuest1 -net none -serial none -parallel none
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-iothreads-ids-partial.xml b/tests/qemuxml2argvdata/qemuxml2argv-iothreads-ids-partial.xml
new file mode 100644
index 0000000000..c63167709f
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-iothreads-ids-partial.xml
@@ -0,0 +1,33 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219136
+ 219136
+ 2
+ 4
+
+
+
+
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-iothreads-ids.args b/tests/qemuxml2argvdata/qemuxml2argv-iothreads-ids.args
new file mode 100644
index 0000000000..68998f67e5
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-iothreads-ids.args
@@ -0,0 +1,8 @@
+LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test QEMU_AUDIO_DRV=none \
+/usr/bin/qemu -S -M \
+pc -m 214 -smp 2 \
+-object iothread,id=iothread2 \
+-object iothread,id=iothread4 \
+-nographic -monitor \
+unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -usb -hda \
+/dev/HostVG/QEMUGuest1 -net none -serial none -parallel none
diff --git a/tests/qemuxml2argvdata/qemuxml2argv-iothreads-ids.xml b/tests/qemuxml2argvdata/qemuxml2argv-iothreads-ids.xml
new file mode 100644
index 0000000000..d70e74b0bc
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-iothreads-ids.xml
@@ -0,0 +1,33 @@
+
+ QEMUGuest1
+ c7a5fdbd-edaf-9455-926a-d65c16db1809
+ 219136
+ 219136
+ 2
+ 2
+
+
+
+
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c
index 055ceee48b..0763068c6b 100644
--- a/tests/qemuxml2argvtest.c
+++ b/tests/qemuxml2argvtest.c
@@ -1217,6 +1217,8 @@ mymain(void)
DO_TEST("smp", QEMU_CAPS_SMP_TOPOLOGY);
DO_TEST("iothreads", QEMU_CAPS_OBJECT_IOTHREAD);
+ DO_TEST("iothreads-ids", QEMU_CAPS_OBJECT_IOTHREAD);
+ DO_TEST("iothreads-ids-partial", QEMU_CAPS_OBJECT_IOTHREAD);
DO_TEST("iothreads-disk", QEMU_CAPS_OBJECT_IOTHREAD, QEMU_CAPS_DEVICE,
QEMU_CAPS_DRIVE);
DO_TEST("iothreads-disk-virtio-ccw", QEMU_CAPS_OBJECT_IOTHREAD, QEMU_CAPS_DEVICE,
diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c
index 45464cc6a1..b611afdd9c 100644
--- a/tests/qemuxml2xmltest.c
+++ b/tests/qemuxml2xmltest.c
@@ -493,6 +493,8 @@ mymain(void)
DO_TEST("smp");
DO_TEST("iothreads");
+ DO_TEST("iothreads-ids");
+ DO_TEST("iothreads-ids-partial");
DO_TEST_DIFFERENT("cputune-iothreads");
DO_TEST("iothreads-disk");
DO_TEST("iothreads-disk-virtio-ccw");