summaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/page_alloc.c17
-rw-r--r--mm/vmscan.c13
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;