aboutsummaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c30
1 files changed, 25 insertions, 5 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index a6326c71b663..596180fedd3a 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -475,6 +475,8 @@ static inline void __free_one_page(struct page *page,
475 int migratetype) 475 int migratetype)
476{ 476{
477 unsigned long page_idx; 477 unsigned long page_idx;
478 unsigned long combined_idx;
479 struct page *buddy;
478 480
479 if (unlikely(PageCompound(page))) 481 if (unlikely(PageCompound(page)))
480 if (unlikely(destroy_compound_page(page, order))) 482 if (unlikely(destroy_compound_page(page, order)))
@@ -488,9 +490,6 @@ static inline void __free_one_page(struct page *page,
488 VM_BUG_ON(bad_range(zone, page)); 490 VM_BUG_ON(bad_range(zone, page));
489 491
490 while (order < MAX_ORDER-1) { 492 while (order < MAX_ORDER-1) {
491 unsigned long combined_idx;
492 struct page *buddy;
493
494 buddy = __page_find_buddy(page, page_idx, order); 493 buddy = __page_find_buddy(page, page_idx, order);
495 if (!page_is_buddy(page, buddy, order)) 494 if (!page_is_buddy(page, buddy, order))
496 break; 495 break;
@@ -505,8 +504,29 @@ static inline void __free_one_page(struct page *page,
505 order++; 504 order++;
506 } 505 }
507 set_page_order(page, order); 506 set_page_order(page, order);
508 list_add(&page->lru, 507
509 &zone->free_area[order].free_list[migratetype]); 508 /*
509 * If this is not the largest possible page, check if the buddy
510 * of the next-highest order is free. If it is, it's possible
511 * that pages are being freed that will coalesce soon. In case,
512 * that is happening, add the free page to the tail of the list
513 * so it's less likely to be used soon and more likely to be merged
514 * as a higher order page
515 */
516 if ((order < MAX_ORDER-1) && pfn_valid_within(page_to_pfn(buddy))) {
517 struct page *higher_page, *higher_buddy;
518 combined_idx = __find_combined_index(page_idx, order);
519 higher_page = page + combined_idx - page_idx;
520 higher_buddy = __page_find_buddy(higher_page, combined_idx, order + 1);
521 if (page_is_buddy(higher_page, higher_buddy, order + 1)) {
522 list_add_tail(&page->lru,
523 &zone->free_area[order].free_list[migratetype]);
524 goto out;
525 }
526 }
527
528 list_add(&page->lru, &zone->free_area[order].free_list[migratetype]);
529out:
510 zone->free_area[order].nr_free++; 530 zone->free_area[order].nr_free++;
511} 531}
512 532