aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/mm/cmm.c
diff options
context:
space:
mode:
authorHeiko Carstens <heiko.carstens@de.ibm.com>2006-09-26 02:33:11 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2006-09-26 11:49:11 -0400
commite8216dee838c09776680a6f1a2e54d81f3cdfa14 (patch)
treea342f566fb564344911998088a6de92227a932dc /arch/s390/mm/cmm.c
parente8df8c3304cfc7d68e9a6a7b6df6c64783cd6991 (diff)
[PATCH] s390: fix cmm kernel thread handling
Convert cmm's usage of kernel_thread to kthread_run. Also create the cmmthread at module load time, so it is possible to check if creation of the thread fails. In addition the cmmthread now gets terminated when the module gets unloaded instead of leaving a stale kernel thread. Also check the return values of other registration functions at module load and handle their return values appropriately. Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> Signed-off-by: Heiko Carstens <heiko.carstens@de.ibm.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch/s390/mm/cmm.c')
-rw-r--r--arch/s390/mm/cmm.c54
1 files changed, 35 insertions, 19 deletions
diff --git a/arch/s390/mm/cmm.c b/arch/s390/mm/cmm.c
index f2e00df99bae..607f50ead1fd 100644
--- a/arch/s390/mm/cmm.c
+++ b/arch/s390/mm/cmm.c
@@ -16,6 +16,7 @@
16#include <linux/sysctl.h> 16#include <linux/sysctl.h>
17#include <linux/ctype.h> 17#include <linux/ctype.h>
18#include <linux/swap.h> 18#include <linux/swap.h>
19#include <linux/kthread.h>
19 20
20#include <asm/pgalloc.h> 21#include <asm/pgalloc.h>
21#include <asm/uaccess.h> 22#include <asm/uaccess.h>
@@ -46,8 +47,7 @@ static struct cmm_page_array *cmm_page_list;
46static struct cmm_page_array *cmm_timed_page_list; 47static struct cmm_page_array *cmm_timed_page_list;
47static DEFINE_SPINLOCK(cmm_lock); 48static DEFINE_SPINLOCK(cmm_lock);
48 49
49static unsigned long cmm_thread_active; 50static struct task_struct *cmm_thread_ptr;
50static struct work_struct cmm_thread_starter;
51static wait_queue_head_t cmm_thread_wait; 51static wait_queue_head_t cmm_thread_wait;
52static struct timer_list cmm_timer; 52static struct timer_list cmm_timer;
53 53
@@ -143,14 +143,12 @@ cmm_thread(void *dummy)
143{ 143{
144 int rc; 144 int rc;
145 145
146 daemonize("cmmthread");
147 while (1) { 146 while (1) {
148 rc = wait_event_interruptible(cmm_thread_wait, 147 rc = wait_event_interruptible(cmm_thread_wait,
149 (cmm_pages != cmm_pages_target || 148 (cmm_pages != cmm_pages_target ||
150 cmm_timed_pages != cmm_timed_pages_target)); 149 cmm_timed_pages != cmm_timed_pages_target ||
151 if (rc == -ERESTARTSYS) { 150 kthread_should_stop()));
152 /* Got kill signal. End thread. */ 151 if (kthread_should_stop() || rc == -ERESTARTSYS) {
153 clear_bit(0, &cmm_thread_active);
154 cmm_pages_target = cmm_pages; 152 cmm_pages_target = cmm_pages;
155 cmm_timed_pages_target = cmm_timed_pages; 153 cmm_timed_pages_target = cmm_timed_pages;
156 break; 154 break;
@@ -176,16 +174,8 @@ cmm_thread(void *dummy)
176} 174}
177 175
178static void 176static void
179cmm_start_thread(void)
180{
181 kernel_thread(cmm_thread, NULL, 0);
182}
183
184static void
185cmm_kick_thread(void) 177cmm_kick_thread(void)
186{ 178{
187 if (!test_and_set_bit(0, &cmm_thread_active))
188 schedule_work(&cmm_thread_starter);
189 wake_up(&cmm_thread_wait); 179 wake_up(&cmm_thread_wait);
190} 180}
191 181
@@ -429,22 +419,48 @@ struct ctl_table_header *cmm_sysctl_header;
429static int 419static int
430cmm_init (void) 420cmm_init (void)
431{ 421{
422 int rc = -ENOMEM;
423
432#ifdef CONFIG_CMM_PROC 424#ifdef CONFIG_CMM_PROC
433 cmm_sysctl_header = register_sysctl_table(cmm_dir_table, 1); 425 cmm_sysctl_header = register_sysctl_table(cmm_dir_table, 1);
426 if (!cmm_sysctl_header)
427 goto out;
434#endif 428#endif
435#ifdef CONFIG_CMM_IUCV 429#ifdef CONFIG_CMM_IUCV
436 smsg_register_callback(SMSG_PREFIX, cmm_smsg_target); 430 rc = smsg_register_callback(SMSG_PREFIX, cmm_smsg_target);
431 if (rc < 0)
432 goto out_smsg;
437#endif 433#endif
438 register_oom_notifier(&cmm_oom_nb); 434 rc = register_oom_notifier(&cmm_oom_nb);
439 INIT_WORK(&cmm_thread_starter, (void *) cmm_start_thread, NULL); 435 if (rc < 0)
436 goto out_oom_notify;
440 init_waitqueue_head(&cmm_thread_wait); 437 init_waitqueue_head(&cmm_thread_wait);
441 init_timer(&cmm_timer); 438 init_timer(&cmm_timer);
442 return 0; 439 cmm_thread_ptr = kthread_run(cmm_thread, NULL, "cmmthread");
440 rc = IS_ERR(cmm_thread_ptr) ? PTR_ERR(cmm_thread_ptr) : 0;
441 if (!rc)
442 goto out;
443 /*
444 * kthread_create failed. undo all the stuff from above again.
445 */
446 unregister_oom_notifier(&cmm_oom_nb);
447
448out_oom_notify:
449#ifdef CONFIG_CMM_IUCV
450 smsg_unregister_callback(SMSG_PREFIX, cmm_smsg_target);
451out_smsg:
452#endif
453#ifdef CONFIG_CMM_PROC
454 unregister_sysctl_table(cmm_sysctl_header);
455#endif
456out:
457 return rc;
443} 458}
444 459
445static void 460static void
446cmm_exit(void) 461cmm_exit(void)
447{ 462{
463 kthread_stop(cmm_thread_ptr);
448 unregister_oom_notifier(&cmm_oom_nb); 464 unregister_oom_notifier(&cmm_oom_nb);
449 cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list); 465 cmm_free_pages(cmm_pages, &cmm_pages, &cmm_page_list);
450 cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list); 466 cmm_free_pages(cmm_timed_pages, &cmm_timed_pages, &cmm_timed_page_list);