Messages in this thread Patch in this message | | | Date | Mon, 4 May 2009 12:14:54 +0400 | From | Cyrill Gorcunov <> | Subject | Re: introducing __GFP_PANIC |
| |
[David Rientjes - Sun, May 03, 2009 at 01:58:49PM -0700] | On Mon, 4 May 2009, Cyrill Gorcunov wrote: | | > @@ -1685,7 +1687,9 @@ nopage: | > dump_stack(); | > show_mem(); | > } | > - return page; | > + if (unlikely(gfp_mask & __GFP_PANIC)) | > + panic("Out of memory: panic due to __GFP_PANIC\n"); | > + return NULL; | > got_pg: | > if (kmemcheck_enabled) | > kmemcheck_pagealloc_alloc(page, order, gfp_mask); | > | | If we really want a __GFP_PANIC flag for this purpose, I'd recommend also | emitting the order and gfpmask in the panic() message since it may not be | immediately obvious from the caller. |
Thanks for note, David!
Here is an updated version for review. I hope I've covered all cases. Complains are welcome :)
-- Cyrill --- mm: introduce __GFP_PANIC
Sometime we need that memory obtained via kmalloc should always be granted. If there is no enough memory we just can't go further.
For such a case we introduce __GFP_PANIC panic modificator. If memory can't be granted -- we just panic.
Note that __GFP_PANIC implicitly turn off failslab facility on such kind calls.
Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> --- include/linux/gfp.h | 13 ++++++++++--- include/linux/slab_def.h | 1 + mm/failslab.c | 3 +++ mm/page_alloc.c | 17 +++++++++++++++-- 4 files changed, 29 insertions(+), 5 deletions(-)
Index: linux-2.6.git/include/linux/gfp.h ===================================================================== --- linux-2.6.git.orig/include/linux/gfp.h +++ linux-2.6.git/include/linux/gfp.h @@ -7,6 +7,7 @@ #include <linux/topology.h> struct vm_area_struct; +void oom_panic(gfp_t gfp_mask, unsigned int order); /* * GFP bitmasks.. @@ -58,7 +59,9 @@ struct vm_area_struct; #define __GFP_NOTRACK ((__force gfp_t)0) #endif -#define __GFP_BITS_SHIFT 22 /* Room for 22 __GFP_FOO bits */ +#define __GFP_PANIC ((__force gfp_t)0x400000u) /* Panic on page alloction failure */ + +#define __GFP_BITS_SHIFT 23 /* Room for 23 __GFP_FOO bits */ #define __GFP_BITS_MASK ((__force gfp_t)((1 << __GFP_BITS_SHIFT) - 1)) /* This equals 0, but use constants in case they ever change */ @@ -196,8 +199,10 @@ __alloc_pages_nodemask(gfp_t gfp_mask, u static inline struct page *alloc_pages_node(int nid, gfp_t gfp_mask, unsigned int order) { - if (unlikely(order >= MAX_ORDER)) + if (unlikely(order >= MAX_ORDER)) { + oom_panic(gfp_mask, order); return NULL; + } /* Unknown node is current node */ if (nid < 0) @@ -212,8 +217,10 @@ extern struct page *alloc_pages_current( static inline struct page * alloc_pages(gfp_t gfp_mask, unsigned int order) { - if (unlikely(order >= MAX_ORDER)) + if (unlikely(order >= MAX_ORDER)) { + oom_panic(gfp_mask, order); return NULL; + } return alloc_pages_current(gfp_mask, order); } Index: linux-2.6.git/include/linux/slab_def.h ===================================================================== --- linux-2.6.git.orig/include/linux/slab_def.h +++ linux-2.6.git/include/linux/slab_def.h @@ -143,6 +143,7 @@ static __always_inline void *kmalloc(siz i++; #include <linux/kmalloc_sizes.h> #undef CACHE + oom_panic(flags, get_order(size)); return NULL; found: #ifdef CONFIG_ZONE_DMA Index: linux-2.6.git/mm/failslab.c ===================================================================== --- linux-2.6.git.orig/mm/failslab.c +++ linux-2.6.git/mm/failslab.c @@ -17,6 +17,9 @@ bool should_failslab(size_t size, gfp_t if (gfpflags & __GFP_NOFAIL) return false; + if (gfpflags & __GFP_PANIC) + return false; + if (failslab.ignore_gfp_wait && (gfpflags & __GFP_WAIT)) return false; Index: linux-2.6.git/mm/page_alloc.c ===================================================================== --- linux-2.6.git.orig/mm/page_alloc.c +++ linux-2.6.git/mm/page_alloc.c @@ -1185,6 +1185,8 @@ static int should_fail_alloc_page(gfp_t return 0; if (gfp_mask & __GFP_NOFAIL) return 0; + if (gfp_mask & __GFP_PANIC) + return 0; if (fail_page_alloc.ignore_gfp_highmem && (gfp_mask & __GFP_HIGHMEM)) return 0; if (fail_page_alloc.ignore_gfp_wait && (gfp_mask & __GFP_WAIT)) @@ -1472,6 +1474,16 @@ try_next_zone: return page; } +void oom_panic(gfp_t gfp_mask, unsigned int order) +{ + if (likely(!(gfp_mask & __GFP_PANIC))) + return; + + panic("Out of memory: panic due to __GFP_PANIC.\n" + "%s order:%d, mode:0x%x\n", current->comm, + order, gfp_mask); +} + /* * This is the 'heart' of the zoned buddy allocator. */ @@ -1506,7 +1518,7 @@ restart: * Happens if we have an empty zonelist as a result of * GFP_THISNODE being used on a memoryless node */ - return NULL; + goto nopage; } page = get_page_from_freelist(gfp_mask|__GFP_HARDWALL, nodemask, order, @@ -1685,7 +1697,8 @@ nopage: dump_stack(); show_mem(); } - return page; + oom_panic(gfp_mask, order); + return NULL; got_pg: if (kmemcheck_enabled) kmemcheck_pagealloc_alloc(page, order, gfp_mask);
| |