summaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c32
1 files changed, 16 insertions, 16 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 2567aa2df..ae05cf8f8 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -217,7 +217,7 @@ static struct page * rmqueue(zone_t *zone, unsigned long order)
*/
struct page * __alloc_pages(zonelist_t *zonelist, unsigned long order)
{
- zone_t **zone = zonelist->zones;
+ zone_t **zone;
extern wait_queue_head_t kswapd_wait;
/*
@@ -228,21 +228,6 @@ struct page * __alloc_pages(zonelist_t *zonelist, unsigned long order)
* 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++);
@@ -264,6 +249,21 @@ struct page * __alloc_pages(zonelist_t *zonelist, unsigned long order)
}
}
+ /* Three possibilities to get here
+ * - Previous alloc_pages resulted in last zone set to have
+ * zone_wake_kswapd and start it. kswapd has not been able
+ * to release enough pages so that one zone does not have
+ * zone_wake_kswapd set.
+ * - Different sets of zones (zonelist)
+ * previous did not have all zones with zone_wake_kswapd but
+ * this one has... should kswapd be woken up? it will run once.
+ * - SMP race, kswapd went to sleep slightly after it as running
+ * in 'if (waitqueue_active(...))' above.
+ * + anyway the test is very cheap to do...
+ */
+ if (waitqueue_active(&kswapd_wait))
+ wake_up_interruptible(&kswapd_wait);
+
/*
* Ok, we don't have any zones that don't need some
* balancing.. See if we have any that aren't critical..