SLOW_WORK: Fix the CONFIG_MODULES=n case
Commits3d7a641
("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 commit3bde31a
("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>
This commit is contained in:
parent
6f05416432
commit
fa1dae4906
@ -109,6 +109,30 @@ static struct module *slow_work_unreg_module;
|
|||||||
static struct slow_work *slow_work_unreg_work_item;
|
static struct slow_work *slow_work_unreg_work_item;
|
||||||
static DECLARE_WAIT_QUEUE_HEAD(slow_work_unreg_wq);
|
static DECLARE_WAIT_QUEUE_HEAD(slow_work_unreg_wq);
|
||||||
static DEFINE_MUTEX(slow_work_unreg_sync_lock);
|
static DEFINE_MUTEX(slow_work_unreg_sync_lock);
|
||||||
|
|
||||||
|
static void slow_work_set_thread_processing(int id, struct slow_work *work)
|
||||||
|
{
|
||||||
|
if (work)
|
||||||
|
slow_work_thread_processing[id] = work->owner;
|
||||||
|
}
|
||||||
|
static void slow_work_done_thread_processing(int id, struct slow_work *work)
|
||||||
|
{
|
||||||
|
struct module *module = slow_work_thread_processing[id];
|
||||||
|
|
||||||
|
slow_work_thread_processing[id] = NULL;
|
||||||
|
smp_mb();
|
||||||
|
if (slow_work_unreg_work_item == work ||
|
||||||
|
slow_work_unreg_module == module)
|
||||||
|
wake_up_all(&slow_work_unreg_wq);
|
||||||
|
}
|
||||||
|
static void slow_work_clear_thread_processing(int id)
|
||||||
|
{
|
||||||
|
slow_work_thread_processing[id] = NULL;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static void slow_work_set_thread_processing(int id, struct slow_work *work) {}
|
||||||
|
static void slow_work_done_thread_processing(int id, struct slow_work *work) {}
|
||||||
|
static void slow_work_clear_thread_processing(int id) {}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -197,9 +221,6 @@ static unsigned slow_work_calc_vsmax(void)
|
|||||||
*/
|
*/
|
||||||
static noinline bool slow_work_execute(int id)
|
static noinline bool slow_work_execute(int id)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_MODULES
|
|
||||||
struct module *module;
|
|
||||||
#endif
|
|
||||||
struct slow_work *work = NULL;
|
struct slow_work *work = NULL;
|
||||||
unsigned vsmax;
|
unsigned vsmax;
|
||||||
bool very_slow;
|
bool very_slow;
|
||||||
@ -236,10 +257,7 @@ static noinline bool slow_work_execute(int id)
|
|||||||
very_slow = false; /* avoid the compiler warning */
|
very_slow = false; /* avoid the compiler warning */
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_MODULES
|
slow_work_set_thread_processing(id, work);
|
||||||
if (work)
|
|
||||||
slow_work_thread_processing[id] = work->owner;
|
|
||||||
#endif
|
|
||||||
if (work) {
|
if (work) {
|
||||||
slow_work_mark_time(work);
|
slow_work_mark_time(work);
|
||||||
slow_work_begin_exec(id, work);
|
slow_work_begin_exec(id, work);
|
||||||
@ -287,15 +305,7 @@ static noinline bool slow_work_execute(int id)
|
|||||||
|
|
||||||
/* sort out the race between module unloading and put_ref() */
|
/* sort out the race between module unloading and put_ref() */
|
||||||
slow_work_put_ref(work);
|
slow_work_put_ref(work);
|
||||||
|
slow_work_done_thread_processing(id, work);
|
||||||
#ifdef CONFIG_MODULES
|
|
||||||
module = slow_work_thread_processing[id];
|
|
||||||
slow_work_thread_processing[id] = NULL;
|
|
||||||
smp_mb();
|
|
||||||
if (slow_work_unreg_work_item == work ||
|
|
||||||
slow_work_unreg_module == module)
|
|
||||||
wake_up_all(&slow_work_unreg_wq);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -310,7 +320,7 @@ auto_requeue:
|
|||||||
else
|
else
|
||||||
list_add_tail(&work->link, &slow_work_queue);
|
list_add_tail(&work->link, &slow_work_queue);
|
||||||
spin_unlock_irq(&slow_work_queue_lock);
|
spin_unlock_irq(&slow_work_queue_lock);
|
||||||
slow_work_thread_processing[id] = NULL;
|
slow_work_clear_thread_processing(id);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -943,6 +953,7 @@ EXPORT_SYMBOL(slow_work_register_user);
|
|||||||
*/
|
*/
|
||||||
static void slow_work_wait_for_items(struct module *module)
|
static void slow_work_wait_for_items(struct module *module)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_MODULES
|
||||||
DECLARE_WAITQUEUE(myself, current);
|
DECLARE_WAITQUEUE(myself, current);
|
||||||
struct slow_work *work;
|
struct slow_work *work;
|
||||||
int loop;
|
int loop;
|
||||||
@ -989,6 +1000,7 @@ static void slow_work_wait_for_items(struct module *module)
|
|||||||
|
|
||||||
remove_wait_queue(&slow_work_unreg_wq, &myself);
|
remove_wait_queue(&slow_work_unreg_wq, &myself);
|
||||||
mutex_unlock(&slow_work_unreg_sync_lock);
|
mutex_unlock(&slow_work_unreg_sync_lock);
|
||||||
|
#endif /* CONFIG_MODULES */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user