|
@@ -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);
|