[libvirt] [PATCH 0/2] add nodeset check in numatune

for memnode.nodeset in numatune, when setting it more than the host nodes, it should fail. Chen Fan (2): numatune: add check for memnode.nodeset range numatune: move up verification codes in virNumaSetupMemoryPolicy src/conf/numatune_conf.c | 32 ++++++++++++++++++++++++++++++++ src/conf/numatune_conf.h | 4 ++++ src/util/virnuma.c | 15 --------------- 3 files changed, 36 insertions(+), 15 deletions(-) -- 1.9.3

For memnode in numatune element, the range of attribute 'nodeset' was not validated. on my host maxnodes was 1, but when setting nodeset to '0-2' or more, guest also started succuss. there probably was qemu's bug too. Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com> --- src/conf/numatune_conf.c | 29 +++++++++++++++++++++++++++++ src/conf/numatune_conf.h | 4 ++++ 2 files changed, 33 insertions(+) diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c index 21d9a64..a9b20aa 100644 --- a/src/conf/numatune_conf.c +++ b/src/conf/numatune_conf.c @@ -183,6 +183,9 @@ virDomainNumatuneNodeParseXML(virDomainNumatunePtr *numatunePtr, VIR_DOMAIN_CPUMASK_LEN) < 0) goto cleanup; VIR_FREE(tmp); + + if (!virDomainNumatuneNodeSetIsAvailable(numatune, cellid)) + goto cleanup; } ret = 0; @@ -612,3 +615,29 @@ virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune) return false; } + +bool +virDomainNumatuneNodeSetIsAvailable(virDomainNumatunePtr numatune, + int cellid) +{ + int maxnode; + int bit = -1; + virBitmapPtr nodemask = NULL; + + nodemask = virDomainNumatuneGetNodeset(numatune, NULL, cellid); + if (!nodemask) + return false; + + if ((maxnode = virNumaGetMaxNode()) < 0) + return false; + + while ((bit = virBitmapNextSetBit(nodemask, bit)) >= 0) { + if (bit > maxnode) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("NUMA node %d is out of range"), bit); + return false; + } + } + + return true; +} diff --git a/src/conf/numatune_conf.h b/src/conf/numatune_conf.h index 5254629..cab0b83 100644 --- a/src/conf/numatune_conf.h +++ b/src/conf/numatune_conf.h @@ -102,4 +102,8 @@ bool virDomainNumatuneHasPlacementAuto(virDomainNumatunePtr numatune); bool virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune); +extern int virNumaGetMaxNode(void); +bool virDomainNumatuneNodeSetIsAvailable(virDomainNumatunePtr numatune, + int cellid); + #endif /* __NUMATUNE_CONF_H__ */ -- 1.9.3

On 23.09.2014 11:34, Chen Fan wrote:
For memnode in numatune element, the range of attribute 'nodeset' was not validated. on my host maxnodes was 1, but when setting nodeset to '0-2' or more, guest also started succuss. there probably was qemu's bug too.
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com> --- src/conf/numatune_conf.c | 29 +++++++++++++++++++++++++++++ src/conf/numatune_conf.h | 4 ++++ 2 files changed, 33 insertions(+)
diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c index 21d9a64..a9b20aa 100644 --- a/src/conf/numatune_conf.c +++ b/src/conf/numatune_conf.c @@ -183,6 +183,9 @@ virDomainNumatuneNodeParseXML(virDomainNumatunePtr *numatunePtr, VIR_DOMAIN_CPUMASK_LEN) < 0) goto cleanup; VIR_FREE(tmp); + + if (!virDomainNumatuneNodeSetIsAvailable(numatune, cellid)) + goto cleanup;
Well, if there already exists such configuration within an existing domain, this will cause a failure on XML parsing when the daemon is starting and hence domain is lost.
}
ret = 0; @@ -612,3 +615,29 @@ virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune)
return false; } + +bool +virDomainNumatuneNodeSetIsAvailable(virDomainNumatunePtr numatune, + int cellid) +{ + int maxnode; + int bit = -1; + virBitmapPtr nodemask = NULL; + + nodemask = virDomainNumatuneGetNodeset(numatune, NULL, cellid); + if (!nodemask) + return false; + + if ((maxnode = virNumaGetMaxNode()) < 0) + return false;
This will work in real environment, but won't work in tests. You need to mock this to get predictable max numa node.
+ + while ((bit = virBitmapNextSetBit(nodemask, bit)) >= 0) { + if (bit > maxnode) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("NUMA node %d is out of range"), bit); + return false; + } + } + + return true; +} diff --git a/src/conf/numatune_conf.h b/src/conf/numatune_conf.h index 5254629..cab0b83 100644 --- a/src/conf/numatune_conf.h +++ b/src/conf/numatune_conf.h @@ -102,4 +102,8 @@ bool virDomainNumatuneHasPlacementAuto(virDomainNumatunePtr numatune);
bool virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune);
+extern int virNumaGetMaxNode(void); +bool virDomainNumatuneNodeSetIsAvailable(virDomainNumatunePtr numatune, + int cellid); + #endif /* __NUMATUNE_CONF_H__ */
Michal

On Tue, 2014-09-23 at 14:41 +0200, Michal Privoznik wrote:
On 23.09.2014 11:34, Chen Fan wrote:
For memnode in numatune element, the range of attribute 'nodeset' was not validated. on my host maxnodes was 1, but when setting nodeset to '0-2' or more, guest also started succuss. there probably was qemu's bug too.
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com> --- src/conf/numatune_conf.c | 29 +++++++++++++++++++++++++++++ src/conf/numatune_conf.h | 4 ++++ 2 files changed, 33 insertions(+)
diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c index 21d9a64..a9b20aa 100644 --- a/src/conf/numatune_conf.c +++ b/src/conf/numatune_conf.c @@ -183,6 +183,9 @@ virDomainNumatuneNodeParseXML(virDomainNumatunePtr *numatunePtr, VIR_DOMAIN_CPUMASK_LEN) < 0) goto cleanup; VIR_FREE(tmp); + + if (!virDomainNumatuneNodeSetIsAvailable(numatune, cellid)) + goto cleanup;
Well, if there already exists such configuration within an existing domain, this will cause a failure on XML parsing when the daemon is starting and hence domain is lost. Right, I would move this check to VM start routine.
}
ret = 0; @@ -612,3 +615,29 @@ virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune)
return false; } + +bool +virDomainNumatuneNodeSetIsAvailable(virDomainNumatunePtr numatune, + int cellid) +{ + int maxnode; + int bit = -1; + virBitmapPtr nodemask = NULL; + + nodemask = virDomainNumatuneGetNodeset(numatune, NULL, cellid); + if (!nodemask) + return false; + + if ((maxnode = virNumaGetMaxNode()) < 0) + return false;
This will work in real environment, but won't work in tests. You need to mock this to get predictable max numa node.
I will add test case for this. Thanks, Chen
+ + while ((bit = virBitmapNextSetBit(nodemask, bit)) >= 0) { + if (bit > maxnode) { + virReportError(VIR_ERR_INTERNAL_ERROR, + _("NUMA node %d is out of range"), bit); + return false; + } + } + + return true; +} diff --git a/src/conf/numatune_conf.h b/src/conf/numatune_conf.h index 5254629..cab0b83 100644 --- a/src/conf/numatune_conf.h +++ b/src/conf/numatune_conf.h @@ -102,4 +102,8 @@ bool virDomainNumatuneHasPlacementAuto(virDomainNumatunePtr numatune);
bool virDomainNumatuneHasPerNodeBinding(virDomainNumatunePtr numatune);
+extern int virNumaGetMaxNode(void); +bool virDomainNumatuneNodeSetIsAvailable(virDomainNumatunePtr numatune, + int cellid); + #endif /* __NUMATUNE_CONF_H__ */
Michal

use virDomainNumatuneNodeSetIsAvailable() to verify momory.nodeset whether is out of range. and move up the verification. Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com> --- src/conf/numatune_conf.c | 3 +++ src/util/virnuma.c | 15 --------------- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c index a9b20aa..8b43167 100644 --- a/src/conf/numatune_conf.c +++ b/src/conf/numatune_conf.c @@ -278,6 +278,9 @@ virDomainNumatuneParseXML(virDomainNumatunePtr *numatunePtr, nodeset) < 0) goto cleanup; + if (!virDomainNumatuneNodeSetIsAvailable(*numatunePtr, -1)) + goto cleanup; + if (virDomainNumatuneNodeParseXML(numatunePtr, ncells, ctxt) < 0) goto cleanup; diff --git a/src/util/virnuma.c b/src/util/virnuma.c index 1a34398..4766f16 100644 --- a/src/util/virnuma.c +++ b/src/util/virnuma.c @@ -95,31 +95,16 @@ virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, int ret = -1; int bit = 0; size_t i; - int maxnode = 0; virBitmapPtr tmp_nodemask = NULL; tmp_nodemask = virDomainNumatuneGetNodeset(numatune, nodemask, -1); if (!tmp_nodemask) return 0; - if (numa_available() < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("Host kernel is not aware of NUMA.")); - return -1; - } - - maxnode = numa_max_node(); - maxnode = maxnode < NUMA_NUM_NODES ? maxnode : NUMA_NUM_NODES; - /* Convert nodemask to NUMA bitmask. */ nodemask_zero(&mask); bit = -1; while ((bit = virBitmapNextSetBit(tmp_nodemask, bit)) >= 0) { - if (bit > maxnode) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("NUMA node %d is out of range"), bit); - return -1; - } nodemask_set(&mask, bit); } -- 1.9.3

On 23.09.2014 11:34, Chen Fan wrote:
use virDomainNumatuneNodeSetIsAvailable() to verify momory.nodeset whether is out of range. and move up the verification.
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com> --- src/conf/numatune_conf.c | 3 +++ src/util/virnuma.c | 15 --------------- 2 files changed, 3 insertions(+), 15 deletions(-)
I'd expect a test case for this.
diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c index a9b20aa..8b43167 100644 --- a/src/conf/numatune_conf.c +++ b/src/conf/numatune_conf.c @@ -278,6 +278,9 @@ virDomainNumatuneParseXML(virDomainNumatunePtr *numatunePtr, nodeset) < 0) goto cleanup;
+ if (!virDomainNumatuneNodeSetIsAvailable(*numatunePtr, -1)) + goto cleanup; + if (virDomainNumatuneNodeParseXML(numatunePtr, ncells, ctxt) < 0) goto cleanup;
diff --git a/src/util/virnuma.c b/src/util/virnuma.c index 1a34398..4766f16 100644 --- a/src/util/virnuma.c +++ b/src/util/virnuma.c @@ -95,31 +95,16 @@ virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, int ret = -1; int bit = 0; size_t i; - int maxnode = 0; virBitmapPtr tmp_nodemask = NULL;
tmp_nodemask = virDomainNumatuneGetNodeset(numatune, nodemask, -1); if (!tmp_nodemask) return 0;
- if (numa_available() < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("Host kernel is not aware of NUMA.")); - return -1; - } - - maxnode = numa_max_node(); - maxnode = maxnode < NUMA_NUM_NODES ? maxnode : NUMA_NUM_NODES; - /* Convert nodemask to NUMA bitmask. */ nodemask_zero(&mask); bit = -1; while ((bit = virBitmapNextSetBit(tmp_nodemask, bit)) >= 0) { - if (bit > maxnode) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("NUMA node %d is out of range"), bit); - return -1; - } nodemask_set(&mask, bit); }
Yet again, this suffers the same problem that 1/2 does: domain may be lost. Michal

On Tue, 2014-09-23 at 14:42 +0200, Michal Privoznik wrote:
On 23.09.2014 11:34, Chen Fan wrote:
use virDomainNumatuneNodeSetIsAvailable() to verify momory.nodeset whether is out of range. and move up the verification.
Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com> --- src/conf/numatune_conf.c | 3 +++ src/util/virnuma.c | 15 --------------- 2 files changed, 3 insertions(+), 15 deletions(-)
I'd expect a test case for this. Ok, I will add it.
thanks, Chen
diff --git a/src/conf/numatune_conf.c b/src/conf/numatune_conf.c index a9b20aa..8b43167 100644 --- a/src/conf/numatune_conf.c +++ b/src/conf/numatune_conf.c @@ -278,6 +278,9 @@ virDomainNumatuneParseXML(virDomainNumatunePtr *numatunePtr, nodeset) < 0) goto cleanup;
+ if (!virDomainNumatuneNodeSetIsAvailable(*numatunePtr, -1)) + goto cleanup; + if (virDomainNumatuneNodeParseXML(numatunePtr, ncells, ctxt) < 0) goto cleanup;
diff --git a/src/util/virnuma.c b/src/util/virnuma.c index 1a34398..4766f16 100644 --- a/src/util/virnuma.c +++ b/src/util/virnuma.c @@ -95,31 +95,16 @@ virNumaSetupMemoryPolicy(virDomainNumatunePtr numatune, int ret = -1; int bit = 0; size_t i; - int maxnode = 0; virBitmapPtr tmp_nodemask = NULL;
tmp_nodemask = virDomainNumatuneGetNodeset(numatune, nodemask, -1); if (!tmp_nodemask) return 0;
- if (numa_available() < 0) { - virReportError(VIR_ERR_INTERNAL_ERROR, - "%s", _("Host kernel is not aware of NUMA.")); - return -1; - } - - maxnode = numa_max_node(); - maxnode = maxnode < NUMA_NUM_NODES ? maxnode : NUMA_NUM_NODES; - /* Convert nodemask to NUMA bitmask. */ nodemask_zero(&mask); bit = -1; while ((bit = virBitmapNextSetBit(tmp_nodemask, bit)) >= 0) { - if (bit > maxnode) { - virReportError(VIR_ERR_INTERNAL_ERROR, - _("NUMA node %d is out of range"), bit); - return -1; - } nodemask_set(&mask, bit); }
Yet again, this suffers the same problem that 1/2 does: domain may be lost.
Michal
participants (3)
-
Chen Fan
-
Chen, Fan
-
Michal Privoznik