Blame view

fs/jffs2/background.c 4.24 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
  /*
   * JFFS2 -- Journalling Flash File System, Version 2.
   *
c00c310ea   David Woodhouse   [JFFS2] Tidy up l...
4
   * Copyright © 2001-2007 Red Hat, Inc.
6088c0587   David Woodhouse   jffs2: Update cop...
5
   * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
1da177e4c   Linus Torvalds   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   Linus Torvalds   Linux-2.6.12-rc2
11
   */
5a528957e   Joe Perches   jffs2: Use pr_fmt...
12
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
1da177e4c   Linus Torvalds   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   Ingo Molnar   sched/headers: Pr...
17
  #include <linux/sched/signal.h>
7dfb71030   Nigel Cunningham   [PATCH] Add inclu...
18
  #include <linux/freezer.h>
91e0955b5   Gerard Lledo   jffs2: move jffs2...
19
  #include <linux/kthread.h>
1da177e4c   Linus Torvalds   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   David Woodhouse   jffs2: Require jf...
27
  	assert_spin_locked(&c->erase_completion_lock);
ef53cb02f   David Woodhouse   [JFFS2] Whitespac...
28
29
  	if (c->gc_task && jffs2_thread_should_wake(c))
  		send_sig(SIGHUP, c->gc_task, 1);
1da177e4c   Linus Torvalds   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   Gerard Lledo   jffs2: move jffs2...
35
  	struct task_struct *tsk;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
36
  	int ret = 0;
4b4d1cc73   Eric Sesterhenn   BUG_ON() Conversi...
37
  	BUG_ON(c->gc_task);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
38

fff7afd79   Thomas Gleixner   [JFFS2] Convert t...
39
  	init_completion(&c->gc_thread_start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
40
  	init_completion(&c->gc_thread_exit);
91e0955b5   Gerard Lledo   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   Joe Perches   jffs2: Convert pr...
43
44
45
  		pr_warn("fork failed for JFFS2 garbage collect thread: %ld
  ",
  			-PTR_ERR(tsk));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46
  		complete(&c->gc_thread_exit);
91e0955b5   Gerard Lledo   jffs2: move jffs2...
47
  		ret = PTR_ERR(tsk);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
48
49
  	} else {
  		/* Wait for it... */
5a528957e   Joe Perches   jffs2: Use pr_fmt...
50
51
  		jffs2_dbg(1, "Garbage collect thread is pid %d
  ", tsk->pid);
fff7afd79   Thomas Gleixner   [JFFS2] Convert t...
52
  		wait_for_completion(&c->gc_thread_start);
91e0955b5   Gerard Lledo   jffs2: move jffs2...
53
  		ret = tsk->pid;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
54
  	}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
55

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
58
59
60
  	return ret;
  }
  
  void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c)
  {
e2d48b1a9   Thomas Gleixner   [JFFS2] Fix clean...
61
  	int wait = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
62
63
  	spin_lock(&c->erase_completion_lock);
  	if (c->gc_task) {
5a528957e   Joe Perches   jffs2: Use pr_fmt...
64
65
  		jffs2_dbg(1, "Killing GC task %d
  ", c->gc_task->pid);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
66
  		send_sig(SIGKILL, c->gc_task, 1);
e2d48b1a9   Thomas Gleixner   [JFFS2] Fix clean...
67
  		wait = 1;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
68
69
  	}
  	spin_unlock(&c->erase_completion_lock);
e2d48b1a9   Thomas Gleixner   [JFFS2] Fix clean...
70
71
  	if (wait)
  		wait_for_completion(&c->gc_thread_exit);
1da177e4c   Linus Torvalds   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   Oleg Nesterov   signals: jffs2: f...
77
  	sigset_t hupmask;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
78

c240837fa   Oleg Nesterov   signals: jffs2: f...
79
  	siginitset(&hupmask, sigmask(SIGHUP));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
80
81
  	allow_signal(SIGKILL);
  	allow_signal(SIGSTOP);
c240837fa   Oleg Nesterov   signals: jffs2: f...
82
  	allow_signal(SIGHUP);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
83
84
  
  	c->gc_task = current;
fff7afd79   Thomas Gleixner   [JFFS2] Convert t...
85
  	complete(&c->gc_thread_start);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
86
87
  
  	set_user_nice(current, 10);
831441862   Rafael J. Wysocki   Freezer: make ker...
88
  	set_freezable();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
89
  	for (;;) {
c240837fa   Oleg Nesterov   signals: jffs2: f...
90
  		sigprocmask(SIG_UNBLOCK, &hupmask, NULL);
e716dd364   David Woodhouse   [JFFS2] Fix suspe...
91
  	again:
b27cf88e9   David Woodhouse   [JFFS2] Fix lack ...
92
  		spin_lock(&c->erase_completion_lock);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
93
94
  		if (!jffs2_thread_should_wake(c)) {
  			set_current_state (TASK_INTERRUPTIBLE);
b27cf88e9   David Woodhouse   [JFFS2] Fix lack ...
95
  			spin_unlock(&c->erase_completion_lock);
9c261b33a   Joe Perches   jffs2: Convert mo...
96
97
  			jffs2_dbg(1, "%s(): sleeping...
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
98
  			schedule();
c240837fa   Oleg Nesterov   signals: jffs2: f...
99
  		} else {
b27cf88e9   David Woodhouse   [JFFS2] Fix lack ...
100
  			spin_unlock(&c->erase_completion_lock);
c240837fa   Oleg Nesterov   signals: jffs2: f...
101
  		}
efab0b5d3   Andres Salomon   [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   Linus Torvalds   Linux-2.6.12-rc2
113

91e0955b5   Gerard Lledo   jffs2: move jffs2...
114
  		if (kthread_should_stop()) {
9c261b33a   Joe Perches   jffs2: Convert mo...
115
116
  			jffs2_dbg(1, "%s(): kthread_stop() called
  ", __func__);
91e0955b5   Gerard Lledo   jffs2: move jffs2...
117
118
  			goto die;
  		}
182ec4eee   Thomas Gleixner   [JFFS2] Clean up ...
119
  		/* Put_super will send a SIGKILL and then wait on the sem.
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
120
  		 */
e136e769d   Rafael J. Wysocki   Freezer: Fix JFFS...
121
  		while (signal_pending(current) || freezing(current)) {
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
122
  			unsigned long signr;
e716dd364   David Woodhouse   [JFFS2] Fix suspe...
123
124
  			if (try_to_freeze())
  				goto again;
be0e6f290   Oleg Nesterov   signal: turn dequ...
125
  			signr = kernel_dequeue_signal(NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
126
127
128
  
  			switch(signr) {
  			case SIGSTOP:
9c261b33a   Joe Perches   jffs2: Convert mo...
129
130
131
  				jffs2_dbg(1, "%s(): SIGSTOP received
  ",
  					  __func__);
9a13049e8   Oleg Nesterov   signal: introduce...
132
  				kernel_signal_stop();
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
133
134
135
  				break;
  
  			case SIGKILL:
9c261b33a   Joe Perches   jffs2: Convert mo...
136
137
138
  				jffs2_dbg(1, "%s(): SIGKILL received
  ",
  					  __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
139
140
141
  				goto die;
  
  			case SIGHUP:
9c261b33a   Joe Perches   jffs2: Convert mo...
142
143
144
  				jffs2_dbg(1, "%s(): SIGHUP received
  ",
  					  __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
145
146
  				break;
  			default:
9c261b33a   Joe Perches   jffs2: Convert mo...
147
148
149
  				jffs2_dbg(1, "%s(): signal %ld received
  ",
  					  __func__, signr);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
150
151
152
  			}
  		}
  		/* We don't want SIGHUP to interrupt us. STOP and KILL are OK though. */
c240837fa   Oleg Nesterov   signals: jffs2: f...
153
  		sigprocmask(SIG_BLOCK, &hupmask, NULL);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154

9c261b33a   Joe Perches   jffs2: Convert mo...
155
156
  		jffs2_dbg(1, "%s(): pass
  ", __func__);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
157
  		if (jffs2_garbage_collect_pass(c) == -ENOSPC) {
da320f055   Joe Perches   jffs2: Convert pr...
158
159
  			pr_notice("No space for garbage collection. Aborting GC thread
  ");
1da177e4c   Linus Torvalds   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);
  }