aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/page_alloc.c24
1 files changed, 15 insertions, 9 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 1b1c39e6a9b8..6877e22e3aa1 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -525,32 +525,38 @@ static void free_pcppages_bulk(struct zone *zone, int count,
525 struct per_cpu_pages *pcp) 525 struct per_cpu_pages *pcp)
526{ 526{
527 int migratetype = 0; 527 int migratetype = 0;
528 int batch_free = 0;
528 529
529 spin_lock(&zone->lock); 530 spin_lock(&zone->lock);
530 zone_clear_flag(zone, ZONE_ALL_UNRECLAIMABLE); 531 zone_clear_flag(zone, ZONE_ALL_UNRECLAIMABLE);
531 zone->pages_scanned = 0; 532 zone->pages_scanned = 0;
532 533
533 __mod_zone_page_state(zone, NR_FREE_PAGES, count); 534 __mod_zone_page_state(zone, NR_FREE_PAGES, count);
534 while (count--) { 535 while (count) {
535 struct page *page; 536 struct page *page;
536 struct list_head *list; 537 struct list_head *list;
537 538
538 /* 539 /*
539 * Remove pages from lists in a round-robin fashion. This spinning 540 * Remove pages from lists in a round-robin fashion. A
540 * around potentially empty lists is bloody awful, alternatives that 541 * batch_free count is maintained that is incremented when an
541 * don't suck are welcome 542 * empty list is encountered. This is so more pages are freed
543 * off fuller lists instead of spinning excessively around empty
544 * lists
542 */ 545 */
543 do { 546 do {
547 batch_free++;
544 if (++migratetype == MIGRATE_PCPTYPES) 548 if (++migratetype == MIGRATE_PCPTYPES)
545 migratetype = 0; 549 migratetype = 0;
546 list = &pcp->lists[migratetype]; 550 list = &pcp->lists[migratetype];
547 } while (list_empty(list)); 551 } while (list_empty(list));
548 552
549 page = list_entry(list->prev, struct page, lru); 553 do {
550 /* have to delete it as __free_one_page list manipulates */ 554 page = list_entry(list->prev, struct page, lru);
551 list_del(&page->lru); 555 /* must delete as __free_one_page list manipulates */
552 trace_mm_page_pcpu_drain(page, 0, migratetype); 556 list_del(&page->lru);
553 __free_one_page(page, zone, 0, migratetype); 557 __free_one_page(page, zone, 0, migratetype);
558 trace_mm_page_pcpu_drain(page, 0, migratetype);
559 } while (--count && --batch_free && !list_empty(list));
554 } 560 }
555 spin_unlock(&zone->lock); 561 spin_unlock(&zone->lock);
556} 562}