|
@@ -286,22 +286,27 @@ __find_combined_index(unsigned long page_idx, unsigned int order)
|
|
|
* we can do coalesce a page and its buddy if
|
|
|
* (a) the buddy is not in a hole &&
|
|
|
* (b) the buddy is in the buddy system &&
|
|
|
- * (c) a page and its buddy have the same order.
|
|
|
+ * (c) a page and its buddy have the same order &&
|
|
|
+ * (d) a page and its buddy are in the same zone.
|
|
|
*
|
|
|
* For recording whether a page is in the buddy system, we use PG_buddy.
|
|
|
* Setting, clearing, and testing PG_buddy is serialized by zone->lock.
|
|
|
*
|
|
|
* For recording page's order, we use page_private(page).
|
|
|
*/
|
|
|
-static inline int page_is_buddy(struct page *page, int order)
|
|
|
+static inline int page_is_buddy(struct page *page, struct page *buddy,
|
|
|
+ int order)
|
|
|
{
|
|
|
#ifdef CONFIG_HOLES_IN_ZONE
|
|
|
- if (!pfn_valid(page_to_pfn(page)))
|
|
|
+ if (!pfn_valid(page_to_pfn(buddy)))
|
|
|
return 0;
|
|
|
#endif
|
|
|
|
|
|
- if (PageBuddy(page) && page_order(page) == order) {
|
|
|
- BUG_ON(page_count(page) != 0);
|
|
|
+ if (page_zone_id(page) != page_zone_id(buddy))
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (PageBuddy(buddy) && page_order(buddy) == order) {
|
|
|
+ BUG_ON(page_count(buddy) != 0);
|
|
|
return 1;
|
|
|
}
|
|
|
return 0;
|
|
@@ -352,7 +357,7 @@ static inline void __free_one_page(struct page *page,
|
|
|
struct page *buddy;
|
|
|
|
|
|
buddy = __page_find_buddy(page, page_idx, order);
|
|
|
- if (!page_is_buddy(buddy, order))
|
|
|
+ if (!page_is_buddy(page, buddy, order))
|
|
|
break; /* Move the buddy up one level. */
|
|
|
|
|
|
list_del(&buddy->lru);
|