mirror of
https://github.com/libvirt/libvirt.git
synced 2025-02-25 18:55:26 -06:00
qemu: Implement the qemu driver fetch for IOThreads
Depending on the flags passed, either attempt to return the active/live IOThread data for the domain or the config data. The active/live path will call into the Monitor in order to get the IOThread data and then correlate the thread_id's returned from the monitor to the currently running system/threads in order to ascertain the affinity for each iothread_id. The config path will map each of the configured IOThreads and return any configured iothreadspin data Signed-off-by: John Ferlan <jferlan@redhat.com>
This commit is contained in:
parent
1e5a8ddc81
commit
82649eb7f1
@ -5557,6 +5557,229 @@ qemuDomainGetMaxVcpus(virDomainPtr dom)
|
|||||||
VIR_DOMAIN_VCPU_MAXIMUM));
|
VIR_DOMAIN_VCPU_MAXIMUM));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuDomainGetIOThreadsLive(virQEMUDriverPtr driver,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
virDomainIOThreadInfoPtr **info)
|
||||||
|
{
|
||||||
|
qemuDomainObjPrivatePtr priv;
|
||||||
|
qemuMonitorIOThreadsInfoPtr *iothreads = NULL;
|
||||||
|
virDomainIOThreadInfoPtr *info_ret = NULL;
|
||||||
|
int niothreads = 0;
|
||||||
|
int maxcpu, hostcpus, maplen;
|
||||||
|
size_t i;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (qemuDomainObjBeginJob(driver, vm, QEMU_JOB_QUERY) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!virDomainObjIsActive(vm)) {
|
||||||
|
virReportError(VIR_ERR_OPERATION_INVALID, "%s",
|
||||||
|
_("cannot list IOThreads for an inactive domain"));
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
|
||||||
|
priv = vm->privateData;
|
||||||
|
if (!virQEMUCapsGet(priv->qemuCaps, QEMU_CAPS_OBJECT_IOTHREAD)) {
|
||||||
|
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
|
||||||
|
_("IOThreads not supported with this binary"));
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
|
||||||
|
qemuDomainObjEnterMonitor(driver, vm);
|
||||||
|
niothreads = qemuMonitorGetIOThreads(priv->mon, &iothreads);
|
||||||
|
if (qemuDomainObjExitMonitor(driver, vm) < 0)
|
||||||
|
goto endjob;
|
||||||
|
if (niothreads < 0)
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
|
/* Nothing to do */
|
||||||
|
if (niothreads == 0) {
|
||||||
|
ret = 0;
|
||||||
|
goto endjob;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((hostcpus = nodeGetCPUCount()) < 0)
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
|
maplen = VIR_CPU_MAPLEN(hostcpus);
|
||||||
|
maxcpu = maplen * 8;
|
||||||
|
if (maxcpu > hostcpus)
|
||||||
|
maxcpu = hostcpus;
|
||||||
|
|
||||||
|
if (VIR_ALLOC_N(info_ret, niothreads) < 0)
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
|
for (i = 0; i < niothreads; i++) {
|
||||||
|
virBitmapPtr map = NULL;
|
||||||
|
unsigned char *tmpmap = NULL;
|
||||||
|
int tmpmaplen = 0;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
if (VIR_ALLOC_N(info_ret[i]->cpumap, maplen) < 0)
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
|
if (virProcessGetAffinity(iothreads[i]->thread_id, &map, maxcpu) < 0)
|
||||||
|
goto endjob;
|
||||||
|
|
||||||
|
virBitmapToData(map, &tmpmap, &tmpmaplen);
|
||||||
|
if (tmpmaplen > maplen)
|
||||||
|
tmpmaplen = maplen;
|
||||||
|
memcpy(info_ret[i]->cpumap, tmpmap, tmpmaplen);
|
||||||
|
info_ret[i]->cpumaplen = tmpmaplen;
|
||||||
|
|
||||||
|
VIR_FREE(tmpmap);
|
||||||
|
virBitmapFree(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
*info = info_ret;
|
||||||
|
info_ret = NULL;
|
||||||
|
ret = niothreads;
|
||||||
|
|
||||||
|
endjob:
|
||||||
|
qemuDomainObjEndJob(driver, vm);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (info_ret) {
|
||||||
|
for (i = 0; i < niothreads; i++)
|
||||||
|
virDomainIOThreadsInfoFree(info_ret[i]);
|
||||||
|
VIR_FREE(info_ret);
|
||||||
|
}
|
||||||
|
if (iothreads) {
|
||||||
|
for (i = 0; i < niothreads; i++)
|
||||||
|
qemuMonitorIOThreadsInfoFree(iothreads[i]);
|
||||||
|
VIR_FREE(iothreads);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuDomainGetIOThreadsConfig(virDomainDefPtr targetDef,
|
||||||
|
virDomainIOThreadInfoPtr **info)
|
||||||
|
{
|
||||||
|
virDomainIOThreadInfoPtr *info_ret = NULL;
|
||||||
|
virDomainVcpuPinDefPtr *iothreadspin_list;
|
||||||
|
virBitmapPtr cpumask = NULL;
|
||||||
|
unsigned char *cpumap;
|
||||||
|
int maxcpu, hostcpus, maplen;
|
||||||
|
size_t i, pcpu;
|
||||||
|
bool pinned;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (targetDef->iothreads == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if ((hostcpus = nodeGetCPUCount()) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
maplen = VIR_CPU_MAPLEN(hostcpus);
|
||||||
|
maxcpu = maplen * 8;
|
||||||
|
if (maxcpu > hostcpus)
|
||||||
|
maxcpu = hostcpus;
|
||||||
|
|
||||||
|
if (VIR_ALLOC_N(info_ret, targetDef->iothreads) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
for (i = 0; i < targetDef->iothreads; i++) {
|
||||||
|
if (VIR_ALLOC(info_ret[i]) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* IOThreads being counting at 1 */
|
||||||
|
info_ret[i]->iothread_id = i + 1;
|
||||||
|
|
||||||
|
if (VIR_ALLOC_N(info_ret[i]->cpumap, maplen) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
/* Initialize the cpumap */
|
||||||
|
info_ret[i]->cpumaplen = maplen;
|
||||||
|
memset(info_ret[i]->cpumap, 0xff, maplen);
|
||||||
|
if (maxcpu % 8)
|
||||||
|
info_ret[i]->cpumap[maplen - 1] &= (1 << maxcpu % 8) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If iothreadspin setting exists, there are unused physical cpus */
|
||||||
|
iothreadspin_list = targetDef->cputune.iothreadspin;
|
||||||
|
for (i = 0; i < targetDef->cputune.niothreadspin; i++) {
|
||||||
|
/* vcpuid is the iothread_id...
|
||||||
|
* iothread_id is the index into info_ret + 1, so we can
|
||||||
|
* assume that the info_ret index we want is vcpuid - 1
|
||||||
|
*/
|
||||||
|
cpumap = info_ret[iothreadspin_list[i]->vcpuid - 1]->cpumap;
|
||||||
|
cpumask = iothreadspin_list[i]->cpumask;
|
||||||
|
|
||||||
|
for (pcpu = 0; pcpu < maxcpu; pcpu++) {
|
||||||
|
if (virBitmapGetBit(cpumask, pcpu, &pinned) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
if (!pinned)
|
||||||
|
VIR_UNUSE_CPU(cpumap, pcpu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*info = info_ret;
|
||||||
|
info_ret = NULL;
|
||||||
|
ret = targetDef->iothreads;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
if (info_ret) {
|
||||||
|
for (i = 0; i < targetDef->iothreads; i++)
|
||||||
|
virDomainIOThreadsInfoFree(info_ret[i]);
|
||||||
|
VIR_FREE(info_ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuDomainGetIOThreadsInfo(virDomainPtr dom,
|
||||||
|
virDomainIOThreadInfoPtr **info,
|
||||||
|
unsigned int flags)
|
||||||
|
{
|
||||||
|
virQEMUDriverPtr driver = dom->conn->privateData;
|
||||||
|
virDomainObjPtr vm;
|
||||||
|
virCapsPtr caps = NULL;
|
||||||
|
virDomainDefPtr targetDef = NULL;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
virCheckFlags(VIR_DOMAIN_AFFECT_LIVE |
|
||||||
|
VIR_DOMAIN_AFFECT_CONFIG, -1);
|
||||||
|
|
||||||
|
if (!(vm = qemuDomObjFromDomain(dom)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virDomainGetIOThreadsInfoEnsureACL(dom->conn, vm->def) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (virDomainLiveConfigHelperMethod(caps, driver->xmlopt, vm, &flags,
|
||||||
|
&targetDef) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
if (flags & VIR_DOMAIN_AFFECT_LIVE)
|
||||||
|
targetDef = vm->def;
|
||||||
|
|
||||||
|
/* Coverity didn't realize that targetDef must be set if we got here. */
|
||||||
|
sa_assert(targetDef);
|
||||||
|
|
||||||
|
if (flags & VIR_DOMAIN_AFFECT_LIVE)
|
||||||
|
ret = qemuDomainGetIOThreadsLive(driver, vm, info);
|
||||||
|
else
|
||||||
|
ret = qemuDomainGetIOThreadsConfig(targetDef, info);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
qemuDomObjEndAPI(&vm);
|
||||||
|
virObjectUnref(caps);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int qemuDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel)
|
static int qemuDomainGetSecurityLabel(virDomainPtr dom, virSecurityLabelPtr seclabel)
|
||||||
{
|
{
|
||||||
virQEMUDriverPtr driver = dom->conn->privateData;
|
virQEMUDriverPtr driver = dom->conn->privateData;
|
||||||
@ -19104,6 +19327,7 @@ static virHypervisorDriver qemuHypervisorDriver = {
|
|||||||
.domainGetEmulatorPinInfo = qemuDomainGetEmulatorPinInfo, /* 0.10.0 */
|
.domainGetEmulatorPinInfo = qemuDomainGetEmulatorPinInfo, /* 0.10.0 */
|
||||||
.domainGetVcpus = qemuDomainGetVcpus, /* 0.4.4 */
|
.domainGetVcpus = qemuDomainGetVcpus, /* 0.4.4 */
|
||||||
.domainGetMaxVcpus = qemuDomainGetMaxVcpus, /* 0.4.4 */
|
.domainGetMaxVcpus = qemuDomainGetMaxVcpus, /* 0.4.4 */
|
||||||
|
.domainGetIOThreadsInfo = qemuDomainGetIOThreadsInfo, /* 1.2.14 */
|
||||||
.domainGetSecurityLabel = qemuDomainGetSecurityLabel, /* 0.6.1 */
|
.domainGetSecurityLabel = qemuDomainGetSecurityLabel, /* 0.6.1 */
|
||||||
.domainGetSecurityLabelList = qemuDomainGetSecurityLabelList, /* 0.10.0 */
|
.domainGetSecurityLabelList = qemuDomainGetSecurityLabelList, /* 0.10.0 */
|
||||||
.nodeGetSecurityModel = qemuNodeGetSecurityModel, /* 0.6.1 */
|
.nodeGetSecurityModel = qemuNodeGetSecurityModel, /* 0.6.1 */
|
||||||
|
Loading…
Reference in New Issue
Block a user