Remove __GFP_NOFAIL in kmem and retry internally.

As of 2.6.31 it's clear __GFP_NOFAIL should no longer be used and it
may disappear from the kernel at any time.  To handle this I have simply
added *_nofail wrappers in the kmem implementation which perform the
retry for non-atomic allocations.

From linux-2.6.31 mm/page_alloc.c:1166
/*
 * __GFP_NOFAIL is not to be used in new code.
 *
 * All __GFP_NOFAIL callers should be fixed so that they
 * properly detect and handle allocation failures.
 *
 * We most definitely don't want callers attempting to
 * allocate greater than order-1 page units with
 * __GFP_NOFAIL.
 */
WARN_ON_ONCE(order > 1);
This commit is contained in:
Brian Behlendorf
2009-11-12 15:11:24 -08:00
parent baf2979ed3
commit c89fdee4d3
2 changed files with 59 additions and 14 deletions
+50 -5
View File
@@ -49,7 +49,7 @@ extern "C" {
/*
* Memory allocation interfaces
*/
#define KM_SLEEP (GFP_KERNEL | __GFP_NOFAIL)
#define KM_SLEEP GFP_KERNEL
#define KM_NOSLEEP GFP_ATOMIC
#undef KM_PANIC /* No linux analog */
#define KM_PUSHPAGE (KM_SLEEP | __GFP_HIGH)
@@ -63,6 +63,51 @@ extern "C" {
# define __GFP_ZERO 0x8000
#endif
/*
* __GFP_NOFAIL looks like it will be removed from the kernel perhaps as
* early as 2.6.32. To avoid this issue when it occurs in upstream kernels
* we retry the allocation here as long as it is not __GFP_WAIT (GFP_ATOMIC).
* I would prefer the caller handle the failure case cleanly but we are
* trying to emulate Solaris and those are not the Solaris semantics.
*/
static inline void *
kmalloc_nofail(size_t size, gfp_t flags)
{
void *ptr;
do {
ptr = kmalloc(size, flags);
} while (ptr == NULL && (flags & __GFP_WAIT));
return ptr;
}
static inline void *
kzalloc_nofail(size_t size, gfp_t flags)
{
void *ptr;
do {
ptr = kzalloc(size, flags);
} while (ptr == NULL && (flags & __GFP_WAIT));
return ptr;
}
#ifdef HAVE_KMALLOC_NODE
static inline void *
kmalloc_node_nofail(size_t size, gfp_t flags, int node)
{
void *ptr;
do {
ptr = kmalloc_node(size, flags, node);
} while (ptr == NULL && (flags & __GFP_WAIT));
return ptr;
}
#endif /* HAVE_KMALLOC_NODE */
#ifdef DEBUG_KMEM
extern atomic64_t kmem_alloc_used;
@@ -125,16 +170,16 @@ extern void vmem_free_debug(void *ptr, size_t size);
#else /* DEBUG_KMEM */
# define kmem_alloc(size, flags) kmalloc((size), (flags))
# define kmem_zalloc(size, flags) kzalloc((size), (flags))
# define kmem_alloc(size, flags) kmalloc_nofail((size), (flags))
# define kmem_zalloc(size, flags) kzalloc_nofail((size), (flags))
# define kmem_free(ptr, size) ((void)(size), kfree(ptr))
# ifdef HAVE_KMALLOC_NODE
# define kmem_alloc_node(size, flags, node) \
kmalloc_node((size), (flags), (node))
kmalloc_node_nofail((size), (flags), (node))
# else
# define kmem_alloc_node(size, flags, node) \
kmalloc((size), (flags))
kmalloc_nofail((size), (flags))
# endif
# define vmem_alloc(size, flags) __vmalloc((size), ((flags) | \