struct zone;
 extern struct zone *zone_table[];
 
+static inline int page_zone_id(struct page *page)
+{
+       return (page->flags >> ZONETABLE_PGSHIFT) & ZONETABLE_MASK;
+}
 static inline struct zone *page_zone(struct page *page)
 {
-       return zone_table[(page->flags >> ZONETABLE_PGSHIFT) &
-                       ZONETABLE_MASK];
+       return zone_table[page_zone_id(page)];
 }
 
 static inline unsigned long page_to_nid(struct page *page)
 
  * 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;
                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);