Blame view
fs/jffs2/background.c
4.24 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 |
/* * JFFS2 -- Journalling Flash File System, Version 2. * |
c00c310ea [JFFS2] Tidy up l... |
4 |
* Copyright © 2001-2007 Red Hat, Inc. |
6088c0587 jffs2: Update cop... |
5 |
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> |
1da177e4c Linux-2.6.12-rc2 |
6 7 8 9 10 |
* * Created by David Woodhouse <dwmw2@infradead.org> * * For licensing information, see the file 'LICENCE' in this directory. * |
1da177e4c Linux-2.6.12-rc2 |
11 |
*/ |
5a528957e jffs2: Use pr_fmt... |
12 |
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
1da177e4c Linux-2.6.12-rc2 |
13 14 15 16 |
#include <linux/kernel.h> #include <linux/jffs2.h> #include <linux/mtd/mtd.h> #include <linux/completion.h> |
3f07c0144 sched/headers: Pr... |
17 |
#include <linux/sched/signal.h> |
7dfb71030 [PATCH] Add inclu... |
18 |
#include <linux/freezer.h> |
91e0955b5 jffs2: move jffs2... |
19 |
#include <linux/kthread.h> |
1da177e4c Linux-2.6.12-rc2 |
20 21 22 23 24 25 26 |
#include "nodelist.h" static int jffs2_garbage_collect_thread(void *); void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c) { |
acb64a43e jffs2: Require jf... |
27 |
assert_spin_locked(&c->erase_completion_lock); |
ef53cb02f [JFFS2] Whitespac... |
28 29 |
if (c->gc_task && jffs2_thread_should_wake(c)) send_sig(SIGHUP, c->gc_task, 1); |
1da177e4c Linux-2.6.12-rc2 |
30 31 32 33 34 |
} /* This must only ever be called when no GC thread is currently running */ int jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c) { |
91e0955b5 jffs2: move jffs2... |
35 |
struct task_struct *tsk; |
1da177e4c Linux-2.6.12-rc2 |
36 |
int ret = 0; |
4b4d1cc73 BUG_ON() Conversi... |
37 |
BUG_ON(c->gc_task); |
1da177e4c Linux-2.6.12-rc2 |
38 |
|
fff7afd79 [JFFS2] Convert t... |
39 |
init_completion(&c->gc_thread_start); |
1da177e4c Linux-2.6.12-rc2 |
40 |
init_completion(&c->gc_thread_exit); |
91e0955b5 jffs2: move jffs2... |
41 42 |
tsk = kthread_run(jffs2_garbage_collect_thread, c, "jffs2_gcd_mtd%d", c->mtd->index); if (IS_ERR(tsk)) { |
da320f055 jffs2: Convert pr... |
43 44 45 |
pr_warn("fork failed for JFFS2 garbage collect thread: %ld ", -PTR_ERR(tsk)); |
1da177e4c Linux-2.6.12-rc2 |
46 |
complete(&c->gc_thread_exit); |
91e0955b5 jffs2: move jffs2... |
47 |
ret = PTR_ERR(tsk); |
1da177e4c Linux-2.6.12-rc2 |
48 49 |
} else { /* Wait for it... */ |
5a528957e jffs2: Use pr_fmt... |
50 51 |
jffs2_dbg(1, "Garbage collect thread is pid %d ", tsk->pid); |
fff7afd79 [JFFS2] Convert t... |
52 |
wait_for_completion(&c->gc_thread_start); |
91e0955b5 jffs2: move jffs2... |
53 |
ret = tsk->pid; |
1da177e4c Linux-2.6.12-rc2 |
54 |
} |
182ec4eee [JFFS2] Clean up ... |
55 |
|
1da177e4c Linux-2.6.12-rc2 |
56 57 58 59 60 |
return ret; } void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c) { |
e2d48b1a9 [JFFS2] Fix clean... |
61 |
int wait = 0; |
1da177e4c Linux-2.6.12-rc2 |
62 63 |
spin_lock(&c->erase_completion_lock); if (c->gc_task) { |
5a528957e jffs2: Use pr_fmt... |
64 65 |
jffs2_dbg(1, "Killing GC task %d ", c->gc_task->pid); |
1da177e4c Linux-2.6.12-rc2 |
66 |
send_sig(SIGKILL, c->gc_task, 1); |
e2d48b1a9 [JFFS2] Fix clean... |
67 |
wait = 1; |
1da177e4c Linux-2.6.12-rc2 |
68 69 |
} spin_unlock(&c->erase_completion_lock); |
e2d48b1a9 [JFFS2] Fix clean... |
70 71 |
if (wait) wait_for_completion(&c->gc_thread_exit); |
1da177e4c Linux-2.6.12-rc2 |
72 73 74 75 76 |
} static int jffs2_garbage_collect_thread(void *_c) { struct jffs2_sb_info *c = _c; |
c240837fa signals: jffs2: f... |
77 |
sigset_t hupmask; |
1da177e4c Linux-2.6.12-rc2 |
78 |
|
c240837fa signals: jffs2: f... |
79 |
siginitset(&hupmask, sigmask(SIGHUP)); |
1da177e4c Linux-2.6.12-rc2 |
80 81 |
allow_signal(SIGKILL); allow_signal(SIGSTOP); |
c240837fa signals: jffs2: f... |
82 |
allow_signal(SIGHUP); |
1da177e4c Linux-2.6.12-rc2 |
83 84 |
c->gc_task = current; |
fff7afd79 [JFFS2] Convert t... |
85 |
complete(&c->gc_thread_start); |
1da177e4c Linux-2.6.12-rc2 |
86 87 |
set_user_nice(current, 10); |
831441862 Freezer: make ker... |
88 |
set_freezable(); |
1da177e4c Linux-2.6.12-rc2 |
89 |
for (;;) { |
c240837fa signals: jffs2: f... |
90 |
sigprocmask(SIG_UNBLOCK, &hupmask, NULL); |
e716dd364 [JFFS2] Fix suspe... |
91 |
again: |
b27cf88e9 [JFFS2] Fix lack ... |
92 |
spin_lock(&c->erase_completion_lock); |
1da177e4c Linux-2.6.12-rc2 |
93 94 |
if (!jffs2_thread_should_wake(c)) { set_current_state (TASK_INTERRUPTIBLE); |
b27cf88e9 [JFFS2] Fix lack ... |
95 |
spin_unlock(&c->erase_completion_lock); |
9c261b33a jffs2: Convert mo... |
96 97 |
jffs2_dbg(1, "%s(): sleeping... ", __func__); |
1da177e4c Linux-2.6.12-rc2 |
98 |
schedule(); |
c240837fa signals: jffs2: f... |
99 |
} else { |
b27cf88e9 [JFFS2] Fix lack ... |
100 |
spin_unlock(&c->erase_completion_lock); |
c240837fa signals: jffs2: f... |
101 |
} |
efab0b5d3 [JFFS2] force the... |
102 103 104 105 106 107 108 109 110 111 112 |
/* Problem - immediately after bootup, the GCD spends a lot * of time in places like jffs2_kill_fragtree(); so much so * that userspace processes (like gdm and X) are starved * despite plenty of cond_resched()s and renicing. Yield() * doesn't help, either (presumably because userspace and GCD * are generally competing for a higher latency resource - * disk). * This forces the GCD to slow the hell down. Pulling an * inode in with read_inode() is much preferable to having * the GC thread get there first. */ schedule_timeout_interruptible(msecs_to_jiffies(50)); |
1da177e4c Linux-2.6.12-rc2 |
113 |
|
91e0955b5 jffs2: move jffs2... |
114 |
if (kthread_should_stop()) { |
9c261b33a jffs2: Convert mo... |
115 116 |
jffs2_dbg(1, "%s(): kthread_stop() called ", __func__); |
91e0955b5 jffs2: move jffs2... |
117 118 |
goto die; } |
182ec4eee [JFFS2] Clean up ... |
119 |
/* Put_super will send a SIGKILL and then wait on the sem. |
1da177e4c Linux-2.6.12-rc2 |
120 |
*/ |
e136e769d Freezer: Fix JFFS... |
121 |
while (signal_pending(current) || freezing(current)) { |
1da177e4c Linux-2.6.12-rc2 |
122 |
unsigned long signr; |
e716dd364 [JFFS2] Fix suspe... |
123 124 |
if (try_to_freeze()) goto again; |
be0e6f290 signal: turn dequ... |
125 |
signr = kernel_dequeue_signal(NULL); |
1da177e4c Linux-2.6.12-rc2 |
126 127 128 |
switch(signr) { case SIGSTOP: |
9c261b33a jffs2: Convert mo... |
129 130 131 |
jffs2_dbg(1, "%s(): SIGSTOP received ", __func__); |
9a13049e8 signal: introduce... |
132 |
kernel_signal_stop(); |
1da177e4c Linux-2.6.12-rc2 |
133 134 135 |
break; case SIGKILL: |
9c261b33a jffs2: Convert mo... |
136 137 138 |
jffs2_dbg(1, "%s(): SIGKILL received ", __func__); |
1da177e4c Linux-2.6.12-rc2 |
139 140 141 |
goto die; case SIGHUP: |
9c261b33a jffs2: Convert mo... |
142 143 144 |
jffs2_dbg(1, "%s(): SIGHUP received ", __func__); |
1da177e4c Linux-2.6.12-rc2 |
145 146 |
break; default: |
9c261b33a jffs2: Convert mo... |
147 148 149 |
jffs2_dbg(1, "%s(): signal %ld received ", __func__, signr); |
1da177e4c Linux-2.6.12-rc2 |
150 151 152 |
} } /* We don't want SIGHUP to interrupt us. STOP and KILL are OK though. */ |
c240837fa signals: jffs2: f... |
153 |
sigprocmask(SIG_BLOCK, &hupmask, NULL); |
1da177e4c Linux-2.6.12-rc2 |
154 |
|
9c261b33a jffs2: Convert mo... |
155 156 |
jffs2_dbg(1, "%s(): pass ", __func__); |
1da177e4c Linux-2.6.12-rc2 |
157 |
if (jffs2_garbage_collect_pass(c) == -ENOSPC) { |
da320f055 jffs2: Convert pr... |
158 159 |
pr_notice("No space for garbage collection. Aborting GC thread "); |
1da177e4c Linux-2.6.12-rc2 |
160 161 162 163 164 165 166 167 168 |
goto die; } } die: spin_lock(&c->erase_completion_lock); c->gc_task = NULL; spin_unlock(&c->erase_completion_lock); complete_and_exit(&c->gc_thread_exit, 0); } |