Zone specific allocations, such as GFP_DMA32, should not be restricted
to cpusets allowed node list: the zones which such allocations demand
might be contained in particular nodes outside the cpuset node list.

Necessary for the following usecase:
- driver which requires zone specific memory (such as KVM, which
requires root pagetable at paddr < 4GB).
- user wants to limit allocations of application to nodeX, and nodeX
has no memory < 4GB.

Signed-off-by: Marcelo Tosatti <>

diff --git a/kernel/cpuset.c b/kernel/cpuset.c
index 3d54c41..3bbc23f 100644
--- a/kernel/cpuset.c
+++ b/kernel/cpuset.c
@@ -2374,6 +2374,7 @@ static struct cpuset *nearest_hardwall_ancestor(struct 
cpuset *cs)
  * variable 'wait' is not set, and the bit ALLOC_CPUSET is not set
  * in alloc_flags.  That logic and the checks below have the combined
  * affect that:
+ *     gfp_zone(mask) < policy_zone - any node ok
  *     in_interrupt - any node ok (current task context irrelevant)
  *     GFP_ATOMIC   - any node ok
  *     TIF_MEMDIE   - any node ok
@@ -2392,6 +2393,10 @@ int __cpuset_node_allowed_softwall(int node, gfp_t 
        if (in_interrupt() || (gfp_mask & __GFP_THISNODE))
                return 1;
+       if (gfp_zone(gfp_mask) < policy_zone)
+               return 1;
        might_sleep_if(!(gfp_mask & __GFP_HARDWALL));
        if (node_isset(node, current->mems_allowed))
                return 1;
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 5dba293..0fd6923 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -2723,6 +2723,11 @@ __alloc_pages_nodemask(gfp_t gfp_mask, unsigned int 
        if (!memcg_kmem_newpage_charge(gfp_mask, &memcg, order))
                return NULL;
+       if (!nodemask && gfp_zone(gfp_mask) < policy_zone)
+               nodemask = &node_states[N_MEMORY];
        cpuset_mems_cookie = read_mems_allowed_begin();

To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to
More majordomo info at
Please read the FAQ at

Reply via email to