Choose pages from the per-cpu list based on migration type
[sfrench/cifs-2.6.git] / mm / page_alloc.c
index d54ecf41b44c2e54874233dc1ec25df0b292a7ec..e3e726bd2858f6b97df2e92e4cf7f3ea9073fbd2 100644 (file)
@@ -760,7 +760,8 @@ static int rmqueue_bulk(struct zone *zone, unsigned int order,
                struct page *page = __rmqueue(zone, order, migratetype);
                if (unlikely(page == NULL))
                        break;
-               list_add_tail(&page->lru, list);
+               list_add(&page->lru, list);
+               set_page_private(page, migratetype);
        }
        spin_unlock(&zone->lock);
        return i;
@@ -887,6 +888,7 @@ static void fastcall free_hot_cold_page(struct page *page, int cold)
        local_irq_save(flags);
        __count_vm_event(PGFREE);
        list_add(&page->lru, &pcp->list);
+       set_page_private(page, get_pageblock_migratetype(page));
        pcp->count++;
        if (pcp->count >= pcp->high) {
                free_pages_bulk(zone, pcp->batch, &pcp->list, 0);
@@ -951,9 +953,27 @@ again:
                        if (unlikely(!pcp->count))
                                goto failed;
                }
-               page = list_entry(pcp->list.next, struct page, lru);
-               list_del(&page->lru);
-               pcp->count--;
+               /* Find a page of the appropriate migrate type */
+               list_for_each_entry(page, &pcp->list, lru) {
+                       if (page_private(page) == migratetype) {
+                               list_del(&page->lru);
+                               pcp->count--;
+                               break;
+                       }
+               }
+
+               /*
+                * Check if a page of the appropriate migrate type
+                * was found. If not, allocate more to the pcp list
+                */
+               if (&page->lru == &pcp->list) {
+                       pcp->count += rmqueue_bulk(zone, 0,
+                                       pcp->batch, &pcp->list, migratetype);
+                       page = list_entry(pcp->list.next, struct page, lru);
+                       VM_BUG_ON(page_private(page) != migratetype);
+                       list_del(&page->lru);
+                       pcp->count--;
+               }
        } else {
                spin_lock_irqsave(&zone->lock, flags);
                page = __rmqueue(zone, order, migratetype);