[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen staging] xen/page-alloc: Clamp get_free_buddy() to online nodes



commit 1ae0db5e48106498dcb3b9fe2dd3e74830e284c4
Author:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
AuthorDate: Mon Jun 24 16:38:36 2019 +0100
Commit:     Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
CommitDate: Wed Jul 31 14:18:31 2019 +0100

    xen/page-alloc: Clamp get_free_buddy() to online nodes
    
    d->node_affinity defaults to NODE_MASK_ALL which has bits set outside of
    node_online_map.  This in turn causes the loop in get_free_buddy() to waste
    effort iterating over offline nodes.
    
    Always clamp d->node_affinity to node_online_map.
    
    This in turn requires ensuring that d->node_affinity intersects with
    node_online_map, and there is one case via XEN_DOMCTL_setnodeaffinity where 
a
    disjoint mask can end up being specified.
    
    Tighten up the hypercall check, because there is no plausible reason to 
select
    a node affinity which is disjoint with the system, and leave 
get_free_buddy()
    with an assertion to the same effect, but with a runtime-safe fallback to 
the
    full online node map.
    
    Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
    Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx>
---
 xen/common/domain.c     |  4 ++--
 xen/common/page_alloc.c | 18 +++++++++++++++++-
 2 files changed, 19 insertions(+), 3 deletions(-)

diff --git a/xen/common/domain.c b/xen/common/domain.c
index df523c9ce4..744b572195 100644
--- a/xen/common/domain.c
+++ b/xen/common/domain.c
@@ -627,8 +627,8 @@ void domain_update_node_affinity(struct domain *d)
 
 int domain_set_node_affinity(struct domain *d, const nodemask_t *affinity)
 {
-    /* Being affine with no nodes is just wrong */
-    if ( nodes_empty(*affinity) )
+    /* Being disjoint with the system is just wrong. */
+    if ( !nodes_intersects(*affinity, node_online_map) )
         return -EINVAL;
 
     spin_lock(&d->node_affinity_lock);
diff --git a/xen/common/page_alloc.c b/xen/common/page_alloc.c
index 44a72d0b19..4b16ef0d54 100644
--- a/xen/common/page_alloc.c
+++ b/xen/common/page_alloc.c
@@ -811,11 +811,27 @@ static struct page_info *get_free_buddy(unsigned int 
zone_lo,
                                         const struct domain *d)
 {
     nodeid_t first, node = MEMF_get_node(memflags), req_node = node;
-    nodemask_t nodemask = d ? d->node_affinity : node_online_map;
+    nodemask_t nodemask = node_online_map;
     unsigned int j, zone, nodemask_retry = 0;
     struct page_info *pg;
     bool use_unscrubbed = (memflags & MEMF_no_scrub);
 
+    /*
+     * d->node_affinity is our preferred allocation set if provided, but it
+     * may have bits set outside of node_online_map.  Clamp it.
+     */
+    if ( d )
+    {
+        /*
+         * It is the callers responsibility to ensure that d->node_affinity
+         * isn't complete junk.
+         */
+        if ( nodes_intersects(nodemask, d->node_affinity) )
+            nodes_and(nodemask, nodemask, d->node_affinity);
+        else
+            ASSERT_UNREACHABLE();
+    }
+
     if ( node == NUMA_NO_NODE )
     {
         if ( d != NULL )
--
generated by git-patchbot for /home/xen/git/xen.git#staging

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/xen-changelog

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.