aboutsummaryrefslogtreecommitdiffstats
path: root/tools/libxl/libxl_numa.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/libxl/libxl_numa.c')
-rw-r--r--tools/libxl/libxl_numa.c88
1 files changed, 64 insertions, 24 deletions
diff --git a/tools/libxl/libxl_numa.c b/tools/libxl/libxl_numa.c
index d95ed2af09..5301ec4f0c 100644
--- a/tools/libxl/libxl_numa.c
+++ b/tools/libxl/libxl_numa.c
@@ -105,30 +105,48 @@ static int comb_next(comb_iter_t it, int n, int k)
/* NUMA automatic placement (see libxl_internal.h for details) */
/*
- * This function turns a k-combination iterator into a node map.
- * This means the bits in the node map corresponding to the indexes
- * of the given combination are the ones that will be set.
- * For example, if the iterator represents the combination { 0, 2, 4},
- * the node map will have bits #0, #2 and #4 set.
+ * This function turns a k-combination iterator into a node map,
+ * given another map, telling us which nodes should be considered.
+ *
+ * This means the bits that are set in suitable_nodemap and that
+ * corresponds to the indexes of the given combination are the ones
+ * that will be set in nodemap.
+ *
+ * For example, given a fully set suitable_nodemap, if the iterator
+ * represents the combination { 0, 2, 4}, nodmeap will have bits #0,
+ * #2 and #4 set.
+ * On the other hand, if, say, suitable_nodemap=01011011, the same
+ * iterator will cause bits #1, #4 and #7 of nodemap to be set.
*/
-static void comb_get_nodemap(comb_iter_t it, libxl_bitmap *nodemap, int k)
+static void comb_get_nodemap(comb_iter_t it, libxl_bitmap *suitable_nodemap,
+ libxl_bitmap *nodemap, int k)
{
- int i;
+ int i, m = 0, n = 0;
libxl_bitmap_set_none(nodemap);
- for (i = 0; i < k; i++)
- libxl_bitmap_set(nodemap, it[i]);
+ libxl_for_each_set_bit(i, *suitable_nodemap) {
+ /* Check wether the n-th set bit of suitable_nodemap
+ * matches with the m-th element of the iterator (and,
+ * only if it does, advance to the next one) */
+ if (m < k && n == it[m]) {
+ libxl_bitmap_set(nodemap, i);
+ m++;
+ }
+ n++;
+ }
}
/* Retrieve the number of cpus that the nodes that are part of the nodemap
- * span. */
+ * span and are also set in suitable_cpumap. */
static int nodemap_to_nr_cpus(libxl_cputopology *tinfo, int nr_cpus,
+ const libxl_bitmap *suitable_cpumap,
const libxl_bitmap *nodemap)
{
int i, nodes_cpus = 0;
for (i = 0; i < nr_cpus; i++) {
- if (libxl_bitmap_test(nodemap, tinfo[i].node))
+ if (libxl_bitmap_test(suitable_cpumap, i) &&
+ libxl_bitmap_test(nodemap, tinfo[i].node))
nodes_cpus++;
}
return nodes_cpus;
@@ -242,6 +260,7 @@ static int count_cpus_per_node(libxl_cputopology *tinfo, int nr_cpus,
int libxl__get_numa_candidate(libxl__gc *gc,
uint32_t min_free_memkb, int min_cpus,
int min_nodes, int max_nodes,
+ const libxl_bitmap *suitable_cpumap,
libxl__numa_candidate_cmpf numa_cmpf,
libxl__numa_candidate *cndt_out,
int *cndt_found)
@@ -249,11 +268,12 @@ int libxl__get_numa_candidate(libxl__gc *gc,
libxl__numa_candidate new_cndt;
libxl_cputopology *tinfo = NULL;
libxl_numainfo *ninfo = NULL;
- int nr_nodes = 0, nr_cpus = 0;
- libxl_bitmap nodemap;
+ int nr_nodes = 0, nr_suit_nodes, nr_cpus = 0;
+ libxl_bitmap suitable_nodemap, nodemap;
int rc = 0;
libxl_bitmap_init(&nodemap);
+ libxl_bitmap_init(&suitable_nodemap);
libxl__numa_candidate_init(&new_cndt);
/* Get platform info and prepare the map for testing the combinations */
@@ -300,6 +320,15 @@ int libxl__get_numa_candidate(libxl__gc *gc,
if (rc)
goto out;
+ /* Allocate and prepare the map of the node that can be utilized for
+ * placement, basing on the map of suitable cpus. */
+ rc = libxl_node_bitmap_alloc(CTX, &suitable_nodemap, 0);
+ if (rc)
+ goto out;
+ rc = libxl_cpumap_to_nodemap(CTX, suitable_cpumap, &suitable_nodemap);
+ if (rc)
+ goto out;
+
/*
* If the minimum number of NUMA nodes is not explicitly specified
* (i.e., min_nodes == 0), we try to figure out a sensible number of nodes
@@ -317,10 +346,14 @@ int libxl__get_numa_candidate(libxl__gc *gc,
else
min_nodes = (min_cpus + cpus_per_node - 1) / cpus_per_node;
}
- if (min_nodes > nr_nodes)
- min_nodes = nr_nodes;
- if (!max_nodes || max_nodes > nr_nodes)
- max_nodes = nr_nodes;
+ /* We also need to be sure we do not exceed the number of
+ * nodes we are allowed to use. */
+ nr_suit_nodes = libxl_bitmap_count_set(&suitable_nodemap);
+
+ if (min_nodes > nr_suit_nodes)
+ min_nodes = nr_suit_nodes;
+ if (!max_nodes || max_nodes > nr_suit_nodes)
+ max_nodes = nr_suit_nodes;
if (min_nodes > max_nodes) {
LOG(ERROR, "Inconsistent minimum or maximum number of guest nodes");
rc = ERROR_INVAL;
@@ -353,12 +386,16 @@ int libxl__get_numa_candidate(libxl__gc *gc,
* amount of free memory and number of cpus) and it can concur to
* become our best placement iff it passes the check.
*/
- for (comb_ok = comb_init(gc, &comb_iter, nr_nodes, min_nodes); comb_ok;
- comb_ok = comb_next(comb_iter, nr_nodes, min_nodes)) {
+ for (comb_ok = comb_init(gc, &comb_iter, nr_suit_nodes, min_nodes);
+ comb_ok;
+ comb_ok = comb_next(comb_iter, nr_suit_nodes, min_nodes)) {
uint32_t nodes_free_memkb;
int nodes_cpus;
- comb_get_nodemap(comb_iter, &nodemap, min_nodes);
+ /* Get the nodemap for the combination, only considering
+ * suitable nodes. */
+ comb_get_nodemap(comb_iter, &suitable_nodemap,
+ &nodemap, min_nodes);
/* If there is not enough memory in this combination, skip it
* and go generating the next one... */
@@ -367,7 +404,8 @@ int libxl__get_numa_candidate(libxl__gc *gc,
continue;
/* And the same applies if this combination is short in cpus */
- nodes_cpus = nodemap_to_nr_cpus(tinfo, nr_cpus, &nodemap);
+ nodes_cpus = nodemap_to_nr_cpus(tinfo, nr_cpus, suitable_cpumap,
+ &nodemap);
if (min_cpus && nodes_cpus < min_cpus)
continue;
@@ -378,7 +416,7 @@ int libxl__get_numa_candidate(libxl__gc *gc,
libxl__numa_candidate_put_nodemap(gc, &new_cndt, &nodemap);
new_cndt.nr_vcpus = nodemap_to_nr_vcpus(gc, tinfo, &nodemap);
new_cndt.free_memkb = nodes_free_memkb;
- new_cndt.nr_nodes = min_nodes;
+ new_cndt.nr_nodes = libxl_bitmap_count_set(&nodemap);
new_cndt.nr_cpus = nodes_cpus;
/*
@@ -392,8 +430,9 @@ int libxl__get_numa_candidate(libxl__gc *gc,
LOG(DEBUG, "New best NUMA placement candidate found: "
"nr_nodes=%d, nr_cpus=%d, nr_vcpus=%d, "
- "free_memkb=%"PRIu32"", min_nodes, new_cndt.nr_cpus,
- new_cndt.nr_vcpus, new_cndt.free_memkb / 1024);
+ "free_memkb=%"PRIu32"", new_cndt.nr_nodes,
+ new_cndt.nr_cpus, new_cndt.nr_vcpus,
+ new_cndt.free_memkb / 1024);
libxl__numa_candidate_put_nodemap(gc, cndt_out, &nodemap);
cndt_out->nr_vcpus = new_cndt.nr_vcpus;
@@ -413,6 +452,7 @@ int libxl__get_numa_candidate(libxl__gc *gc,
out:
libxl_bitmap_dispose(&nodemap);
+ libxl_bitmap_dispose(&suitable_nodemap);
libxl__numa_candidate_dispose(&new_cndt);
libxl_numainfo_list_free(ninfo, nr_nodes);
libxl_cputopology_list_free(tinfo, nr_cpus);