summaryrefslogtreecommitdiffstats
path: root/mm/page_alloc.c
diff options
context:
space:
mode:
authorNicolai Stange <nicstange@gmail.com>2015-08-06 18:46:16 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2015-08-06 21:39:40 -0400
commitd3cd131d935ab3bab700491edbbd7cad4040ce50 (patch)
tree50d9755ae9dfbb3105761b3f87e37fe9454d7a1b /mm/page_alloc.c
parent7ace99170789bc53cbb7e9e352d7a3851208fbcf (diff)
mm, meminit: replace rwsem with completion
Commit 0e1cc95b4cc7 ("mm: meminit: finish initialisation of struct pages before basic setup") introduced a rwsem to signal completion of the initialization workers. Lockdep complains about possible recursive locking: ============================================= [ INFO: possible recursive locking detected ] 4.1.0-12802-g1dc51b8 #3 Not tainted --------------------------------------------- swapper/0/1 is trying to acquire lock: (pgdat_init_rwsem){++++.+}, at: [<ffffffff8424c7fb>] page_alloc_init_late+0xc7/0xe6 but task is already holding lock: (pgdat_init_rwsem){++++.+}, at: [<ffffffff8424c772>] page_alloc_init_late+0x3e/0xe6 Replace the rwsem by a completion together with an atomic "outstanding work counter". [peterz@infradead.org: Barrier removal on the grounds of being pointless] [mgorman@suse.de: Applied review feedback] Signed-off-by: Nicolai Stange <nicstange@gmail.com> Signed-off-by: Mel Gorman <mgorman@suse.de> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Cc: Dave Hansen <dave.hansen@intel.com> Cc: Alex Ng <alexng@microsoft.com> Cc: Fengguang Wu <fengguang.wu@intel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/page_alloc.c')
-rw-r--r--mm/page_alloc.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index ea0e6a6e7a11..322628278ae4 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>
@@ -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
1063static __initdata DECLARE_RWSEM(pgdat_init_rwsem); 1062/* Completion tracking for deferred_init_memmap() threads */
1063static atomic_t pgdat_init_n_undone __initdata;
1064static __initdata DECLARE_COMPLETION(pgdat_init_all_done_comp);
1065
1066static 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 */
1066static int __init deferred_init_memmap(void *data) 1073static 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,14 @@ 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);
1196} 1204}
1197#endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */ 1205#endif /* CONFIG_DEFERRED_STRUCT_PAGE_INIT */
1198 1206