diff options
Diffstat (limited to 'mm')
-rw-r--r-- | mm/page_alloc.c | 24 |
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 | } |