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.c80
1 files changed, 63 insertions, 17 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index dc523a1f270d..123c60586740 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -51,6 +51,7 @@ nodemask_t node_possible_map __read_mostly = NODE_MASK_ALL;
51EXPORT_SYMBOL(node_possible_map); 51EXPORT_SYMBOL(node_possible_map);
52unsigned long totalram_pages __read_mostly; 52unsigned long totalram_pages __read_mostly;
53unsigned long totalhigh_pages __read_mostly; 53unsigned long totalhigh_pages __read_mostly;
54unsigned long totalreserve_pages __read_mostly;
54long nr_swap_pages; 55long nr_swap_pages;
55int percpu_pagelist_fraction; 56int percpu_pagelist_fraction;
56 57
@@ -151,7 +152,8 @@ static void bad_page(struct page *page)
151 1 << PG_reclaim | 152 1 << PG_reclaim |
152 1 << PG_slab | 153 1 << PG_slab |
153 1 << PG_swapcache | 154 1 << PG_swapcache |
154 1 << PG_writeback ); 155 1 << PG_writeback |
156 1 << PG_buddy );
155 set_page_count(page, 0); 157 set_page_count(page, 0);
156 reset_page_mapcount(page); 158 reset_page_mapcount(page);
157 page->mapping = NULL; 159 page->mapping = NULL;
@@ -230,18 +232,20 @@ static inline void prep_zero_page(struct page *page, int order, gfp_t gfp_flags)
230 * zone->lock is already acquired when we use these. 232 * zone->lock is already acquired when we use these.
231 * So, we don't need atomic page->flags operations here. 233 * So, we don't need atomic page->flags operations here.
232 */ 234 */
233static inline unsigned long page_order(struct page *page) { 235static inline unsigned long page_order(struct page *page)
236{
234 return page_private(page); 237 return page_private(page);
235} 238}
236 239
237static inline void set_page_order(struct page *page, int order) { 240static inline void set_page_order(struct page *page, int order)
241{
238 set_page_private(page, order); 242 set_page_private(page, order);
239 __SetPagePrivate(page); 243 __SetPageBuddy(page);
240} 244}
241 245
242static inline void rmv_page_order(struct page *page) 246static inline void rmv_page_order(struct page *page)
243{ 247{
244 __ClearPagePrivate(page); 248 __ClearPageBuddy(page);
245 set_page_private(page, 0); 249 set_page_private(page, 0);
246} 250}
247 251
@@ -280,11 +284,13 @@ __find_combined_index(unsigned long page_idx, unsigned int order)
280 * This function checks whether a page is free && is the buddy 284 * This function checks whether a page is free && is the buddy
281 * we can do coalesce a page and its buddy if 285 * we can do coalesce a page and its buddy if
282 * (a) the buddy is not in a hole && 286 * (a) the buddy is not in a hole &&
283 * (b) the buddy is free && 287 * (b) the buddy is in the buddy system &&
284 * (c) the buddy is on the buddy system && 288 * (c) a page and its buddy have the same order.
285 * (d) a page and its buddy have the same order.
286 * for recording page's order, we use page_private(page) and PG_private.
287 * 289 *
290 * For recording whether a page is in the buddy system, we use PG_buddy.
291 * Setting, clearing, and testing PG_buddy is serialized by zone->lock.
292 *
293 * For recording page's order, we use page_private(page).
288 */ 294 */
289static inline int page_is_buddy(struct page *page, int order) 295static inline int page_is_buddy(struct page *page, int order)
290{ 296{
@@ -293,11 +299,11 @@ static inline int page_is_buddy(struct page *page, int order)
293 return 0; 299 return 0;
294#endif 300#endif
295 301
296 if (PagePrivate(page) && 302 if (PageBuddy(page) && page_order(page) == order) {
297 (page_order(page) == order) && 303 BUG_ON(page_count(page) != 0);
298 page_count(page) == 0) 304 return 1;
299 return 1; 305 }
300 return 0; 306 return 0;
301} 307}
302 308
303/* 309/*
@@ -313,7 +319,7 @@ static inline int page_is_buddy(struct page *page, int order)
313 * as necessary, plus some accounting needed to play nicely with other 319 * as necessary, plus some accounting needed to play nicely with other
314 * parts of the VM system. 320 * parts of the VM system.
315 * At each level, we keep a list of pages, which are heads of continuous 321 * At each level, we keep a list of pages, which are heads of continuous
316 * free pages of length of (1 << order) and marked with PG_Private.Page's 322 * free pages of length of (1 << order) and marked with PG_buddy. Page's
317 * order is recorded in page_private(page) field. 323 * order is recorded in page_private(page) field.
318 * So when we are allocating or freeing one, we can derive the state of the 324 * So when we are allocating or freeing one, we can derive the state of the
319 * other. That is, if we allocate a small block, and both were 325 * other. That is, if we allocate a small block, and both were
@@ -376,7 +382,8 @@ static inline int free_pages_check(struct page *page)
376 1 << PG_slab | 382 1 << PG_slab |
377 1 << PG_swapcache | 383 1 << PG_swapcache |
378 1 << PG_writeback | 384 1 << PG_writeback |
379 1 << PG_reserved )))) 385 1 << PG_reserved |
386 1 << PG_buddy ))))
380 bad_page(page); 387 bad_page(page);
381 if (PageDirty(page)) 388 if (PageDirty(page))
382 __ClearPageDirty(page); 389 __ClearPageDirty(page);
@@ -524,7 +531,8 @@ static int prep_new_page(struct page *page, int order, gfp_t gfp_flags)
524 1 << PG_slab | 531 1 << PG_slab |
525 1 << PG_swapcache | 532 1 << PG_swapcache |
526 1 << PG_writeback | 533 1 << PG_writeback |
527 1 << PG_reserved )))) 534 1 << PG_reserved |
535 1 << PG_buddy ))))
528 bad_page(page); 536 bad_page(page);
529 537
530 /* 538 /*
@@ -2472,6 +2480,38 @@ void __init page_alloc_init(void)
2472} 2480}
2473 2481
2474/* 2482/*
2483 * calculate_totalreserve_pages - called when sysctl_lower_zone_reserve_ratio
2484 * or min_free_kbytes changes.
2485 */
2486static void calculate_totalreserve_pages(void)
2487{
2488 struct pglist_data *pgdat;
2489 unsigned long reserve_pages = 0;
2490 int i, j;
2491
2492 for_each_online_pgdat(pgdat) {
2493 for (i = 0; i < MAX_NR_ZONES; i++) {
2494 struct zone *zone = pgdat->node_zones + i;
2495 unsigned long max = 0;
2496
2497 /* Find valid and maximum lowmem_reserve in the zone */
2498 for (j = i; j < MAX_NR_ZONES; j++) {
2499 if (zone->lowmem_reserve[j] > max)
2500 max = zone->lowmem_reserve[j];
2501 }
2502
2503 /* we treat pages_high as reserved pages. */
2504 max += zone->pages_high;
2505
2506 if (max > zone->present_pages)
2507 max = zone->present_pages;
2508 reserve_pages += max;
2509 }
2510 }
2511 totalreserve_pages = reserve_pages;
2512}
2513
2514/*
2475 * setup_per_zone_lowmem_reserve - called whenever 2515 * setup_per_zone_lowmem_reserve - called whenever
2476 * sysctl_lower_zone_reserve_ratio changes. Ensures that each zone 2516 * sysctl_lower_zone_reserve_ratio changes. Ensures that each zone
2477 * has a correct pages reserved value, so an adequate number of 2517 * has a correct pages reserved value, so an adequate number of
@@ -2502,6 +2542,9 @@ static void setup_per_zone_lowmem_reserve(void)
2502 } 2542 }
2503 } 2543 }
2504 } 2544 }
2545
2546 /* update totalreserve_pages */
2547 calculate_totalreserve_pages();
2505} 2548}
2506 2549
2507/* 2550/*
@@ -2556,6 +2599,9 @@ void setup_per_zone_pages_min(void)
2556 zone->pages_high = zone->pages_min + tmp / 2; 2599 zone->pages_high = zone->pages_min + tmp / 2;
2557 spin_unlock_irqrestore(&zone->lru_lock, flags); 2600 spin_unlock_irqrestore(&zone->lru_lock, flags);
2558 } 2601 }
2602
2603 /* update totalreserve_pages */
2604 calculate_totalreserve_pages();
2559} 2605}
2560 2606
2561/* 2607/*