diff options
author | Christoph Lameter <clameter@sgi.com> | 2006-09-26 02:31:40 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@g5.osdl.org> | 2006-09-26 11:48:50 -0400 |
commit | 9b819d204cf602eab1a53a9ec4b8d2ca51e02a1d (patch) | |
tree | 9442bf01a00a93a8ae54462fb4878588e1b2a6bf | |
parent | 056c62418cc639bf2fe962c6a6ee56054b838bc7 (diff) |
[PATCH] Add __GFP_THISNODE to avoid fallback to other nodes and ignore cpuset/memory policy restrictions
Add a new gfp flag __GFP_THISNODE to avoid fallback to other nodes. This
flag is essential if a kernel component requires memory to be located on a
certain node. It will be needed for alloc_pages_node() to force allocation
on the indicated node and for alloc_pages() to force allocation on the
current node.
Signed-off-by: Christoph Lameter <clameter@sgi.com>
Cc: Andy Whitcroft <apw@shadowen.org>
Cc: Mel Gorman <mel@csn.ul.ie>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | include/linux/gfp.h | 3 | ||||
-rw-r--r-- | kernel/cpuset.c | 2 | ||||
-rw-r--r-- | mm/mempolicy.c | 2 | ||||
-rw-r--r-- | mm/page_alloc.c | 3 |
4 files changed, 7 insertions, 3 deletions
diff --git a/include/linux/gfp.h b/include/linux/gfp.h index 63ab88a36f39..0eda5b6dedbd 100644 --- a/include/linux/gfp.h +++ b/include/linux/gfp.h | |||
@@ -45,6 +45,7 @@ struct vm_area_struct; | |||
45 | #define __GFP_ZERO ((__force gfp_t)0x8000u)/* Return zeroed page on success */ | 45 | #define __GFP_ZERO ((__force gfp_t)0x8000u)/* Return zeroed page on success */ |
46 | #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */ | 46 | #define __GFP_NOMEMALLOC ((__force gfp_t)0x10000u) /* Don't use emergency reserves */ |
47 | #define __GFP_HARDWALL ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */ | 47 | #define __GFP_HARDWALL ((__force gfp_t)0x20000u) /* Enforce hardwall cpuset memory allocs */ |
48 | #define __GFP_THISNODE ((__force gfp_t)0x40000u)/* No fallback, no policies */ | ||
48 | 49 | ||
49 | #define __GFP_BITS_SHIFT 20 /* Room for 20 __GFP_FOO bits */ | 50 | #define __GFP_BITS_SHIFT 20 /* Room for 20 __GFP_FOO bits */ |
50 | #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) | 51 | #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) |
@@ -53,7 +54,7 @@ struct vm_area_struct; | |||
53 | #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \ | 54 | #define GFP_LEVEL_MASK (__GFP_WAIT|__GFP_HIGH|__GFP_IO|__GFP_FS| \ |
54 | __GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \ | 55 | __GFP_COLD|__GFP_NOWARN|__GFP_REPEAT| \ |
55 | __GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \ | 56 | __GFP_NOFAIL|__GFP_NORETRY|__GFP_NO_GROW|__GFP_COMP| \ |
56 | __GFP_NOMEMALLOC|__GFP_HARDWALL) | 57 | __GFP_NOMEMALLOC|__GFP_HARDWALL|__GFP_THISNODE) |
57 | 58 | ||
58 | /* This equals 0, but use constants in case they ever change */ | 59 | /* This equals 0, but use constants in case they ever change */ |
59 | #define GFP_NOWAIT (GFP_ATOMIC & ~__GFP_HIGH) | 60 | #define GFP_NOWAIT (GFP_ATOMIC & ~__GFP_HIGH) |
diff --git a/kernel/cpuset.c b/kernel/cpuset.c index 4ea6f0dc2fc5..76940361273e 100644 --- a/kernel/cpuset.c +++ b/kernel/cpuset.c | |||
@@ -2316,7 +2316,7 @@ int __cpuset_zone_allowed(struct zone *z, gfp_t gfp_mask) | |||
2316 | const struct cpuset *cs; /* current cpuset ancestors */ | 2316 | const struct cpuset *cs; /* current cpuset ancestors */ |
2317 | int allowed; /* is allocation in zone z allowed? */ | 2317 | int allowed; /* is allocation in zone z allowed? */ |
2318 | 2318 | ||
2319 | if (in_interrupt()) | 2319 | if (in_interrupt() || (gfp_mask & __GFP_THISNODE)) |
2320 | return 1; | 2320 | return 1; |
2321 | node = z->zone_pgdat->node_id; | 2321 | node = z->zone_pgdat->node_id; |
2322 | might_sleep_if(!(gfp_mask & __GFP_HARDWALL)); | 2322 | might_sleep_if(!(gfp_mask & __GFP_HARDWALL)); |
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index c3429a710ab1..8002e1faccda 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -1290,7 +1290,7 @@ struct page *alloc_pages_current(gfp_t gfp, unsigned order) | |||
1290 | 1290 | ||
1291 | if ((gfp & __GFP_WAIT) && !in_interrupt()) | 1291 | if ((gfp & __GFP_WAIT) && !in_interrupt()) |
1292 | cpuset_update_task_memory_state(); | 1292 | cpuset_update_task_memory_state(); |
1293 | if (!pol || in_interrupt()) | 1293 | if (!pol || in_interrupt() || (gfp & __GFP_THISNODE)) |
1294 | pol = &default_policy; | 1294 | pol = &default_policy; |
1295 | if (pol->policy == MPOL_INTERLEAVE) | 1295 | if (pol->policy == MPOL_INTERLEAVE) |
1296 | return alloc_page_interleave(gfp, order, interleave_nodes(pol)); | 1296 | return alloc_page_interleave(gfp, order, interleave_nodes(pol)); |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 208a6b03aa78..ea498788af53 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -893,6 +893,9 @@ get_page_from_freelist(gfp_t gfp_mask, unsigned int order, | |||
893 | * See also cpuset_zone_allowed() comment in kernel/cpuset.c. | 893 | * See also cpuset_zone_allowed() comment in kernel/cpuset.c. |
894 | */ | 894 | */ |
895 | do { | 895 | do { |
896 | if (unlikely((gfp_mask & __GFP_THISNODE) && | ||
897 | (*z)->zone_pgdat != zonelist->zones[0]->zone_pgdat)) | ||
898 | break; | ||
896 | if ((alloc_flags & ALLOC_CPUSET) && | 899 | if ((alloc_flags & ALLOC_CPUSET) && |
897 | !cpuset_zone_allowed(*z, gfp_mask)) | 900 | !cpuset_zone_allowed(*z, gfp_mask)) |
898 | continue; | 901 | continue; |