diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/page_alloc.c | 17 | ||||
-rw-r--r-- | mm/vmscan.c | 13 |
2 files changed, 24 insertions, 6 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 18a60fdbd..2567aa2df 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c @@ -227,6 +227,23 @@ struct page * __alloc_pages(zonelist_t *zonelist, unsigned long order) * We are falling back to lower-level zones if allocation * in a higher zone fails. */ + + for (;;) { + zone_t *z = *(zone++); + if (!z) + break; + if (!z->size) + BUG(); + + /* If there are zones with a lot of free memory allocate from them */ + if (z->free_pages > z->pages_high) { + struct page *page = rmqueue(z, order); + if (page) + return page; + } + } + + zone = zonelist->zones; for (;;) { zone_t *z = *(zone++); if (!z) diff --git a/mm/vmscan.c b/mm/vmscan.c index be600ec49..f19721ee5 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -440,7 +440,7 @@ static inline int memory_pressure(void) } /* - * Check if there is any memory pressure (free_pages < pages_low) + * Check if there recently has been memory pressure (zone_wake_kswapd) */ static inline int keep_kswapd_awake(void) { @@ -541,16 +541,16 @@ static int do_try_to_free_pages(unsigned int gfp_mask) if (--swap_count < 0) break; - priority--; - } while (priority >= 0); + } while (--priority >= 0); - /* Always end on a shrink_mmap.. */ + /* Always end on a shrink_mmap.., may sleep... */ while (shrink_mmap(0, gfp_mask)) { if (!--count) goto done; } - /* We return 1 if we are freed some page */ - return (count != FREE_COUNT); + /* We return 1 if we are freed some page, or + * there are no memory pressure remaining */ + return (count != FREE_COUNT || !memory_pressure()); done: return 1; @@ -626,6 +626,7 @@ int try_to_free_pages(unsigned int gfp_mask) int retval = 1; if (gfp_mask & __GFP_WAIT) { + current->state = TASK_RUNNING; current->flags |= PF_MEMALLOC; retval = do_try_to_free_pages(gfp_mask); current->flags &= ~PF_MEMALLOC; |