Commit 91e0955b57377578f7555b5d0f2a21040691004b

Authored by Gerard Lledo
Committed by David Woodhouse
1 parent 2c78c44362

jffs2: move jffs2_gcd_mtd threads to the new kthread API

Move the jffs2 garbage collecting thread to the new kthread API.

Signed-off-by: Gerard Lledo <gerard.lledo@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>

Showing 1 changed file with 13 additions and 7 deletions Inline Diff

fs/jffs2/background.c
1 /* 1 /*
2 * JFFS2 -- Journalling Flash File System, Version 2. 2 * JFFS2 -- Journalling Flash File System, Version 2.
3 * 3 *
4 * Copyright © 2001-2007 Red Hat, Inc. 4 * Copyright © 2001-2007 Red Hat, Inc.
5 * 5 *
6 * Created by David Woodhouse <dwmw2@infradead.org> 6 * Created by David Woodhouse <dwmw2@infradead.org>
7 * 7 *
8 * For licensing information, see the file 'LICENCE' in this directory. 8 * For licensing information, see the file 'LICENCE' in this directory.
9 * 9 *
10 */ 10 */
11 11
12 #include <linux/kernel.h> 12 #include <linux/kernel.h>
13 #include <linux/jffs2.h> 13 #include <linux/jffs2.h>
14 #include <linux/mtd/mtd.h> 14 #include <linux/mtd/mtd.h>
15 #include <linux/completion.h> 15 #include <linux/completion.h>
16 #include <linux/sched.h> 16 #include <linux/sched.h>
17 #include <linux/freezer.h> 17 #include <linux/freezer.h>
18 #include <linux/kthread.h>
18 #include "nodelist.h" 19 #include "nodelist.h"
19 20
20 21
21 static int jffs2_garbage_collect_thread(void *); 22 static int jffs2_garbage_collect_thread(void *);
22 23
23 void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c) 24 void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c)
24 { 25 {
25 spin_lock(&c->erase_completion_lock); 26 spin_lock(&c->erase_completion_lock);
26 if (c->gc_task && jffs2_thread_should_wake(c)) 27 if (c->gc_task && jffs2_thread_should_wake(c))
27 send_sig(SIGHUP, c->gc_task, 1); 28 send_sig(SIGHUP, c->gc_task, 1);
28 spin_unlock(&c->erase_completion_lock); 29 spin_unlock(&c->erase_completion_lock);
29 } 30 }
30 31
31 /* This must only ever be called when no GC thread is currently running */ 32 /* This must only ever be called when no GC thread is currently running */
32 int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c) 33 int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c)
33 { 34 {
34 pid_t pid; 35 struct task_struct *tsk;
35 int ret = 0; 36 int ret = 0;
36 37
37 BUG_ON(c->gc_task); 38 BUG_ON(c->gc_task);
38 39
39 init_completion(&c->gc_thread_start); 40 init_completion(&c->gc_thread_start);
40 init_completion(&c->gc_thread_exit); 41 init_completion(&c->gc_thread_exit);
41 42
42 pid = kernel_thread(jffs2_garbage_collect_thread, c, CLONE_FS|CLONE_FILES); 43 tsk = kthread_run(jffs2_garbage_collect_thread, c, "jffs2_gcd_mtd%d", c->mtd->index);
43 if (pid < 0) { 44 if (IS_ERR(tsk)) {
44 printk(KERN_WARNING "fork failed for JFFS2 garbage collect thread: %d\n", -pid); 45 printk(KERN_WARNING "fork failed for JFFS2 garbage collect thread: %ld\n", -PTR_ERR(tsk));
45 complete(&c->gc_thread_exit); 46 complete(&c->gc_thread_exit);
46 ret = pid; 47 ret = PTR_ERR(tsk);
47 } else { 48 } else {
48 /* Wait for it... */ 49 /* Wait for it... */
49 D1(printk(KERN_DEBUG "JFFS2: Garbage collect thread is pid %d\n", pid)); 50 D1(printk(KERN_DEBUG "JFFS2: Garbage collect thread is pid %d\n", tsk->pid));
50 wait_for_completion(&c->gc_thread_start); 51 wait_for_completion(&c->gc_thread_start);
52 ret = tsk->pid;
51 } 53 }
52 54
53 return ret; 55 return ret;
54 } 56 }
55 57
56 void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c) 58 void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c)
57 { 59 {
58 int wait = 0; 60 int wait = 0;
59 spin_lock(&c->erase_completion_lock); 61 spin_lock(&c->erase_completion_lock);
60 if (c->gc_task) { 62 if (c->gc_task) {
61 D1(printk(KERN_DEBUG "jffs2: Killing GC task %d\n", c->gc_task->pid)); 63 D1(printk(KERN_DEBUG "jffs2: Killing GC task %d\n", c->gc_task->pid));
62 send_sig(SIGKILL, c->gc_task, 1); 64 send_sig(SIGKILL, c->gc_task, 1);
63 wait = 1; 65 wait = 1;
64 } 66 }
65 spin_unlock(&c->erase_completion_lock); 67 spin_unlock(&c->erase_completion_lock);
66 if (wait) 68 if (wait)
67 wait_for_completion(&c->gc_thread_exit); 69 wait_for_completion(&c->gc_thread_exit);
68 } 70 }
69 71
70 static int jffs2_garbage_collect_thread(void *_c) 72 static int jffs2_garbage_collect_thread(void *_c)
71 { 73 {
72 struct jffs2_sb_info *c = _c; 74 struct jffs2_sb_info *c = _c;
73 75
74 daemonize("jffs2_gcd_mtd%d", c->mtd->index);
75 allow_signal(SIGKILL); 76 allow_signal(SIGKILL);
76 allow_signal(SIGSTOP); 77 allow_signal(SIGSTOP);
77 allow_signal(SIGCONT); 78 allow_signal(SIGCONT);
78 79
79 c->gc_task = current; 80 c->gc_task = current;
80 complete(&c->gc_thread_start); 81 complete(&c->gc_thread_start);
81 82
82 set_user_nice(current, 10); 83 set_user_nice(current, 10);
83 84
84 set_freezable(); 85 set_freezable();
85 for (;;) { 86 for (;;) {
86 allow_signal(SIGHUP); 87 allow_signal(SIGHUP);
87 again: 88 again:
88 spin_lock(&c->erase_completion_lock); 89 spin_lock(&c->erase_completion_lock);
89 if (!jffs2_thread_should_wake(c)) { 90 if (!jffs2_thread_should_wake(c)) {
90 set_current_state (TASK_INTERRUPTIBLE); 91 set_current_state (TASK_INTERRUPTIBLE);
91 spin_unlock(&c->erase_completion_lock); 92 spin_unlock(&c->erase_completion_lock);
92 D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread sleeping...\n")); 93 D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread sleeping...\n"));
93 schedule(); 94 schedule();
94 } else 95 } else
95 spin_unlock(&c->erase_completion_lock); 96 spin_unlock(&c->erase_completion_lock);
96 97
97 98
98 /* Problem - immediately after bootup, the GCD spends a lot 99 /* Problem - immediately after bootup, the GCD spends a lot
99 * of time in places like jffs2_kill_fragtree(); so much so 100 * of time in places like jffs2_kill_fragtree(); so much so
100 * that userspace processes (like gdm and X) are starved 101 * that userspace processes (like gdm and X) are starved
101 * despite plenty of cond_resched()s and renicing. Yield() 102 * despite plenty of cond_resched()s and renicing. Yield()
102 * doesn't help, either (presumably because userspace and GCD 103 * doesn't help, either (presumably because userspace and GCD
103 * are generally competing for a higher latency resource - 104 * are generally competing for a higher latency resource -
104 * disk). 105 * disk).
105 * This forces the GCD to slow the hell down. Pulling an 106 * This forces the GCD to slow the hell down. Pulling an
106 * inode in with read_inode() is much preferable to having 107 * inode in with read_inode() is much preferable to having
107 * the GC thread get there first. */ 108 * the GC thread get there first. */
108 schedule_timeout_interruptible(msecs_to_jiffies(50)); 109 schedule_timeout_interruptible(msecs_to_jiffies(50));
110
111 if (kthread_should_stop()) {
112 D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): kthread_stop() called.\n"));
113 goto die;
114 }
109 115
110 /* Put_super will send a SIGKILL and then wait on the sem. 116 /* Put_super will send a SIGKILL and then wait on the sem.
111 */ 117 */
112 while (signal_pending(current) || freezing(current)) { 118 while (signal_pending(current) || freezing(current)) {
113 siginfo_t info; 119 siginfo_t info;
114 unsigned long signr; 120 unsigned long signr;
115 121
116 if (try_to_freeze()) 122 if (try_to_freeze())
117 goto again; 123 goto again;
118 124
119 signr = dequeue_signal_lock(current, &current->blocked, &info); 125 signr = dequeue_signal_lock(current, &current->blocked, &info);
120 126
121 switch(signr) { 127 switch(signr) {
122 case SIGSTOP: 128 case SIGSTOP:
123 D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): SIGSTOP received.\n")); 129 D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): SIGSTOP received.\n"));
124 set_current_state(TASK_STOPPED); 130 set_current_state(TASK_STOPPED);
125 schedule(); 131 schedule();
126 break; 132 break;
127 133
128 case SIGKILL: 134 case SIGKILL:
129 D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): SIGKILL received.\n")); 135 D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): SIGKILL received.\n"));
130 goto die; 136 goto die;
131 137
132 case SIGHUP: 138 case SIGHUP:
133 D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): SIGHUP received.\n")); 139 D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): SIGHUP received.\n"));
134 break; 140 break;
135 default: 141 default:
136 D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): signal %ld received\n", signr)); 142 D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): signal %ld received\n", signr));
137 } 143 }
138 } 144 }
139 /* We don't want SIGHUP to interrupt us. STOP and KILL are OK though. */ 145 /* We don't want SIGHUP to interrupt us. STOP and KILL are OK though. */
140 disallow_signal(SIGHUP); 146 disallow_signal(SIGHUP);
141 147
142 D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): pass\n")); 148 D1(printk(KERN_DEBUG "jffs2_garbage_collect_thread(): pass\n"));
143 if (jffs2_garbage_collect_pass(c) == -ENOSPC) { 149 if (jffs2_garbage_collect_pass(c) == -ENOSPC) {
144 printk(KERN_NOTICE "No space for garbage collection. Aborting GC thread\n"); 150 printk(KERN_NOTICE "No space for garbage collection. Aborting GC thread\n");
145 goto die; 151 goto die;
146 } 152 }
147 } 153 }
148 die: 154 die:
149 spin_lock(&c->erase_completion_lock); 155 spin_lock(&c->erase_completion_lock);
150 c->gc_task = NULL; 156 c->gc_task = NULL;
151 spin_unlock(&c->erase_completion_lock); 157 spin_unlock(&c->erase_completion_lock);
152 complete_and_exit(&c->gc_thread_exit, 0); 158 complete_and_exit(&c->gc_thread_exit, 0);
153 } 159 }