conf: Introduce <defaultiothread/>

As of v7.0.0-877-g70ac26b9e5 QEMU exposes its default event loop
for devices with no IOThread assigned as an QMP object. In the
very next commit (v7.0.0-878-g71ad4713cc) it was extended for
thread-pool-min and thread-pool-max attributes. Expose them under
new <defaultiothread/> element.

Signed-off-by: Michal Privoznik <mprivozn@redhat.com>
Reviewed-by: Peter Krempa <pkrempa@redhat.com>
This commit is contained in:
Michal Privoznik 2022-05-16 13:23:32 +02:00
parent 7162cee68a
commit 3e4bebb9d1
7 changed files with 127 additions and 10 deletions

View File

@ -677,6 +677,7 @@ host/guest with many LUNs. :since:`Since 1.2.8 (QEMU only)`
<iothread id="6"/>
<iothread id="8" thread_pool_min="2" thread_pool_max="32"/>
</iothreadids>
<defaultiothread thread_pool_min="8" thread_pool_max="16">
...
</domain>
@ -700,6 +701,16 @@ host/guest with many LUNs. :since:`Since 1.2.8 (QEMU only)`
``thread_pool_max`` which allow setting lower and upper boundary for number
of worker threads for given IOThread. While the former can be value of zero,
the latter can't. :since:`Since 8.5.0`
``defaultiothread``
This element represents the default event loop within hypervisor, where I/O
requests from devices not assigned to a specific IOThread are processed.
The element then can have ``thread_pool_min`` and/or ``thread_pool_max``
attributes, which control the lower and upper boundary for number of worker
threads of the default event loop. Emulator might be multithreaded and spawn
so called worker threads on demand. In general neither of these attributes
should be set (leaving the emulator use its own default values), unless the
emulator runs in a real time workload and thus can't afford unpredictability
of time it takes to spawn new worker threads. :since:`Since 8.5.0`
CPU Tuning

View File

@ -3825,6 +3825,8 @@ void virDomainDefFree(virDomainDef *def)
virDomainIOThreadIDDefArrayFree(def->iothreadids, def->niothreadids);
g_free(def->defaultIOThread);
virBitmapFree(def->cputune.emulatorpin);
g_free(def->cputune.emulatorsched);
@ -17017,6 +17019,7 @@ virDomainIdmapDefParseXML(xmlXPathContextPtr ctxt,
* <iothread id='5'/>
* <iothread id='7'/>
* </iothreadids>
* <defaultiothread thread_pool_min="8" thread_pool_max="8"/>
*/
static virDomainIOThreadIDDef *
virDomainIOThreadIDDefParseXML(xmlNodePtr node)
@ -17042,6 +17045,38 @@ virDomainIOThreadIDDefParseXML(xmlNodePtr node)
}
static int
virDomainDefaultIOThreadDefParse(virDomainDef *def,
xmlXPathContextPtr ctxt)
{
xmlNodePtr node = NULL;
g_autofree virDomainDefaultIOThreadDef *thrd = NULL;
node = virXPathNode("./defaultiothread", ctxt);
if (!node)
return 0;
thrd = g_new0(virDomainDefaultIOThreadDef, 1);
if (virXMLPropInt(node, "thread_pool_min", 10,
VIR_XML_PROP_NONNEGATIVE,
&thrd->thread_pool_min, -1) < 0)
return -1;
if (virXMLPropInt(node, "thread_pool_max", 10,
VIR_XML_PROP_NONNEGATIVE,
&thrd->thread_pool_max, -1) < 0)
return -1;
if (thrd->thread_pool_min == -1 &&
thrd->thread_pool_max == -1)
return 0;
def->defaultIOThread = g_steal_pointer(&thrd);
return 0;
}
static int
virDomainDefParseIOThreads(virDomainDef *def,
xmlXPathContextPtr ctxt)
@ -17059,6 +17094,9 @@ virDomainDefParseIOThreads(virDomainDef *def,
return -1;
}
if (virDomainDefaultIOThreadDefParse(def, ctxt) < 0)
return -1;
/* Extract any iothread id's defined */
if ((n = virXPathNodeSet("./iothreadids/iothread", ctxt, &nodes)) < 0)
return -1;
@ -27604,6 +27642,29 @@ virDomainDefIothreadShouldFormat(const virDomainDef *def)
}
static void
virDomainDefaultIOThreadDefFormat(virBuffer *buf,
const virDomainDef *def)
{
virBuffer attrBuf = VIR_BUFFER_INITIALIZER;
if (!def->defaultIOThread)
return;
if (def->defaultIOThread->thread_pool_min >= 0) {
virBufferAsprintf(&attrBuf, " thread_pool_min='%d'",
def->defaultIOThread->thread_pool_min);
}
if (def->defaultIOThread->thread_pool_max >= 0) {
virBufferAsprintf(&attrBuf, " thread_pool_max='%d'",
def->defaultIOThread->thread_pool_max);
}
virXMLFormatElement(buf, "defaultiothread", &attrBuf, NULL);
}
static void
virDomainDefIOThreadsFormat(virBuffer *buf,
const virDomainDef *def)
@ -27641,6 +27702,8 @@ virDomainDefIOThreadsFormat(virBuffer *buf,
}
virXMLFormatElement(buf, "iothreadids", NULL, &childrenBuf);
virDomainDefaultIOThreadDefFormat(buf, def);
}

View File

@ -2655,6 +2655,12 @@ void virDomainIOThreadIDDefFree(virDomainIOThreadIDDef *def);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(virDomainIOThreadIDDef, virDomainIOThreadIDDefFree);
struct _virDomainDefaultIOThreadDef {
int thread_pool_min;
int thread_pool_max;
};
struct _virDomainCputune {
unsigned long long shares;
bool sharesSpecified;
@ -2863,6 +2869,8 @@ struct _virDomainDef {
size_t niothreadids;
virDomainIOThreadIDDef **iothreadids;
virDomainDefaultIOThreadDef *defaultIOThread;
virDomainCputune cputune;
virDomainResctrlDef **resctrls;

View File

@ -1716,6 +1716,26 @@ virDomainDefFSValidate(const virDomainDef *def)
}
static int
virDomainDefValidateIOThreadsThreadPool(int thread_pool_min,
int thread_pool_max)
{
if (thread_pool_max == 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("thread_pool_max must be a positive integer"));
return -1;
}
if (thread_pool_min > thread_pool_max) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("thread_pool_min must be smaller or equal to thread_pool_max"));
return -1;
}
return 0;
}
static int
virDomainDefValidateIOThreads(const virDomainDef *def)
{
@ -1724,19 +1744,16 @@ virDomainDefValidateIOThreads(const virDomainDef *def)
for (i = 0; i < def->niothreadids; i++) {
virDomainIOThreadIDDef *iothread = def->iothreadids[i];
if (iothread->thread_pool_max == 0) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("thread_pool_max must be a positive integer"));
if (virDomainDefValidateIOThreadsThreadPool(iothread->thread_pool_min,
iothread->thread_pool_max) < 0)
return -1;
}
if (iothread->thread_pool_min > iothread->thread_pool_max) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
_("thread_pool_min must be smaller or equal to thread_pool_max"));
return -1;
}
}
if (def->defaultIOThread &&
virDomainDefValidateIOThreadsThreadPool(def->defaultIOThread->thread_pool_min,
def->defaultIOThread->thread_pool_max) < 0)
return -1;
return 0;
}

View File

@ -844,6 +844,21 @@
</element>
</optional>
<optional>
<element name="defaultiothread">
<optional>
<attribute name="thread_pool_min">
<ref name="unsignedInt"/>
</attribute>
</optional>
<optional>
<attribute name="thread_pool_max">
<ref name="unsignedInt"/>
</attribute>
</optional>
</element>
</optional>
<optional>
<ref name="blkiotune"/>
</optional>

View File

@ -142,6 +142,8 @@ typedef struct _virDomainIOMMUDef virDomainIOMMUDef;
typedef struct _virDomainIOThreadIDDef virDomainIOThreadIDDef;
typedef struct _virDomainDefaultIOThreadDef virDomainDefaultIOThreadDef;
typedef struct _virDomainIdMapDef virDomainIdMapDef;
typedef struct _virDomainIdMapEntry virDomainIdMapEntry;

View File

@ -12,6 +12,7 @@
<iothread id='3'/>
<iothread id='5'/>
</iothreadids>
<defaultiothread thread_pool_min='8' thread_pool_max='16'/>
<os>
<type arch='x86_64' machine='q35'>hvm</type>
<boot dev='hd'/>