aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2009-12-01 08:52:08 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-01 10:35:11 -0500
commitfa1dae4906982b5d896c07613b1fe42456133b1c (patch)
tree027dec5baeedbe25a7b645311b530a06d78b36f3
parent6f054164322bc6c1233402b9ed6b40d4af39a98f (diff)
SLOW_WORK: Fix the CONFIG_MODULES=n case
Commits 3d7a641 ("SLOW_WORK: Wait for outstanding work items belonging to a module to clear") introduced some code to make sure that all of a module's slow-work items were complete before that module was removed, and commit 3bde31a ("SLOW_WORK: Allow a requeueable work item to sleep till the thread is needed") further extended that, breaking it in the process if CONFIG_MODULES=n: CC kernel/slow-work.o kernel/slow-work.c: In function 'slow_work_execute': kernel/slow-work.c:313: error: 'slow_work_thread_processing' undeclared (first use in this function) kernel/slow-work.c:313: error: (Each undeclared identifier is reported only once kernel/slow-work.c:313: error: for each function it appears in.) kernel/slow-work.c: In function 'slow_work_wait_for_items': kernel/slow-work.c:950: error: 'slow_work_unreg_sync_lock' undeclared (first use in this function) kernel/slow-work.c:951: error: 'slow_work_unreg_wq' undeclared (first use in this function) kernel/slow-work.c:961: error: 'slow_work_unreg_work_item' undeclared (first use in this function) kernel/slow-work.c:974: error: 'slow_work_unreg_module' undeclared (first use in this function) kernel/slow-work.c:977: error: 'slow_work_thread_processing' undeclared (first use in this function) make[1]: *** [kernel/slow-work.o] Error 1 Fix this by: (1) Extracting the bits of slow_work_execute() that are contingent on CONFIG_MODULES, and the bits that should be, into inline functions and placing them into the #ifdef'd section that defines the relevant variables and adding stubs for moduleless kernels. This allows the removal of some #ifdefs. (2) #ifdef'ing out the contents of slow_work_wait_for_items() in moduleless kernels. The four functions related to handling module unloading synchronisation (and their associated variables) could be offloaded into a separate .c file, but each function is only used once and three of them are tiny, so doing so would prevent them from being inlined. Reported-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--kernel/slow-work.c46
1 files changed, 29 insertions, 17 deletions
diff --git a/kernel/slow-work.c b/kernel/slow-work.c
index da94f3c101af..b5c17f15f9de 100644
--- a/kernel/slow-work.c
+++ b/kernel/slow-work.c
@@ -109,6 +109,30 @@ static struct module *slow_work_unreg_module;
109static struct slow_work *slow_work_unreg_work_item; 109static struct slow_work *slow_work_unreg_work_item;
110static DECLARE_WAIT_QUEUE_HEAD(slow_work_unreg_wq); 110static DECLARE_WAIT_QUEUE_HEAD(slow_work_unreg_wq);
111static DEFINE_MUTEX(slow_work_unreg_sync_lock); 111static DEFINE_MUTEX(slow_work_unreg_sync_lock);
112
113static void slow_work_set_thread_processing(int id, struct slow_work *work)
114{
115 if (work)
116 slow_work_thread_processing[id] = work->owner;
117}
118static void slow_work_done_thread_processing(int id, struct slow_work *work)
119{
120 struct module *module = slow_work_thread_processing[id];
121
122 slow_work_thread_processing[id] = NULL;
123 smp_mb();
124 if (slow_work_unreg_work_item == work ||
125 slow_work_unreg_module == module)
126 wake_up_all(&slow_work_unreg_wq);
127}
128static void slow_work_clear_thread_processing(int id)
129{
130 slow_work_thread_processing[id] = NULL;
131}
132#else
133static void slow_work_set_thread_processing(int id, struct slow_work *work) {}
134static void slow_work_done_thread_processing(int id, struct slow_work *work) {}
135static void slow_work_clear_thread_processing(int id) {}
112#endif 136#endif
113 137
114/* 138/*
@@ -197,9 +221,6 @@ static unsigned slow_work_calc_vsmax(void)
197 */ 221 */
198static noinline bool slow_work_execute(int id) 222static noinline bool slow_work_execute(int id)
199{ 223{
200#ifdef CONFIG_MODULES
201 struct module *module;
202#endif
203 struct slow_work *work = NULL; 224 struct slow_work *work = NULL;
204 unsigned vsmax; 225 unsigned vsmax;
205 bool very_slow; 226 bool very_slow;
@@ -236,10 +257,7 @@ static noinline bool slow_work_execute(int id)
236 very_slow = false; /* avoid the compiler warning */ 257 very_slow = false; /* avoid the compiler warning */
237 } 258 }
238 259
239#ifdef CONFIG_MODULES 260 slow_work_set_thread_processing(id, work);
240 if (work)
241 slow_work_thread_processing[id] = work->owner;
242#endif
243 if (work) { 261 if (work) {
244 slow_work_mark_time(work); 262 slow_work_mark_time(work);
245 slow_work_begin_exec(id, work); 263 slow_work_begin_exec(id, work);
@@ -287,15 +305,7 @@ static noinline bool slow_work_execute(int id)
287 305
288 /* sort out the race between module unloading and put_ref() */ 306 /* sort out the race between module unloading and put_ref() */
289 slow_work_put_ref(work); 307 slow_work_put_ref(work);
290 308 slow_work_done_thread_processing(id, work);
291#ifdef CONFIG_MODULES
292 module = slow_work_thread_processing[id];
293 slow_work_thread_processing[id] = NULL;
294 smp_mb();
295 if (slow_work_unreg_work_item == work ||
296 slow_work_unreg_module == module)
297 wake_up_all(&slow_work_unreg_wq);
298#endif
299 309
300 return true; 310 return true;
301 311
@@ -310,7 +320,7 @@ auto_requeue:
310 else 320 else
311 list_add_tail(&work->link, &slow_work_queue); 321 list_add_tail(&work->link, &slow_work_queue);
312 spin_unlock_irq(&slow_work_queue_lock); 322 spin_unlock_irq(&slow_work_queue_lock);
313 slow_work_thread_processing[id] = NULL; 323 slow_work_clear_thread_processing(id);
314 return true; 324 return true;
315} 325}
316 326
@@ -943,6 +953,7 @@ EXPORT_SYMBOL(slow_work_register_user);
943 */ 953 */
944static void slow_work_wait_for_items(struct module *module) 954static void slow_work_wait_for_items(struct module *module)
945{ 955{
956#ifdef CONFIG_MODULES
946 DECLARE_WAITQUEUE(myself, current); 957 DECLARE_WAITQUEUE(myself, current);
947 struct slow_work *work; 958 struct slow_work *work;
948 int loop; 959 int loop;
@@ -989,6 +1000,7 @@ static void slow_work_wait_for_items(struct module *module)
989 1000
990 remove_wait_queue(&slow_work_unreg_wq, &myself); 1001 remove_wait_queue(&slow_work_unreg_wq, &myself);
991 mutex_unlock(&slow_work_unreg_sync_lock); 1002 mutex_unlock(&slow_work_unreg_sync_lock);
1003#endif /* CONFIG_MODULES */
992} 1004}
993 1005
994/** 1006/**