|
@@ -466,29 +466,6 @@ static inline void rmv_page_order(struct page *page)
|
|
|
set_page_private(page, 0);
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Locate the struct page for both the matching buddy in our
|
|
|
- * pair (buddy1) and the combined O(n+1) page they form (page).
|
|
|
- *
|
|
|
- * 1) Any buddy B1 will have an order O twin B2 which satisfies
|
|
|
- * the following equation:
|
|
|
- * B2 = B1 ^ (1 << O)
|
|
|
- * For example, if the starting buddy (buddy2) is #8 its order
|
|
|
- * 1 buddy is #10:
|
|
|
- * B2 = 8 ^ (1 << 1) = 8 ^ 2 = 10
|
|
|
- *
|
|
|
- * 2) Any buddy B will have an order O+1 parent P which
|
|
|
- * satisfies the following equation:
|
|
|
- * P = B & ~(1 << O)
|
|
|
- *
|
|
|
- * Assumption: *_mem_map is contiguous at least up to MAX_ORDER
|
|
|
- */
|
|
|
-static inline unsigned long
|
|
|
-__find_buddy_index(unsigned long page_idx, unsigned int order)
|
|
|
-{
|
|
|
- return page_idx ^ (1 << order);
|
|
|
-}
|
|
|
-
|
|
|
/*
|
|
|
* This function checks whether a page is free && is the buddy
|
|
|
* we can do coalesce a page and its buddy if
|
|
@@ -569,6 +546,7 @@ static inline void __free_one_page(struct page *page,
|
|
|
unsigned long combined_idx;
|
|
|
unsigned long uninitialized_var(buddy_idx);
|
|
|
struct page *buddy;
|
|
|
+ int max_order = MAX_ORDER;
|
|
|
|
|
|
VM_BUG_ON(!zone_is_initialized(zone));
|
|
|
|
|
@@ -577,15 +555,24 @@ static inline void __free_one_page(struct page *page,
|
|
|
return;
|
|
|
|
|
|
VM_BUG_ON(migratetype == -1);
|
|
|
- if (!is_migrate_isolate(migratetype))
|
|
|
+ if (is_migrate_isolate(migratetype)) {
|
|
|
+ /*
|
|
|
+ * We restrict max order of merging to prevent merge
|
|
|
+ * between freepages on isolate pageblock and normal
|
|
|
+ * pageblock. Without this, pageblock isolation
|
|
|
+ * could cause incorrect freepage accounting.
|
|
|
+ */
|
|
|
+ max_order = min(MAX_ORDER, pageblock_order + 1);
|
|
|
+ } else {
|
|
|
__mod_zone_freepage_state(zone, 1 << order, migratetype);
|
|
|
+ }
|
|
|
|
|
|
- page_idx = pfn & ((1 << MAX_ORDER) - 1);
|
|
|
+ page_idx = pfn & ((1 << max_order) - 1);
|
|
|
|
|
|
VM_BUG_ON_PAGE(page_idx & ((1 << order) - 1), page);
|
|
|
VM_BUG_ON_PAGE(bad_range(zone, page), page);
|
|
|
|
|
|
- while (order < MAX_ORDER-1) {
|
|
|
+ while (order < max_order - 1) {
|
|
|
buddy_idx = __find_buddy_index(page_idx, order);
|
|
|
buddy = page + (buddy_idx - page_idx);
|
|
|
if (!page_is_buddy(page, buddy, order))
|
|
@@ -1486,7 +1473,7 @@ void split_page(struct page *page, unsigned int order)
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(split_page);
|
|
|
|
|
|
-static int __isolate_free_page(struct page *page, unsigned int order)
|
|
|
+int __isolate_free_page(struct page *page, unsigned int order)
|
|
|
{
|
|
|
unsigned long watermark;
|
|
|
struct zone *zone;
|