Skip to content

Commit f9054c7

Browse files
rientjestorvalds
authored andcommitted
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 <[email protected]> Cc: Greg Thelen <[email protected]> Cc: Michal Hocko <[email protected]> Cc: Tetsuo Handa <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent b14a1ef commit f9054c7

File tree

1 file changed

+16
-4
lines changed

1 file changed

+16
-4
lines changed

mm/mempool.c

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -310,25 +310,36 @@ EXPORT_SYMBOL(mempool_resize);
310310
* returns NULL. Note that due to preallocation, this function
311311
* *never* fails when called from process contexts. (it might
312312
* 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.
314314
*/
315-
void * mempool_alloc(mempool_t *pool, gfp_t gfp_mask)
315+
void *mempool_alloc(mempool_t *pool, gfp_t gfp_mask)
316316
{
317317
void *element;
318318
unsigned long flags;
319319
wait_queue_t wait;
320320
gfp_t gfp_temp;
321321

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 */
322325
VM_WARN_ON_ONCE(gfp_mask & __GFP_ZERO);
326+
323327
might_sleep_if(gfp_mask & __GFP_DIRECT_RECLAIM);
324328

325-
gfp_mask |= __GFP_NOMEMALLOC; /* don't allocate emergency reserves */
326329
gfp_mask |= __GFP_NORETRY; /* don't loop in __alloc_pages */
327330
gfp_mask |= __GFP_NOWARN; /* failures are OK */
328331

329332
gfp_temp = gfp_mask & ~(__GFP_DIRECT_RECLAIM|__GFP_IO);
330333

331334
repeat_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+
}
332343

333344
element = pool->alloc(gfp_temp, pool->pool_data);
334345
if (likely(element != NULL))
@@ -352,11 +363,12 @@ void * mempool_alloc(mempool_t *pool, gfp_t gfp_mask)
352363
* We use gfp mask w/o direct reclaim or IO for the first round. If
353364
* alloc failed with that and @pool was empty, retry immediately.
354365
*/
355-
if (gfp_temp != gfp_mask) {
366+
if ((gfp_temp & ~__GFP_NOMEMALLOC) != gfp_mask) {
356367
spin_unlock_irqrestore(&pool->lock, flags);
357368
gfp_temp = gfp_mask;
358369
goto repeat_alloc;
359370
}
371+
gfp_temp = gfp_mask;
360372

361373
/* We must not sleep if !__GFP_DIRECT_RECLAIM */
362374
if (!(gfp_mask & __GFP_DIRECT_RECLAIM)) {

0 commit comments

Comments
 (0)