-----Original Message-----
From: John Ferlan [mailto:jferlan@redhat.com]
Sent: Wednesday, September 19, 2018 3:47 AM
To: Wang, Huaqiang <huaqiang.wang(a)intel.com>; libvir-list(a)redhat.com
Cc: Feng, Shaohe <shaohe.feng(a)intel.com>; Niu, Bing <bing.niu(a)intel.com>;
Ding, Jian-feng <jian-feng.ding(a)intel.com>; Zang, Rui <rui.zang(a)intel.com>
Subject: Re: [PATCHv2 4/4] conf: Introduce RDT monitor host capability
ca
On 09/14/2018 09:30 PM, Wang Huaqiang wrote:
> Cache monitoring technology(CMT) and memory bandwidth monitoring
> technology(MBM) are resource monitoring part of Intel resource
> director technology(RDT).
>
> This patch is introducing cache monitor(CMT) to cache and memory
> bandwidth monitor(MBM) for monitoring CPU memory bandwidth.
There's some redundancy in the above...
> The host capability of the two monitors is also introduced in this
> patch.
The above two paragraphs can be collapsed to:
This patch introduces CMT and MBM for monitoring CPU cache and memory
bandwidth into the host capability XML output.
>
> For cache monitor, the host capability is shown like:
For CMT, ...
> <host>
> ...
> <cache>
> <bank id='0' level='3' type='both'
size='15' unit='MiB' cpus='0-5'>
> <control granularity='768' min='1536' unit='KiB'
type='both' maxAllocs='4'/>
> </bank>
> <monitor level='3' 'reuseThreshold'='270336'
maxMonitors='176'>
> <feature name='llc_occupancy'/>
> </monitor>
> </cache>
> ...
> </host>
>
> For memory bandwidth monitor, the capability is shown like this:
For MBM, ...
>
> <host>
> ...
> <memory_bandwidth>
> <node id='1' cpus='6-11'>
> <control granularity='10' min ='10'
maxAllocs='4'/>
> </node>
> <monitor maxMonitors='176'>
> <feature name='mbm_total_bytes'/>
> <feature name='mbm_local_bytes'/>
> </monitor>
> </memory_bandwidth>
> ...
> </host>
>
> Signed-off-by: Wang Huaqiang <huaqiang.wang(a)intel.com>
> ---
> docs/schemas/capability.rng | 37 ++++++-
> src/conf/capabilities.c | 68 ++++++++++++
> src/conf/capabilities.h | 4 +
> src/libvirt_private.syms | 2 +
> src/util/virresctrl.c | 120 ++++++++++++++++++++-
> src/util/virresctrl.h | 62 +++++++++++
> .../resctrl/info/L3_MON/max_threshold_occupancy | 1 +
> .../resctrl/info/L3_MON/mon_features | 1 +
> .../resctrl/info/L3_MON/num_rmids | 1 +
> .../linux-resctrl-cmt/resctrl/manualres/cpus | 1 +
> .../linux-resctrl-cmt/resctrl/manualres/schemata | 1 +
> .../linux-resctrl-cmt/resctrl/manualres/tasks | 0
> .../linux-resctrl-cmt/resctrl/schemata | 1 +
> tests/vircaps2xmldata/linux-resctrl-cmt/system | 1 +
> .../resctrl/info/L3/cbm_mask | 1 +
> .../resctrl/info/L3/min_cbm_bits | 1 +
> .../resctrl/info/L3/num_closids | 1 +
> .../resctrl/info/L3_MON/max_threshold_occupancy | 1 +
> .../resctrl/info/L3_MON/mon_features | 10 ++
> .../resctrl/info/L3_MON/num_rmids | 1 +
> .../resctrl/info/MB/bandwidth_gran | 1 +
> .../resctrl/info/MB/min_bandwidth | 1 +
> .../resctrl/info/MB/num_closids | 1 +
> .../resctrl/manualres/cpus | 1 +
> .../resctrl/manualres/schemata | 1 +
> .../resctrl/manualres/tasks | 0
> .../linux-resctrl-fake-feature/resctrl/schemata | 1 +
> .../linux-resctrl-fake-feature/system | 1 +
> .../resctrl/info/L3_MON/max_threshold_occupancy | 1 +
> .../linux-resctrl/resctrl/info/L3_MON/mon_features | 3 +
> .../linux-resctrl/resctrl/info/L3_MON/num_rmids | 1 +
> .../vircaps2xmldata/vircaps-x86_64-resctrl-cmt.xml | 53 +++++++++
> .../vircaps-x86_64-resctrl-fake-feature.xml | 73 +++++++++++++
> tests/vircaps2xmldata/vircaps-x86_64-resctrl.xml | 7 ++
> tests/vircaps2xmltest.c | 2 +
> 35 files changed, 459 insertions(+), 3 deletions(-) create mode
> 100644
> tests/vircaps2xmldata/linux-resctrl-cmt/resctrl/info/L3_MON/max_thresh
> old_occupancy create mode 100644
> tests/vircaps2xmldata/linux-resctrl-cmt/resctrl/info/L3_MON/mon_featur
> es create mode 100644
> tests/vircaps2xmldata/linux-resctrl-cmt/resctrl/info/L3_MON/num_rmids
> create mode 100644
> tests/vircaps2xmldata/linux-resctrl-cmt/resctrl/manualres/cpus
> create mode 100644
> tests/vircaps2xmldata/linux-resctrl-cmt/resctrl/manualres/schemata
> create mode 100644
> tests/vircaps2xmldata/linux-resctrl-cmt/resctrl/manualres/tasks
> create mode 100644
> tests/vircaps2xmldata/linux-resctrl-cmt/resctrl/schemata
> create mode 120000 tests/vircaps2xmldata/linux-resctrl-cmt/system
> create mode 100644
> tests/vircaps2xmldata/linux-resctrl-fake-feature/resctrl/info/L3/cbm_m
> ask create mode 100644
> tests/vircaps2xmldata/linux-resctrl-fake-feature/resctrl/info/L3/min_c
> bm_bits create mode 100644
> tests/vircaps2xmldata/linux-resctrl-fake-feature/resctrl/info/L3/num_c
> losids create mode 100644
> tests/vircaps2xmldata/linux-resctrl-fake-feature/resctrl/info/L3_MON/m
> ax_threshold_occupancy create mode 100644
> tests/vircaps2xmldata/linux-resctrl-fake-feature/resctrl/info/L3_MON/m
> on_features create mode 100644
> tests/vircaps2xmldata/linux-resctrl-fake-feature/resctrl/info/L3_MON/n
> um_rmids create mode 100644
> tests/vircaps2xmldata/linux-resctrl-fake-feature/resctrl/info/MB/bandw
> idth_gran create mode 100644
> tests/vircaps2xmldata/linux-resctrl-fake-feature/resctrl/info/MB/min_b
> andwidth create mode 100644
> tests/vircaps2xmldata/linux-resctrl-fake-feature/resctrl/info/MB/num_c
> losids create mode 100644
> tests/vircaps2xmldata/linux-resctrl-fake-feature/resctrl/manualres/cpu
> s create mode 100644
> tests/vircaps2xmldata/linux-resctrl-fake-feature/resctrl/manualres/sch
> emata create mode 100644
> tests/vircaps2xmldata/linux-resctrl-fake-feature/resctrl/manualres/tas
> ks create mode 100644
> tests/vircaps2xmldata/linux-resctrl-fake-feature/resctrl/schemata
> create mode 120000
> tests/vircaps2xmldata/linux-resctrl-fake-feature/system
> create mode 100644
> tests/vircaps2xmldata/linux-resctrl/resctrl/info/L3_MON/max_threshold_
> occupancy create mode 100644
> tests/vircaps2xmldata/linux-resctrl/resctrl/info/L3_MON/mon_features
> create mode 100644
> tests/vircaps2xmldata/linux-resctrl/resctrl/info/L3_MON/num_rmids
> create mode 100644
> tests/vircaps2xmldata/vircaps-x86_64-resctrl-cmt.xml
> create mode 100644
> tests/vircaps2xmldata/vircaps-x86_64-resctrl-fake-feature.xml
>
> diff --git a/docs/schemas/capability.rng b/docs/schemas/capability.rng
> index d61515c..fe12bf9 100644
> --- a/docs/schemas/capability.rng
> +++ b/docs/schemas/capability.rng
> @@ -316,6 +316,9 @@
> </zeroOrMore>
> </element>
> </oneOrMore>
> + <optional>
> + <ref name='cpuMonitor'/>
> + </optional>
> </element>
> </define>
>
> @@ -347,7 +350,7 @@
> <optional>
> <attribute name='min'>
> <ref name='unsignedInt'/>
> - </attribute>
> + </attribute>
> </optional>
> <attribute name='maxAllocs'>
> <ref name='unsignedInt'/> @@ -356,9 +359,41 @@
> </zeroOrMore>
> </element>
> </oneOrMore>
> + <optional>
> + <ref name='cpuMonitor'/>
> + </optional>
> </element>
> </define>
>
> + <define name='cpuMonitor'>
> + <element name='monitor'>
> + <optional>
> + <attribute name='level'>
> + <ref name='unsignedInt'/>
> + </attribute>
> + <attribute name='reuseThreshold'>
> + <ref name='unsignedInt'/>
> + </attribute>
> + </optional>
Ironically you fixed alignment above, but created more misalignment.
I've cleaned it up...
Embarrassing...
Will be fixed.
> + <attribute name='maxMonitors'>
> + <ref name='unsignedInt'/>
> + </attribute>
> + <oneOrMore>
> + <element name='feature'>
> + <attribute name='name'>
> + <ref name='monitorFeature'/>
> + </attribute>
> + </element>
> + </oneOrMore>
> + </element>
> + </define>
> +
> + <define name='monitorFeature'>
> + <data type='string'>
> + <param name='pattern'>(llc_|mbm_)[a-zA-Z0-9\-_]+</param>
> + </data>
> + </define>
> +
> <define name='guestcaps'>
> <element name='guest'>
> <ref name='ostype'/>
> diff --git a/src/conf/capabilities.c b/src/conf/capabilities.c index
> 66ad420..ba69d6f 100644
> --- a/src/conf/capabilities.c
> +++ b/src/conf/capabilities.c
> @@ -247,10 +247,12 @@ virCapsDispose(void *object)
>
> for (i = 0; i < caps->host.cache.nbanks; i++)
> virCapsHostCacheBankFree(caps->host.cache.banks[i]);
> + virResctrlInfoMonFree(caps->host.cache.monitor);
> VIR_FREE(caps->host.cache.banks);
>
> for (i = 0; i < caps->host.memBW.nnodes; i++)
> virCapsHostMemBWNodeFree(caps->host.memBW.nodes[i]);
> + virResctrlInfoMonFree(caps->host.memBW.monitor);
> VIR_FREE(caps->host.memBW.nodes);
>
> VIR_FREE(caps->host.netprefix);
> @@ -867,6 +869,50 @@ virCapabilitiesFormatNUMATopology(virBufferPtr
> buf, }
>
Two blank lines
Will be fixed.
> static int
> +virCapabilitiesFormatResctrlMonitor(virBufferPtr buf,
> + virResctrlInfoMonPtr monitor) {
> + size_t i = 0;
> + virBuffer childrenBuf = VIR_BUFFER_INITIALIZER;
> +
> + /* monitor not supported, no capability */
> + if (!monitor)
> + return 0;
> +
> + /* no feature found in mointor means no capability, return */
*monitor
Will be fixed.
> + if (monitor->nfeatures == 0)
> + return 0;
I don't believe we can get the above. See [1] in virResctrlInfoGetMonitorPrefix -
we never steal @mon for @*monitor when
mon->nfeatures == 0
Yes, mon->nfeatures will not be 0, it is ensured in time of creating the
*monitor. But we should still keep the two lines here to prevent the emergence
of
<monitor maxMonitors='127'/>
"<monitor maxMonitors='127'/>" is invalid from the perspective of
any
existing hardware. I can not image the use of a resource monitor without a
counter (indicating through feature name ) associating with it.
I can leave it for safety, unless you think it would ever be useful to
display:
<monitor maxMonitors='127'/>
In which case I'll move the == 0 check below, slap a "/>" on and return
0 - ignoring childrenBuf
> +
> + virBufferAddLit(buf, "<monitor ");
> +
> + /* CMT might not enabled, if enabled show related attributes. */
> + if (monitor->type == VIR_MONITOR_TYPE_CACHE)
> + virBufferAsprintf(buf,
> + "level='%u' reuseThreshold='%u'
",
> + monitor->cache_level,
> + monitor->cache_reuse_threshold);
> + virBufferAsprintf(buf,
> + "maxMonitors='%u'>\n",
> + monitor->max_monitor);
> +
One less blank line here.
Will be fixed.
> +
> + for (i = 0; i < monitor->nfeatures; i++) {
> + virBufferSetChildIndent(&childrenBuf, buf);
This can be to put this outside the for loop
Thanks, will be moved outside.
> + virBufferAsprintf(&childrenBuf,
> + "<feature name='%s'/>\n",
> + monitor->features[i]);
> + }
> +
> + if (virBufferCheckError(&childrenBuf) < 0)
> + return -1;
> + > > + virBufferAddBuffer(buf, &childrenBuf);
> + virBufferAddLit(buf, "</monitor>\n");
> +
> + return 0;
> +}
> +
> +static int
> virCapabilitiesFormatCaches(virBufferPtr buf,
> virCapsHostCachePtr cache) { @@ -953,6
> +999,10 @@ virCapabilitiesFormatCaches(virBufferPtr buf,
> }
> }
>
> + if (virCapabilitiesFormatResctrlMonitor(buf,
> + cache->monitor) < 0)
Fits on previous line, I moved it.
You mean change it to
if (virCapabilitiesFormatResctrlMonitor(buf, cache->monitor) < 0)
right?
Will be fixed.
> + return -1;
> +
> virBufferAdjustIndent(buf, -2);
> virBufferAddLit(buf, "</cache>\n");
>
> @@ -1004,6 +1054,10 @@
virCapabilitiesFormatMemoryBandwidth(virBufferPtr buf,
> }
> }
>
> + if (virCapabilitiesFormatResctrlMonitor(buf,
> + memBW->monitor) < 0)
Same here.
Will be fixed.
> + return -1;
> +
> virBufferAdjustIndent(buf, -2);
> virBufferAddLit(buf, "</memory_bandwidth>\n");
>
> @@ -1664,6 +1718,8 @@ virCapabilitiesInitResctrlMemory(virCapsPtr caps)
> size_t i = 0;
> int ret = -1;
>
Removed blank line here.
Will be fixed.
> + const char *prefix =
> + virMonitorPrefixTypeToString(VIR_MONITOR_TYPE_MEMBW);
> +
> for (i = 0; i < caps->host.cache.nbanks; i++) {
> virCapsHostCacheBankPtr bank = caps->host.cache.banks[i];
> if (VIR_ALLOC(node) < 0)
> @@ -1684,6 +1740,11 @@ virCapabilitiesInitResctrlMemory(virCapsPtr caps)
> node = NULL;
> }
>
> + if (virResctrlInfoGetMonitorPrefix(caps->host.resctrl,
> + prefix,
Fits on previous line
Will be fxied.
> + &caps->host.memBW.monitor) < 0)
> + goto cleanup;
> +
> ret = 0;
> cleanup:
> virCapsHostMemBWNodeFree(node);
> @@ -1704,6 +1765,8 @@ virCapabilitiesInitCaches(virCapsPtr caps)
> struct dirent *ent = NULL;
> virCapsHostCacheBankPtr bank = NULL;
>
Same - removed blank line
OK.
> + const char *prefix =
> + virMonitorPrefixTypeToString(VIR_MONITOR_TYPE_CACHE);
> +
> /* Minimum level to expose in capabilities. Can be lowered or removed
(with
> * the appropriate code below), but should not be increased, because we'd
> * lose information. */
> @@ -1823,6 +1886,11 @@ virCapabilitiesInitCaches(virCapsPtr caps)
> if (virCapabilitiesInitResctrlMemory(caps) < 0)
> goto cleanup;
>
> + if (virResctrlInfoGetMonitorPrefix(caps->host.resctrl,
> + prefix,
Fits on previous line.
Will be fixed.
> + &caps->host.cache.monitor) < 0)
> + goto cleanup;
> +
> ret = 0;
> cleanup:
> VIR_FREE(type);
> diff --git a/src/conf/capabilities.h b/src/conf/capabilities.h index
> 694fd6b..45b331a 100644
> --- a/src/conf/capabilities.h
> +++ b/src/conf/capabilities.h
> @@ -156,6 +156,8 @@ typedef virCapsHostCache *virCapsHostCachePtr;
> struct _virCapsHostCache {
> size_t nbanks;
> virCapsHostCacheBankPtr *banks;
> +
> + virResctrlInfoMonPtr monitor;
> };
>
> typedef struct _virCapsHostMemBWNode virCapsHostMemBWNode; @@ -
171,6
> +173,8 @@ typedef virCapsHostMemBW *virCapsHostMemBWPtr; struct
> _virCapsHostMemBW {
> size_t nnodes;
> virCapsHostMemBWNodePtr *nodes;
> +
> + virResctrlInfoMonPtr monitor;
> };
>
> typedef struct _virCapsHost virCapsHost; diff --git
> a/src/libvirt_private.syms b/src/libvirt_private.syms index
> e7a4d61..8061e1c 100644
> --- a/src/libvirt_private.syms
> +++ b/src/libvirt_private.syms
> @@ -2668,6 +2668,8 @@ virResctrlAllocSetCacheSize;
> virResctrlAllocSetID; virResctrlAllocSetMemoryBandwidth;
> virResctrlInfoGetCache;
> +virResctrlInfoGetMonitorPrefix;
> +virResctrlInfoMonFree;
> virResctrlInfoNew;
>
>
> diff --git a/src/util/virresctrl.c b/src/util/virresctrl.c index
> 4601f69..156618f 100644
> --- a/src/util/virresctrl.c
> +++ b/src/util/virresctrl.c
> @@ -70,6 +70,18 @@ VIR_ENUM_IMPL(virResctrl, VIR_CACHE_TYPE_LAST,
> "CODE",
> "DATA")
>
> +/* Monitor name mapping for monitor naming */
> +VIR_ENUM_IMPL(virMonitor, VIR_MONITOR_TYPE_LAST,
> + "unsupported monitor",
> + "cache monitor",
> + "memory bandwidth monitor")
This is probably overkill for the usage in a VIR_INFO, I've removed it and
you'll
see my suggestion for VIR_INFO below.
Let's remove it as well as that 'VIR_INFO' line.
> +
> +/* Monitor feature name prefix mapping for monitor naming */
> +VIR_ENUM_IMPL(virMonitorPrefix, VIR_MONITOR_TYPE_LAST,
Should be "virResctrlMonitorPrefix"
Agree.
> + "__unsupported__",
> + "llc_",
> + "mbm_")
> +
>
> /* All private typedefs so that they exist for all later definitions. This way
> * structs can be included in one or another without reorganizing the
> code every @@ -207,6 +219,17 @@ virResctrlInfoDispose(void *obj) }
>
>
> +void
> +virResctrlInfoMonFree(virResctrlInfoMonPtr mon) {
> + if (!mon)
> + return;
> +
> + virStringListFree(mon->features);
> + VIR_FREE(mon);
> +}
> +
> +
> /* virResctrlAlloc */
>
> /*
> @@ -686,11 +709,11 @@ virResctrlGetInfo(virResctrlInfoPtr resctrl)
> if (ret < 0)
> goto cleanup;
>
> - ret = virResctrlGetCacheInfo(resctrl, dirp);
> + ret = virResctrlGetMonitorInfo(resctrl);
> if (ret < 0)
> goto cleanup;
>
> - ret = virResctrlGetMonitorInfo(resctrl);
> + ret = virResctrlGetCacheInfo(resctrl, dirp);
Why did the order switch?
If they need to be this order, then patch1 needs adjustment.
I've changed back to the former order for now.
It is swapped by unknown reason, and I don't need any kind of
specific order, let's use the original order.
> if (ret < 0)
> goto cleanup;
>
> @@ -851,6 +874,99 @@ virResctrlInfoGetCache(virResctrlInfoPtr resctrl,
> }
>
>
> +/* virResctrlInfoGetMonitorPrefix
> + *
> + * @resctrl: Pointer to virResctrlInfo
> + * @prefix: Monitor prefix name for monitor looking for.
> + * @monitor: Returns the capability inforamtion for taget monitor if
> +the
*information
*target
Will be fixed.
> + * monitor with prefix name @prefex is supported by host.
s/prefix name @prefex/@prefix
Will be fixed.
> + *
> + * Return monitor capability information describe in prefix name
> + @prefix
> + * through @monitor
* Return monitor capability information for @prefix through @monitor.
* It is possible to return an empty list of features for @monitor
* leaving it up to the caller to handle.
No, no empty feature list will be returned. If feature list for monitor
with @prefix is empty, @monitor will be set to NULL, and 0 will will
be returned. This tells caller the monitor with @prefix is not supported
in system and which is a tolerable case.
This will be guaranteed by performing following line
/* In case *monitor is pointed to some monitor, clean it. */
virResctrlInfoMonFree(*monitor);
This line will be moved like this, to ensure *monitor=NULL if mon->nfeatures == 0
ret = 0;
+ /* In case *monitor is pointed to some monitor, clean it. */
+ virResctrlInfoMonFree(*monitor);
+
if (mon->nfeatures == 0) {
/* No feature found for current monitor, means host does not support
* monitor type with @prefix name.
@@ -959,11 +957,8 @@ virResctrlInfoGetMonitorPrefix(virResctrlInfoPtr resctrl,
goto cleanup;
}
- /* In case *monitor is pointed to some monitor, clean it. */
- VIR_FREE(*monitor);
-
VIR_STEAL_PTR(*monitor, mon);
> + *
> + * Returns 0 if a monitor is found or a valid monitor is not
> + supported by host,
> + * -1 on failure with error message set.
> + * */
s/* */*/
Will be fixed.
New notation for this function is like this:
/* virResctrlInfoGetMonitorPrefix
*
* @resctrl: Pointer to virResctrlInfo
* @prefix: Monitor prefix name for monitor looking for.
* @monitor: Returns the capability information for target monitor if the
* monitor with @prefex is supported by host.
*
* Return monitor capability information for @prefix through @monitor.
* If monitor with @prefix is not supported in system, @monitor will be
* cleared to NULL.
*
* Returns 0 if @monitor is created or monitor type with @prefix is not
* supported by host, -1 on failure with error message set.
*/
> +int
> +virResctrlInfoGetMonitorPrefix(virResctrlInfoPtr resctrl,
> + const char *prefix,
> + virResctrlInfoMonPtr *monitor) {
> + size_t i = 0;
> + virResctrlInfoMongrpPtr mongrp_info = NULL;
> + virResctrlInfoMonPtr mon = NULL;
> + int ret = -1;
> +
> + if (virResctrlInfoIsEmpty(resctrl))
> + return 0;
> +
> + mongrp_info = resctrl->monitor_info;
> +
> + if (!mongrp_info) {
> + VIR_INFO("Monitor is not supported in host");
> + return 0;
> + }
> +
> + if (!prefix) {
> + virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
> + _("Empty prefix name for resctrl monitor"));
> + return -1;
> + }
Could be earlier, but it whatever.
Moved before line
if (virResctrlInfoIsEmpty(resctrl))
> +
> + for (i = 0; i < VIR_MONITOR_TYPE_LAST; i++) {
> + if (STREQ(prefix, virMonitorPrefixTypeToString(i))) {
I'm sure there's a way with ARRAY_CARDINALITY too - that's something I
haven't quite figured out.
Can we use enum type data structure? It is quite common in libvirt.
It should be ok for using array and ARRAY_CARDINALITY, but need to change some
code.
> + if (VIR_ALLOC(mon) < 0)
> + goto cleanup;
> + mon->type = i;
> + break;
> + }
> + }
> +
> + if (!mon) {
> + virReportError(VIR_ERR_INTERNAL_ERROR,
> + _("Bad prefix name \"%s\" for resctrl
> + monitor"),
use '%s'
OK.
> + prefix);
> + goto cleanup;
could be just return -1 since @mon == NULL and that's all cleanup does is clean
it up.
Yes, I think it could return -1 directly here.
> + }
> +
> + mon->max_monitor = mongrp_info->max_monitor;
> +
> + if (mon->type == VIR_MONITOR_TYPE_CACHE) {
> + mon->cache_reuse_threshold = mongrp_info->cache_reuse_threshold;
> + mon->cache_level = mongrp_info->cache_level;
s/= /= /
Just one space.
Will be fixed.
> + }
> +
> + for (i = 0; i < mongrp_info->nfeatures; i++) {
> + if (STRPREFIX(mongrp_info->features[i], prefix)) {
> + if (virStringListAdd(&mon->features,
> + mongrp_info->features[i]) < 0)
> + goto cleanup;
> + mon->nfeatures++;
> + }
> + }
> +
> + ret = 0;
> +
> + if (mon->nfeatures == 0) {
> + /* No feature found for current monitor, means host does not support
> + * monitor type with @prefix name.
> + * Telling caller this monitor is supported by hardware specification,
> + * but not supported by this host */
> + VIR_INFO("%s is not supported by host",
> + virMonitorTypeToString(mon->type));
Actually this just logs a message (if we're printing VIR_INFO) on the daemon side.
The consumer on the other end is goint to have to "handle"
nfeatures == 0 then.
Just tell user some resctrl monitoring is not supported by your system.
Also, since I think @virMonitor is overkill, let's just go with:
VIR_INFO("No resctrl monitor features using prefix '%s' found",
prefix);
Will remove VIR_ENUM_IMPL(virMonitor...) and will change as you recommended.
> + goto cleanup;
[1] If we go to cleanup, then we return 0, but never steal @mon. Our
"consumer" that does the Format won't ever get @*monitor filled in.
return 0, and clear *monitor to NULL, means monitor with @prefix is not
supported here. caller should continue to check next type monitor.
> + }
> +
> + /* In case *monitor is pointed to some monitor, clean it. */
> + VIR_FREE(*monitor);
This should be virResctrlInfoMonFree, right?
Good catch. Will be fixed.
> +
> + VIR_STEAL_PTR(*monitor, mon);
> + cleanup:
> + virResctrlInfoMonFree(mon);
> + return ret;
> +}
> +
> +
> /* virResctrlAlloc-related definitions */ virResctrlAllocPtr
> virResctrlAllocNew(void)
> diff --git a/src/util/virresctrl.h b/src/util/virresctrl.h index
> cfd56dd..949e20f 100644
> --- a/src/util/virresctrl.h
> +++ b/src/util/virresctrl.h
> @@ -36,6 +36,16 @@ typedef enum {
> VIR_ENUM_DECL(virCache);
> VIR_ENUM_DECL(virCacheKernel);
>
The following are missing the Resctrl or RESCRTL_ name "prefix"... e.g.
virResctrlMonitor* and VIR_RESCTRL_MONITOR*
I'll adjust...
Your naming is better. Thanks.
> +typedef enum {
> + VIR_MONITOR_TYPE_UNSUPPORT,
> + VIR_MONITOR_TYPE_CACHE,
> + VIR_MONITOR_TYPE_MEMBW,
> +
> + VIR_MONITOR_TYPE_LAST
> +} virMonitorType;
> +VIR_ENUM_DECL(virMonitor);
No use for ^^ this one.
> +VIR_ENUM_DECL(virMonitorPrefix);
> +
>
> typedef struct _virResctrlInfoPerCache virResctrlInfoPerCache;
> typedef virResctrlInfoPerCache *virResctrlInfoPerCachePtr; @@ -61,6
> +71,51 @@ struct _virResctrlInfoMemBWPerNode {
> unsigned int max_allocation;
> };
>
> +typedef struct _virResctrlInfoMon virResctrlInfoMon; typedef
> +virResctrlInfoMon *virResctrlInfoMonPtr; struct _virResctrlInfoMon {
> + /* Common fields */
> +
> + /* Maximum number of simultaneous monitors */
> + unsigned int max_monitor;
> + /* null-terminal string list for monitor features */
> + char **features;
> + /* Number of monitor features */
> + size_t nfeatures;
> + /* Monitor type */
> + virMonitorType type;
virResctrlMonitorType type;
I'm not a total fan of just 'type', but there's precedent so I won't
change it.
Finding "->type " in the code can be like looking a needle in the haystack.
> +
> + /* cache monitor (CMT) related field
> + *
> + * CMT has following resource monitor event:
> + * "llc_occupancy"
> + *
> + * If this is a cache monitor, the memory bandwidth monitor related
> + * fields and feture events will not be valid. */
*feature
Will be fixed.
Hmmm.. I'm not really sure how to read the above. Is it "important" for
the
consumer to know the relationship to MBM from a data fetching viewpoint?
> +
> + /* This Adjustable value affects the final reuse of resources used by
> + * monitor. After the action of removing a monitor, the kernel may not
> + * release all hardware resources that monitor used immediately if the
> + * cache occupancy value associated with 'removed' monitor is above
this
> + * threshold. Once the cache occupancy is below this threshold, the
> + * underlying hardware resource will be reclaimed and be put into the
> + * resource pool for next reusing.*/
> + unsigned int cache_reuse_threshold;
> + /* The cache 'level' that has the monitor capability */
> + unsigned int cache_level;
> +
> + /* memory bandwidth monitor (MBM) related field
> + *
> + * MBM has following resource monitor events:
> + * "mbm_total_bytes"
> + * "mbm_local_bytes"
> + *
> + * If this is a memory bandwidth monitor, the cache monitor related
> + * fields and feature events will not be valid. */
Similar type, but opposite question - is this an implementation detail that the
normal consumer really won't have to know.
> +
> + /* MBM related field is empty */
Kind of an odd comment - not sure what to do with it or think about it.
Seems I said too much. Let's use an more precise way:
struct _virResctrlInfoMon {
/* Maximum number of simultaneous monitors */
unsigned int max_monitor;
/* null-terminal string list for monitor features */
char **features;
/* Number of monitor features */
size_t nfeatures;
/* Monitor type */
virResctrlMonitorType type;
/* This adjustable value affects the final reuse of resources used by
* monitor. After the action of removing a monitor, the kernel may not
* release all hardware resources that monitor used immediately if the
* cache occupancy value associated with 'removed' monitor is above
this
* threshold. Once the cache occupancy is below this threshold, the
* underlying hardware resource will be reclaimed and be put into the
* resource pool for next reusing.*/
unsigned int cache_reuse_threshold;
/* The cache 'level' that has the monitor capability */
unsigned int cache_level;
};
> +};
> +
> typedef struct _virResctrlInfo virResctrlInfo; typedef
> virResctrlInfo *virResctrlInfoPtr;
>
> @@ -145,4 +200,11 @@ virResctrlAllocAddPID(virResctrlAllocPtr alloc,
> int virResctrlAllocRemove(virResctrlAllocPtr alloc);
>
> +void
> +virResctrlInfoMonFree(virResctrlInfoMonPtr mon);
> +
> +int
> +virResctrlInfoGetMonitorPrefix(virResctrlInfoPtr resctrl,
> + const char *prefix,
> + virResctrlInfoMonPtr *monitor);
Use ATTRIBUTE_NONNULL(3)... The will *Free it and replace it so if what
@*monitor points at is NULL, that's fine, but if it's NULL, then my coverity
build
will capture that.
> #endif /* __VIR_RESCTRL_H__ */
[...]
> diff --git a/tests/vircaps2xmltest.c b/tests/vircaps2xmltest.c index
> 1fb8861..7f3c26a 100644
> --- a/tests/vircaps2xmltest.c
> +++ b/tests/vircaps2xmltest.c
> @@ -111,9 +111,11 @@ mymain(void)
> DO_TEST_FULL("caches", VIR_ARCH_X86_64, true, true);
>
> DO_TEST_FULL("resctrl", VIR_ARCH_X86_64, true, true);
> + DO_TEST_FULL("resctrl-cmt", VIR_ARCH_X86_64, true, true);
So this one just shows that <memory_bandwidth> may not be displayed, true?
And of course the <control> is optional too for <bank>.
Yes. CMT, MBM as well as CAT, MBA are all independent hardware features, we
may encounter some system only support CMT, this test is designed for
this case.
I can make all the suggested alterations with your OK. I think there were a
couple of questions about things which I think we can easily hammer out.
Thank you for your review.
I'll also submit the patches fixed, just for your reference.
Huaqiang
John
> DO_TEST_FULL("resctrl-cdp", VIR_ARCH_X86_64, true, true);
> DO_TEST_FULL("resctrl-skx", VIR_ARCH_X86_64, true, true);
> DO_TEST_FULL("resctrl-skx-twocaches", VIR_ARCH_X86_64, true,
> true);
> + DO_TEST_FULL("resctrl-fake-feature", VIR_ARCH_X86_64, true,
> + true);
>
> return ret;
> }
>