|
@@ -475,6 +475,8 @@ static inline void __free_one_page(struct page *page,
|
|
int migratetype)
|
|
int migratetype)
|
|
{
|
|
{
|
|
unsigned long page_idx;
|
|
unsigned long page_idx;
|
|
|
|
+ unsigned long combined_idx;
|
|
|
|
+ struct page *buddy;
|
|
|
|
|
|
if (unlikely(PageCompound(page)))
|
|
if (unlikely(PageCompound(page)))
|
|
if (unlikely(destroy_compound_page(page, order)))
|
|
if (unlikely(destroy_compound_page(page, order)))
|
|
@@ -488,9 +490,6 @@ static inline void __free_one_page(struct page *page,
|
|
VM_BUG_ON(bad_range(zone, page));
|
|
VM_BUG_ON(bad_range(zone, page));
|
|
|
|
|
|
while (order < MAX_ORDER-1) {
|
|
while (order < MAX_ORDER-1) {
|
|
- unsigned long combined_idx;
|
|
|
|
- struct page *buddy;
|
|
|
|
-
|
|
|
|
buddy = __page_find_buddy(page, page_idx, order);
|
|
buddy = __page_find_buddy(page, page_idx, order);
|
|
if (!page_is_buddy(page, buddy, order))
|
|
if (!page_is_buddy(page, buddy, order))
|
|
break;
|
|
break;
|
|
@@ -505,8 +504,29 @@ static inline void __free_one_page(struct page *page,
|
|
order++;
|
|
order++;
|
|
}
|
|
}
|
|
set_page_order(page, order);
|
|
set_page_order(page, order);
|
|
- list_add(&page->lru,
|
|
|
|
- &zone->free_area[order].free_list[migratetype]);
|
|
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * If this is not the largest possible page, check if the buddy
|
|
|
|
+ * of the next-highest order is free. If it is, it's possible
|
|
|
|
+ * that pages are being freed that will coalesce soon. In case,
|
|
|
|
+ * that is happening, add the free page to the tail of the list
|
|
|
|
+ * so it's less likely to be used soon and more likely to be merged
|
|
|
|
+ * as a higher order page
|
|
|
|
+ */
|
|
|
|
+ if ((order < MAX_ORDER-1) && pfn_valid_within(page_to_pfn(buddy))) {
|
|
|
|
+ struct page *higher_page, *higher_buddy;
|
|
|
|
+ combined_idx = __find_combined_index(page_idx, order);
|
|
|
|
+ higher_page = page + combined_idx - page_idx;
|
|
|
|
+ higher_buddy = __page_find_buddy(higher_page, combined_idx, order + 1);
|
|
|
|
+ if (page_is_buddy(higher_page, higher_buddy, order + 1)) {
|
|
|
|
+ list_add_tail(&page->lru,
|
|
|
|
+ &zone->free_area[order].free_list[migratetype]);
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ list_add(&page->lru, &zone->free_area[order].free_list[migratetype]);
|
|
|
|
+out:
|
|
zone->free_area[order].nr_free++;
|
|
zone->free_area[order].nr_free++;
|
|
}
|
|
}
|
|
|
|
|