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");