aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Rientjes <rientjes@google.com>2016-03-17 17:19:19 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2016-03-17 18:09:34 -0400
commitf9054c70d28bc214b2857cf8db8269f4f45a5e23 (patch)
tree2eaaa8b6363efd5a0da09764da38820aea4fcffe
parentb14a1ef58e8acb7fa64c1c8f745b21fd8a577aba (diff)
mm, mempool: only set __GFP_NOMEMALLOC if there are free elements
If an oom killed thread calls mempool_alloc(), it is possible that it'll loop forever if there are no elements on the freelist since __GFP_NOMEMALLOC prevents it from accessing needed memory reserves in oom conditions. Only set __GFP_NOMEMALLOC if there are elements on the freelist. If there are no free elements, allow allocations without the bit set so that memory reserves can be accessed if needed. Additionally, using mempool_alloc() with __GFP_NOMEMALLOC is not supported since the implementation can loop forever without accessing memory reserves when needed. Signed-off-by: David Rientjes <rientjes@google.com> Cc: Greg Thelen <gthelen@google.com> Cc: Michal Hocko <mhocko@kernel.org> Cc: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--mm/mempool.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/mm/mempool.c b/mm/mempool.c
index 7924f4f58a6d..07c383ddbbab 100644
--- a/mm/mempool.c
+++ b/mm/mempool.c
@@ -310,25 +310,36 @@ EXPORT_SYMBOL(mempool_resize);
310 * returns NULL. Note that due to preallocation, this function 310 * returns NULL. Note that due to preallocation, this function
311 * *never* fails when called from process contexts. (it might 311 * *never* fails when called from process contexts. (it might
312 * fail if called from an IRQ context.) 312 * fail if called from an IRQ context.)
313 * Note: using __GFP_ZERO is not supported. 313 * Note: neither __GFP_NOMEMALLOC nor __GFP_ZERO are supported.
314 */ 314 */
315void * mempool_alloc(mempool_t *pool, gfp_t gfp_mask) 315void *mempool_alloc(mempool_t *pool, gfp_t gfp_mask)
316{ 316{
317 void *element; 317 void *element;
318 unsigned long flags; 318 unsigned long flags;
319 wait_queue_t wait; 319 wait_queue_t wait;
320 gfp_t gfp_temp; 320 gfp_t gfp_temp;
321 321
322 /* If oom killed, memory reserves are essential to prevent livelock */
323 VM_WARN_ON_ONCE(gfp_mask & __GFP_NOMEMALLOC);
324 /* No element size to zero on allocation */
322 VM_WARN_ON_ONCE(gfp_mask & __GFP_ZERO); 325 VM_WARN_ON_ONCE(gfp_mask & __GFP_ZERO);
326
323 might_sleep_if(gfp_mask & __GFP_DIRECT_RECLAIM); 327 might_sleep_if(gfp_mask & __GFP_DIRECT_RECLAIM);
324 328
325 gfp_mask |= __GFP_NOMEMALLOC; /* don't allocate emergency reserves */
326 gfp_mask |= __GFP_NORETRY; /* don't loop in __alloc_pages */ 329 gfp_mask |= __GFP_NORETRY; /* don't loop in __alloc_pages */
327 gfp_mask |= __GFP_NOWARN; /* failures are OK */ 330 gfp_mask |= __GFP_NOWARN; /* failures are OK */
328 331
329 gfp_temp = gfp_mask & ~(__GFP_DIRECT_RECLAIM|__GFP_IO); 332 gfp_temp = gfp_mask & ~(__GFP_DIRECT_RECLAIM|__GFP_IO);
330 333
331repeat_alloc: 334repeat_alloc:
335 if (likely(pool->curr_nr)) {
336 /*
337 * Don't allocate from emergency reserves if there are
338 * elements available. This check is racy, but it will
339 * be rechecked each loop.
340 */
341 gfp_temp |= __GFP_NOMEMALLOC;
342 }
332 343
333 element = pool->alloc(gfp_temp, pool->pool_data); 344 element = pool->alloc(gfp_temp, pool->pool_data);
334 if (likely(element != NULL)) 345 if (likely(element != NULL))
@@ -352,11 +363,12 @@ repeat_alloc:
352 * We use gfp mask w/o direct reclaim or IO for the first round. If 363 * We use gfp mask w/o direct reclaim or IO for the first round. If
353 * alloc failed with that and @pool was empty, retry immediately. 364 * alloc failed with that and @pool was empty, retry immediately.
354 */ 365 */
355 if (gfp_temp != gfp_mask) { 366 if ((gfp_temp & ~__GFP_NOMEMALLOC) != gfp_mask) {
356 spin_unlock_irqrestore(&pool->lock, flags); 367 spin_unlock_irqrestore(&pool->lock, flags);
357 gfp_temp = gfp_mask; 368 gfp_temp = gfp_mask;
358 goto repeat_alloc; 369 goto repeat_alloc;
359 } 370 }
371 gfp_temp = gfp_mask;
360 372
361 /* We must not sleep if !__GFP_DIRECT_RECLAIM */ 373 /* We must not sleep if !__GFP_DIRECT_RECLAIM */
362 if (!(gfp_mask & __GFP_DIRECT_RECLAIM)) { 374 if (!(gfp_mask & __GFP_DIRECT_RECLAIM)) {