diff options
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r-- | mm/page_alloc.c | 53 |
1 files changed, 38 insertions, 15 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index ef19f22b2b7d..df959b7d6085 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/mm.h> | 18 | #include <linux/mm.h> |
19 | #include <linux/swap.h> | 19 | #include <linux/swap.h> |
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/rwsem.h> | ||
22 | #include <linux/pagemap.h> | 21 | #include <linux/pagemap.h> |
23 | #include <linux/jiffies.h> | 22 | #include <linux/jiffies.h> |
24 | #include <linux/bootmem.h> | 23 | #include <linux/bootmem.h> |
@@ -981,21 +980,21 @@ static void __init __free_pages_boot_core(struct page *page, | |||
981 | 980 | ||
982 | #if defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID) || \ | 981 | #if defined(CONFIG_HAVE_ARCH_EARLY_PFN_TO_NID) || \ |
983 | defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) | 982 | defined(CONFIG_HAVE_MEMBLOCK_NODE_MAP) |
984 | /* Only safe to use early in boot when initialisation is single-threaded */ | 983 | |
985 | static struct mminit_pfnnid_cache early_pfnnid_cache __meminitdata; | 984 | static struct mminit_pfnnid_cache early_pfnnid_cache __meminitdata; |
986 | 985 | ||
987 | int __meminit early_pfn_to_nid(unsigned long pfn) | 986 | int __meminit early_pfn_to_nid(unsigned long pfn) |
988 | { | 987 | { |
988 | static DEFINE_SPINLOCK(early_pfn_lock); | ||
989 | int nid; | 989 | int nid; |
990 | 990 | ||
991 | /* The system will behave unpredictably otherwise */ | 991 | spin_lock(&early_pfn_lock); |
992 | BUG_ON(system_state != SYSTEM_BOOTING); | ||
993 | |||
994 | nid = __early_pfn_to_nid(pfn, &early_pfnnid_cache); | 992 | nid = __early_pfn_to_nid(pfn, &early_pfnnid_cache); |
995 | if (nid >= 0) | 993 | if (nid < 0) |
996 | return nid; | 994 | nid = 0; |
997 | /* just returns 0 */ | 995 | spin_unlock(&early_pfn_lock); |
998 | return 0; | 996 | |
997 | return nid; | ||
999 | } | 998 | } |
1000 | #endif | 999 | #endif |
1001 | 1000 | ||
@@ -1060,7 +1059,15 @@ static void __init deferred_free_range(struct page *page, | |||
1060 | __free_pages_boot_core(page, pfn, 0); | 1059 | __free_pages_boot_core(page, pfn, 0); |
1061 | } | 1060 | } |
1062 | 1061 | ||
1063 | static __initdata DECLARE_RWSEM(pgdat_init_rwsem); | 1062 | /* Completion tracking for deferred_init_memmap() threads */ |
1063 | static atomic_t pgdat_init_n_undone __initdata; | ||
1064 | static __initdata DECLARE_COMPLETION(pgdat_init_all_done_comp); | ||
1065 | |||
1066 | static inline void __init pgdat_init_report_one_done(void) | ||
1067 | { | ||
1068 | if (atomic_dec_and_test(&pgdat_init_n_undone)) | ||
1069 | complete(&pgdat_init_all_done_comp); | ||
1070 | } | ||
1064 | 1071 | ||
1065 | /* Initialise remaining memory on a node */ | 1072 | /* Initialise remaining memory on a node */ |
1066 | static int __init deferred_init_memmap(void *data) | 1073 | static int __init deferred_init_memmap(void *data) |
@@ -1077,7 +1084,7 @@ static int __init deferred_init_memmap(void *data) | |||
1077 | const struct cpumask *cpumask = cpumask_of_node(pgdat->node_id); | 1084 | const struct cpumask *cpumask = cpumask_of_node(pgdat->node_id); |
1078 | 1085 | ||
1079 | if (first_init_pfn == ULONG_MAX) { | 1086 | if (first_init_pfn == ULONG_MAX) { |
1080 | up_read(&pgdat_init_rwsem); | 1087 | pgdat_init_report_one_done(); |
1081 | return 0; | 1088 | return 0; |
1082 | } | 1089 | } |
1083 | 1090 | ||
@@ -1177,7 +1184,8 @@ free_range: | |||
1177 | 1184 | ||
1178 | pr_info("node %d initialised, %lu pages in %ums\n", nid, nr_pages, | 1185 | pr_info("node %d initialised, %lu pages in %ums\n", nid, nr_pages, |
1179 | jiffies_to_msecs(jiffies - start)); | 1186 | jiffies_to_msecs(jiffies - start)); |
1180 | up_read(&pgdat_init_rwsem); | 1187 | |
1188 | pgdat_init_report_one_done(); | ||
1181 | return 0; | 1189 | return 0; |
1182 | } | 1190 | } |
1183 | 1191 | ||
@@ -1185,14 +1193,17 @@ void __init page_alloc_init_late(void) | |||
1185 | { | 1193 | { |
1186 | int nid; | 1194 | int nid; |
1187 | 1195 | ||
1196 | /* There will be num_node_state(N_MEMORY) threads */ | ||
1197 | atomic_set(&pgdat_init_n_undone, num_node_state(N_MEMORY)); | ||
1188 | for_each_node_state(nid, N_MEMORY) { | 1198 | for_each_node_state(nid, N_MEMORY) { |
1189 | down_read(&pgdat_init_rwsem); | ||
1190 | kthread_run(deferred_init_memmap, NODE_DATA(nid), "pgdatinit%d", nid); | 1199 | kthread_run(deferred_init_memmap, NODE_DATA(nid), "pgdatinit%d", nid); |
1191 | } | 1200 | } |
1192 | 1201 | ||
1193 | /* Block until all are initialised */ | 1202 | /* Block until all are initialised */ |
1194 | down_write(&pgdat_init_rwsem); | 1203 | wait_for_completion(&pgdat_init_all_done_comp); |
1195 | up_write(&pgdat_init_rwsem); | 1204 | |
1205 | /* Reinit limits that are based on free pages after the kernel is up */ | ||
1206 | files_maxfiles_init(); | ||
1196 | } | 1207 | } |
1197 | #endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */ | 1208 | #endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */ |
1198 | 1209 | ||
@@ -1285,6 +1296,10 @@ static inline int check_new_page(struct page *page) | |||
1285 | bad_reason = "non-NULL mapping"; | 1296 | bad_reason = "non-NULL mapping"; |
1286 | if (unlikely(atomic_read(&page->_count) != 0)) | 1297 | if (unlikely(atomic_read(&page->_count) != 0)) |
1287 | bad_reason = "nonzero _count"; | 1298 | bad_reason = "nonzero _count"; |
1299 | if (unlikely(page->flags & __PG_HWPOISON)) { | ||
1300 | bad_reason = "HWPoisoned (hardware-corrupted)"; | ||
1301 | bad_flags = __PG_HWPOISON; | ||
1302 | } | ||
1288 | if (unlikely(page->flags & PAGE_FLAGS_CHECK_AT_PREP)) { | 1303 | if (unlikely(page->flags & PAGE_FLAGS_CHECK_AT_PREP)) { |
1289 | bad_reason = "PAGE_FLAGS_CHECK_AT_PREP flag set"; | 1304 | bad_reason = "PAGE_FLAGS_CHECK_AT_PREP flag set"; |
1290 | bad_flags = PAGE_FLAGS_CHECK_AT_PREP; | 1305 | bad_flags = PAGE_FLAGS_CHECK_AT_PREP; |
@@ -5045,6 +5060,10 @@ static unsigned long __meminit zone_spanned_pages_in_node(int nid, | |||
5045 | { | 5060 | { |
5046 | unsigned long zone_start_pfn, zone_end_pfn; | 5061 | unsigned long zone_start_pfn, zone_end_pfn; |
5047 | 5062 | ||
5063 | /* When hotadd a new node, the node should be empty */ | ||
5064 | if (!node_start_pfn && !node_end_pfn) | ||
5065 | return 0; | ||
5066 | |||
5048 | /* Get the start and end of the zone */ | 5067 | /* Get the start and end of the zone */ |
5049 | zone_start_pfn = arch_zone_lowest_possible_pfn[zone_type]; | 5068 | zone_start_pfn = arch_zone_lowest_possible_pfn[zone_type]; |
5050 | zone_end_pfn = arch_zone_highest_possible_pfn[zone_type]; | 5069 | zone_end_pfn = arch_zone_highest_possible_pfn[zone_type]; |
@@ -5108,6 +5127,10 @@ static unsigned long __meminit zone_absent_pages_in_node(int nid, | |||
5108 | unsigned long zone_high = arch_zone_highest_possible_pfn[zone_type]; | 5127 | unsigned long zone_high = arch_zone_highest_possible_pfn[zone_type]; |
5109 | unsigned long zone_start_pfn, zone_end_pfn; | 5128 | unsigned long zone_start_pfn, zone_end_pfn; |
5110 | 5129 | ||
5130 | /* When hotadd a new node, the node should be empty */ | ||
5131 | if (!node_start_pfn && !node_end_pfn) | ||
5132 | return 0; | ||
5133 | |||
5111 | zone_start_pfn = clamp(node_start_pfn, zone_low, zone_high); | 5134 | zone_start_pfn = clamp(node_start_pfn, zone_low, zone_high); |
5112 | zone_end_pfn = clamp(node_end_pfn, zone_low, zone_high); | 5135 | zone_end_pfn = clamp(node_end_pfn, zone_low, zone_high); |
5113 | 5136 | ||