From: Martin Kletzander Date: Thu, 8 Jan 2015 12:54:21 +0000 (+0100) Subject: docs, schema, conf: Add support for setting scheduler parameters of guest threads X-Git-Url: http://xenbits.xensource.com/gitweb?a=commitdiff_plain;h=8680ea9749a22230714a982df2531ac8847551bf;p=libvirt.git docs, schema, conf: Add support for setting scheduler parameters of guest threads In order for QEMU vCPU (and other) threads to run with RT scheduler, libvirt needs to take care of that so QEMU doesn't have to run privileged. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=1178986 Signed-off-by: Martin Kletzander --- diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index d8144ea22c..fcf598428e 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -550,6 +550,8 @@ <quota>-1</quota> <emulator_period>1000000</emulator_period> <emulator_quota>-1</emulator_quota> + <vcpusched vcpus='0-4,^3' scheduler='fifo' priority='1'/> + <iothreadsched iothreads='2' scheduler='batch'/> </cputune> ... </domain> @@ -652,6 +654,19 @@ Only QEMU driver support since 0.10.0 +
vcpusched and iothreadsched
+
+ The optional vcpusched elements specifies the scheduler + type (values batch, idle, fifo, + rr) for particular vCPU/IOThread threads (based on + vcpus and iothreads, leaving out + vcpus/iothreads sets the default). For + real-time schedulers (fifo, rr), priority must + be specified as well (and is ignored for non-real-time ones). The value + range for the priority depends on the host kernel (usually 1-99). + Since 1.2.12 +
+ diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index b1f4eaac06..7a1d299b55 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -815,10 +815,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + batch + idle + + + + + + + fifo + rr + + + + + + + + + diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 7d28314e77..fd3606379c 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -772,6 +772,13 @@ VIR_ENUM_IMPL(virDomainLoader, "rom", "pflash") +VIR_ENUM_IMPL(virDomainThreadSched, VIR_DOMAIN_THREAD_SCHED_LAST, + "other", /* default */ + "batch", + "idle", + "fifo", + "rr") + /* Internal mapping: subset of block job types that can be present in * XML (remaining types are not two-phase). */ VIR_ENUM_DECL(virDomainBlockJob) @@ -2234,6 +2241,14 @@ void virDomainDefFree(virDomainDefPtr def) virDomainVcpuPinDefArrayFree(def->cputune.iothreadspin, def->cputune.niothreadspin); + for (i = 0; i < def->cputune.nvcpusched; i++) + virBitmapFree(def->cputune.vcpusched[i].ids); + VIR_FREE(def->cputune.vcpusched); + + for (i = 0; i < def->cputune.niothreadsched; i++) + virBitmapFree(def->cputune.iothreadsched[i].ids); + VIR_FREE(def->cputune.iothreadsched); + virDomainNumatuneFree(def->numatune); virSysinfoDefFree(def->sysinfo); @@ -12772,6 +12787,70 @@ virDomainLoaderDefParseXML(xmlNodePtr node, return ret; } +static int +virDomainThreadSchedParse(xmlNodePtr node, + unsigned int minid, + unsigned int maxid, + const char *name, + virDomainThreadSchedParamPtr sp) +{ + char *tmp = NULL; + int sched = 0; + + tmp = virXMLPropString(node, name); + if (!tmp) { + virReportError(VIR_ERR_XML_ERROR, + _("Missing attribute '%s' in element '%sched'"), + name, name); + goto error; + } + + if (!virBitmapParse(tmp, 0, &sp->ids, + VIR_DOMAIN_CPUMASK_LEN) || + virBitmapIsAllClear(sp->ids) || + virBitmapNextSetBit(sp->ids, -1) < minid || + virBitmapLastSetBit(sp->ids) > maxid) { + + virReportError(VIR_ERR_XML_ERROR, + _("Invalid value of '%s': %s"), + name, tmp); + goto error; + } + VIR_FREE(tmp); + + tmp = virXMLPropString(node, "scheduler"); + if (tmp) { + if ((sched = virDomainThreadSchedTypeFromString(tmp)) <= 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("Invalid scheduler attribute: '%s'"), + tmp); + goto error; + } + sp->scheduler = sched; + + VIR_FREE(tmp); + if (sp->scheduler >= VIR_DOMAIN_THREAD_SCHED_FIFO) { + tmp = virXMLPropString(node, "priority"); + if (!tmp) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Missing scheduler priority")); + goto error; + } + if (virStrToLong_i(tmp, NULL, 10, &sp->priority) < 0) { + virReportError(VIR_ERR_XML_ERROR, "%s", + _("Invalid value for element priority")); + goto error; + } + VIR_FREE(tmp); + } + } + + return 0; + + error: + VIR_FREE(tmp); + return -1; +} static virDomainDefPtr virDomainDefParseXML(xmlDocPtr xml, @@ -13316,6 +13395,77 @@ virDomainDefParseXML(xmlDocPtr xml, } VIR_FREE(nodes); + if ((n = virXPathNodeSet("./cputune/vcpusched", ctxt, &nodes)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot extract vcpusched nodes")); + goto error; + } + if (n) { + if (n > def->maxvcpus) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("too many vcpusched nodes in cputune")); + goto error; + } + + if (VIR_ALLOC_N(def->cputune.vcpusched, n) < 0) + goto error; + def->cputune.nvcpusched = n; + + for (i = 0; i < def->cputune.nvcpusched; i++) { + if (virDomainThreadSchedParse(nodes[i], + 0, def->maxvcpus - 1, + "vcpus", + &def->cputune.vcpusched[i]) < 0) + goto error; + + for (j = 0; j < i; j++) { + if (virBitmapOverlaps(def->cputune.vcpusched[i].ids, + def->cputune.vcpusched[j].ids)) { + virReportError(VIR_ERR_XML_DETAIL, "%s", + _("vcpusched attributes 'vcpus' " + "must not overlap")); + goto error; + } + } + } + } + VIR_FREE(nodes); + + if ((n = virXPathNodeSet("./cputune/iothreadsched", ctxt, &nodes)) < 0) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("cannot extract iothreadsched nodes")); + goto error; + } + if (n) { + if (n > def->iothreads) { + virReportError(VIR_ERR_INTERNAL_ERROR, "%s", + _("too many iothreadsched nodes in cputune")); + goto error; + } + + if (VIR_ALLOC_N(def->cputune.iothreadsched, n) < 0) + goto error; + def->cputune.niothreadsched = n; + + for (i = 0; i < def->cputune.niothreadsched; i++) { + if (virDomainThreadSchedParse(nodes[i], + 1, def->iothreads, + "iothreads", + &def->cputune.iothreadsched[i]) < 0) + goto error; + + for (j = 0; j < i; j++) { + if (virBitmapOverlaps(def->cputune.iothreadsched[i].ids, + def->cputune.iothreadsched[j].ids)) { + virReportError(VIR_ERR_XML_DETAIL, "%s", + _("iothreadsched attributes 'iothreads' " + "must not overlap")); + goto error; + } + } + } + } + VIR_FREE(nodes); /* analysis of cpu handling */ if ((node = virXPathNode("./cpu[1]", ctxt)) != NULL) { @@ -19621,7 +19771,8 @@ virDomainDefFormatInternal(virDomainDefPtr def, def->cputune.period || def->cputune.quota || def->cputune.emulatorpin || def->cputune.emulator_period || def->cputune.emulator_quota || - def->cputune.niothreadspin) { + def->cputune.niothreadspin || + def->cputune.vcpusched || def->cputune.iothreadsched) { virBufferAddLit(buf, "\n"); cputune = true; } @@ -19690,6 +19841,36 @@ virDomainDefFormatInternal(virDomainDefPtr def, VIR_FREE(cpumask); } + for (i = 0; i < def->cputune.nvcpusched; i++) { + virDomainThreadSchedParamPtr sp = &def->cputune.vcpusched[i]; + char *ids = NULL; + + if (!(ids = virBitmapFormat(sp->ids))) + goto error; + virBufferAsprintf(buf, "scheduler)); + VIR_FREE(ids); + + if (sp->priority) + virBufferAsprintf(buf, " priority='%d'", sp->priority); + virBufferAddLit(buf, "/>\n"); + } + + for (i = 0; i < def->cputune.niothreadsched; i++) { + virDomainThreadSchedParamPtr sp = &def->cputune.iothreadsched[i]; + char *ids = NULL; + + if (!(ids = virBitmapFormat(sp->ids))) + goto error; + virBufferAsprintf(buf, "scheduler)); + VIR_FREE(ids); + + if (sp->priority) + virBufferAsprintf(buf, " priority='%d'", sp->priority); + virBufferAddLit(buf, "/>\n"); + } + virBufferAdjustIndent(buf, -2); if (cputune) virBufferAddLit(buf, "\n"); diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index e96d2e311d..da21bcefe1 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -1810,6 +1810,24 @@ typedef enum { VIR_DOMAIN_CPU_PLACEMENT_MODE_LAST } virDomainCpuPlacementMode; +typedef enum { + VIR_DOMAIN_THREAD_SCHED_OTHER = 0, + VIR_DOMAIN_THREAD_SCHED_BATCH, + VIR_DOMAIN_THREAD_SCHED_IDLE, + VIR_DOMAIN_THREAD_SCHED_FIFO, + VIR_DOMAIN_THREAD_SCHED_RR, + + VIR_DOMAIN_THREAD_SCHED_LAST +} virDomainThreadSched; + +typedef struct _virDomainThreadSchedParam virDomainThreadSchedParam; +typedef virDomainThreadSchedParam *virDomainThreadSchedParamPtr; +struct _virDomainThreadSchedParam { + virBitmapPtr ids; + virDomainThreadSched scheduler; + int priority; +}; + typedef struct _virDomainTimerCatchupDef virDomainTimerCatchupDef; typedef virDomainTimerCatchupDef *virDomainTimerCatchupDefPtr; struct _virDomainTimerCatchupDef { @@ -1997,6 +2015,11 @@ struct _virDomainCputune { virDomainVcpuPinDefPtr emulatorpin; size_t niothreadspin; virDomainVcpuPinDefPtr *iothreadspin; + + size_t nvcpusched; + virDomainThreadSchedParamPtr vcpusched; + size_t niothreadsched; + virDomainThreadSchedParamPtr iothreadsched; }; typedef struct _virDomainBlkiotune virDomainBlkiotune; @@ -2854,6 +2877,7 @@ VIR_ENUM_DECL(virDomainRNGModel) VIR_ENUM_DECL(virDomainRNGBackend) VIR_ENUM_DECL(virDomainTPMModel) VIR_ENUM_DECL(virDomainTPMBackend) +VIR_ENUM_DECL(virDomainThreadSched) /* from libvirt.h */ VIR_ENUM_DECL(virDomainState) VIR_ENUM_DECL(virDomainNostateReason) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index bff9a0bf38..645aef14cb 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -413,6 +413,8 @@ virDomainStateTypeFromString; virDomainStateTypeToString; virDomainTaintTypeFromString; virDomainTaintTypeToString; +virDomainThreadSchedTypeFromString; +virDomainThreadSchedTypeToString; virDomainTimerModeTypeFromString; virDomainTimerModeTypeToString; virDomainTimerNameTypeFromString; diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cputune-iothreadsched-toomuch.xml b/tests/qemuxml2argvdata/qemuxml2argv-cputune-iothreadsched-toomuch.xml new file mode 100644 index 0000000000..1540969a3b --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-cputune-iothreadsched-toomuch.xml @@ -0,0 +1,38 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 2 + 1 + + 2048 + 1000000 + -1 + + + + + + + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + + + + diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cputune-iothreadsched.xml b/tests/qemuxml2argvdata/qemuxml2argv-cputune-iothreadsched.xml new file mode 100644 index 0000000000..0a3ffc7c71 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-cputune-iothreadsched.xml @@ -0,0 +1,39 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 2 + 4 + + 2048 + 1000000 + -1 + + + + + + + + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + + + + diff --git a/tests/qemuxml2argvdata/qemuxml2argv-cputune-vcpusched-overlap.xml b/tests/qemuxml2argvdata/qemuxml2argv-cputune-vcpusched-overlap.xml new file mode 100644 index 0000000000..cbbe7dc18b --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-cputune-vcpusched-overlap.xml @@ -0,0 +1,38 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 4 + 1 + + 2048 + 1000000 + -1 + + + + + + + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + + + + diff --git a/tests/qemuxml2argvtest.c b/tests/qemuxml2argvtest.c index 395cab3d91..316f4793a6 100644 --- a/tests/qemuxml2argvtest.c +++ b/tests/qemuxml2argvtest.c @@ -1253,6 +1253,8 @@ mymain(void) DO_TEST("blkiotune-device", QEMU_CAPS_NAME); DO_TEST("cputune", QEMU_CAPS_NAME); DO_TEST("cputune-zero-shares", QEMU_CAPS_NAME); + DO_TEST_PARSE_ERROR("cputune-iothreadsched-toomuch", QEMU_CAPS_NAME); + DO_TEST_PARSE_ERROR("cputune-vcpusched-overlap", QEMU_CAPS_NAME); DO_TEST("numatune-memory", NONE); DO_TEST_PARSE_ERROR("numatune-memory-invalid-nodeset", NONE); diff --git a/tests/qemuxml2xmloutdata/qemuxml2xmlout-cputune-iothreadsched.xml b/tests/qemuxml2xmloutdata/qemuxml2xmlout-cputune-iothreadsched.xml new file mode 100644 index 0000000000..9f61336b8d --- /dev/null +++ b/tests/qemuxml2xmloutdata/qemuxml2xmlout-cputune-iothreadsched.xml @@ -0,0 +1,39 @@ + + QEMUGuest1 + c7a5fdbd-edaf-9455-926a-d65c16db1809 + 219136 + 219136 + 2 + 4 + + 2048 + 1000000 + -1 + + + + + + + + + hvm + + + + destroy + restart + destroy + + /usr/bin/qemu + + + +
+ + + + + + + diff --git a/tests/qemuxml2xmltest.c b/tests/qemuxml2xmltest.c index cc29083a44..99d46299af 100644 --- a/tests/qemuxml2xmltest.c +++ b/tests/qemuxml2xmltest.c @@ -310,6 +310,7 @@ mymain(void) DO_TEST("blkiotune-device"); DO_TEST("cputune"); DO_TEST("cputune-zero-shares"); + DO_TEST_DIFFERENT("cputune-iothreadsched"); DO_TEST("cputune-numatune"); DO_TEST("vcpu-placement-static");