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.c26
1 files changed, 19 insertions, 7 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index b0647b515277..088712f2ac02 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -81,6 +81,7 @@ int min_free_kbytes = 1024;
81unsigned long __initdata nr_kernel_pages; 81unsigned long __initdata nr_kernel_pages;
82unsigned long __initdata nr_all_pages; 82unsigned long __initdata nr_all_pages;
83 83
84#ifdef CONFIG_DEBUG_VM
84static int page_outside_zone_boundaries(struct zone *zone, struct page *page) 85static int page_outside_zone_boundaries(struct zone *zone, struct page *page)
85{ 86{
86 int ret = 0; 87 int ret = 0;
@@ -122,6 +123,13 @@ static int bad_range(struct zone *zone, struct page *page)
122 return 0; 123 return 0;
123} 124}
124 125
126#else
127static inline int bad_range(struct zone *zone, struct page *page)
128{
129 return 0;
130}
131#endif
132
125static void bad_page(const char *function, struct page *page) 133static void bad_page(const char *function, struct page *page)
126{ 134{
127 printk(KERN_EMERG "Bad page state at %s (in process '%s', page %p)\n", 135 printk(KERN_EMERG "Bad page state at %s (in process '%s', page %p)\n",
@@ -255,14 +263,20 @@ __find_combined_index(unsigned long page_idx, unsigned int order)
255/* 263/*
256 * This function checks whether a page is free && is the buddy 264 * This function checks whether a page is free && is the buddy
257 * we can do coalesce a page and its buddy if 265 * we can do coalesce a page and its buddy if
258 * (a) the buddy is free && 266 * (a) the buddy is not in a hole &&
259 * (b) the buddy is on the buddy system && 267 * (b) the buddy is free &&
260 * (c) a page and its buddy have the same order. 268 * (c) the buddy is on the buddy system &&
269 * (d) a page and its buddy have the same order.
261 * for recording page's order, we use page_private(page) and PG_private. 270 * for recording page's order, we use page_private(page) and PG_private.
262 * 271 *
263 */ 272 */
264static inline int page_is_buddy(struct page *page, int order) 273static inline int page_is_buddy(struct page *page, int order)
265{ 274{
275#ifdef CONFIG_HOLES_IN_ZONE
276 if (!pfn_valid(page_to_pfn(page)))
277 return 0;
278#endif
279
266 if (PagePrivate(page) && 280 if (PagePrivate(page) &&
267 (page_order(page) == order) && 281 (page_order(page) == order) &&
268 page_count(page) == 0) 282 page_count(page) == 0)
@@ -314,17 +328,15 @@ static inline void __free_pages_bulk (struct page *page,
314 struct free_area *area; 328 struct free_area *area;
315 struct page *buddy; 329 struct page *buddy;
316 330
317 combined_idx = __find_combined_index(page_idx, order);
318 buddy = __page_find_buddy(page, page_idx, order); 331 buddy = __page_find_buddy(page, page_idx, order);
319
320 if (bad_range(zone, buddy))
321 break;
322 if (!page_is_buddy(buddy, order)) 332 if (!page_is_buddy(buddy, order))
323 break; /* Move the buddy up one level. */ 333 break; /* Move the buddy up one level. */
334
324 list_del(&buddy->lru); 335 list_del(&buddy->lru);
325 area = zone->free_area + order; 336 area = zone->free_area + order;
326 area->nr_free--; 337 area->nr_free--;
327 rmv_page_order(buddy); 338 rmv_page_order(buddy);
339 combined_idx = __find_combined_index(page_idx, order);
328 page = page + (combined_idx - page_idx); 340 page = page + (combined_idx - page_idx);
329 page_idx = combined_idx; 341 page_idx = combined_idx;
330 order++; 342 order++;