diff options
-rw-r--r-- | include/linux/mm.h | 6 | ||||
-rw-r--r-- | include/linux/mmzone.h | 14 | ||||
-rw-r--r-- | mm/page_alloc.c | 11 |
3 files changed, 23 insertions, 8 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h index 083cc0ba2384..4310f80ce956 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -1313,6 +1313,7 @@ extern void free_initmem(void); | |||
1313 | */ | 1313 | */ |
1314 | extern unsigned long free_reserved_area(void *start, void *end, | 1314 | extern unsigned long free_reserved_area(void *start, void *end, |
1315 | int poison, char *s); | 1315 | int poison, char *s); |
1316 | |||
1316 | #ifdef CONFIG_HIGHMEM | 1317 | #ifdef CONFIG_HIGHMEM |
1317 | /* | 1318 | /* |
1318 | * Free a highmem page into the buddy system, adjusting totalhigh_pages | 1319 | * Free a highmem page into the buddy system, adjusting totalhigh_pages |
@@ -1321,10 +1322,7 @@ extern unsigned long free_reserved_area(void *start, void *end, | |||
1321 | extern void free_highmem_page(struct page *page); | 1322 | extern void free_highmem_page(struct page *page); |
1322 | #endif | 1323 | #endif |
1323 | 1324 | ||
1324 | static inline void adjust_managed_page_count(struct page *page, long count) | 1325 | extern void adjust_managed_page_count(struct page *page, long count); |
1325 | { | ||
1326 | totalram_pages += count; | ||
1327 | } | ||
1328 | 1326 | ||
1329 | /* Free the reserved page into the buddy system, so it gets managed. */ | 1327 | /* Free the reserved page into the buddy system, so it gets managed. */ |
1330 | static inline void __free_reserved_page(struct page *page) | 1328 | static inline void __free_reserved_page(struct page *page) |
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index e511f9429f1e..09d381b71fd8 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h | |||
@@ -474,10 +474,16 @@ struct zone { | |||
474 | * frequently read in proximity to zone->lock. It's good to | 474 | * frequently read in proximity to zone->lock. It's good to |
475 | * give them a chance of being in the same cacheline. | 475 | * give them a chance of being in the same cacheline. |
476 | * | 476 | * |
477 | * Write access to present_pages and managed_pages at runtime should | 477 | * Write access to present_pages at runtime should be protected by |
478 | * be protected by lock_memory_hotplug()/unlock_memory_hotplug(). | 478 | * lock_memory_hotplug()/unlock_memory_hotplug(). Any reader who can't |
479 | * Any reader who can't tolerant drift of present_pages and | 479 | * tolerant drift of present_pages should hold memory hotplug lock to |
480 | * managed_pages should hold memory hotplug lock to get a stable value. | 480 | * get a stable value. |
481 | * | ||
482 | * Read access to managed_pages should be safe because it's unsigned | ||
483 | * long. Write access to zone->managed_pages and totalram_pages are | ||
484 | * protected by managed_page_count_lock at runtime. Idealy only | ||
485 | * adjust_managed_page_count() should be used instead of directly | ||
486 | * touching zone->managed_pages and totalram_pages. | ||
481 | */ | 487 | */ |
482 | unsigned long spanned_pages; | 488 | unsigned long spanned_pages; |
483 | unsigned long present_pages; | 489 | unsigned long present_pages; |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 22438eba00b6..93f292a60cb0 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -103,6 +103,9 @@ nodemask_t node_states[NR_NODE_STATES] __read_mostly = { | |||
103 | }; | 103 | }; |
104 | EXPORT_SYMBOL(node_states); | 104 | EXPORT_SYMBOL(node_states); |
105 | 105 | ||
106 | /* Protect totalram_pages and zone->managed_pages */ | ||
107 | static DEFINE_SPINLOCK(managed_page_count_lock); | ||
108 | |||
106 | unsigned long totalram_pages __read_mostly; | 109 | unsigned long totalram_pages __read_mostly; |
107 | unsigned long totalreserve_pages __read_mostly; | 110 | unsigned long totalreserve_pages __read_mostly; |
108 | /* | 111 | /* |
@@ -5206,6 +5209,14 @@ early_param("movablecore", cmdline_parse_movablecore); | |||
5206 | 5209 | ||
5207 | #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ | 5210 | #endif /* CONFIG_HAVE_MEMBLOCK_NODE_MAP */ |
5208 | 5211 | ||
5212 | void adjust_managed_page_count(struct page *page, long count) | ||
5213 | { | ||
5214 | spin_lock(&managed_page_count_lock); | ||
5215 | page_zone(page)->managed_pages += count; | ||
5216 | totalram_pages += count; | ||
5217 | spin_unlock(&managed_page_count_lock); | ||
5218 | } | ||
5219 | |||
5209 | unsigned long free_reserved_area(void *start, void *end, int poison, char *s) | 5220 | unsigned long free_reserved_area(void *start, void *end, int poison, char *s) |
5210 | { | 5221 | { |
5211 | void *pos; | 5222 | void *pos; |