diff options
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 80 |
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; | |||
51 | EXPORT_SYMBOL(node_possible_map); | 51 | EXPORT_SYMBOL(node_possible_map); |
52 | unsigned long totalram_pages __read_mostly; | 52 | unsigned long totalram_pages __read_mostly; |
53 | unsigned long totalhigh_pages __read_mostly; | 53 | unsigned long totalhigh_pages __read_mostly; |
54 | unsigned long totalreserve_pages __read_mostly; | ||
54 | long nr_swap_pages; | 55 | long nr_swap_pages; |
55 | int percpu_pagelist_fraction; | 56 | int 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 | */ |
233 | static inline unsigned long page_order(struct page *page) { | 235 | static inline unsigned long page_order(struct page *page) |
236 | { | ||
234 | return page_private(page); | 237 | return page_private(page); |
235 | } | 238 | } |
236 | 239 | ||
237 | static inline void set_page_order(struct page *page, int order) { | 240 | static 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 | ||
242 | static inline void rmv_page_order(struct page *page) | 246 | static 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 | */ |
289 | static inline int page_is_buddy(struct page *page, int order) | 295 | static 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 | */ | ||
2486 | static 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 | /* |