aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
Diffstat (limited to 'mm')
-rw-r--r--mm/pdflush.c47
1 files changed, 36 insertions, 11 deletions
diff --git a/mm/pdflush.c b/mm/pdflush.c
index 118905e3d788..f2caf96993f8 100644
--- a/mm/pdflush.c
+++ b/mm/pdflush.c
@@ -58,6 +58,14 @@ static DEFINE_SPINLOCK(pdflush_lock);
58int nr_pdflush_threads = 0; 58int nr_pdflush_threads = 0;
59 59
60/* 60/*
61 * The max/min number of pdflush threads. R/W by sysctl at
62 * /proc/sys/vm/nr_pdflush_threads_max/min
63 */
64int nr_pdflush_threads_max __read_mostly = MAX_PDFLUSH_THREADS;
65int nr_pdflush_threads_min __read_mostly = MIN_PDFLUSH_THREADS;
66
67
68/*
61 * The time at which the pdflush thread pool last went empty 69 * The time at which the pdflush thread pool last went empty
62 */ 70 */
63static unsigned long last_empty_jifs; 71static unsigned long last_empty_jifs;
@@ -68,7 +76,7 @@ static unsigned long last_empty_jifs;
68 * Thread pool management algorithm: 76 * Thread pool management algorithm:
69 * 77 *
70 * - The minimum and maximum number of pdflush instances are bound 78 * - The minimum and maximum number of pdflush instances are bound
71 * by MIN_PDFLUSH_THREADS and MAX_PDFLUSH_THREADS. 79 * by nr_pdflush_threads_min and nr_pdflush_threads_max.
72 * 80 *
73 * - If there have been no idle pdflush instances for 1 second, create 81 * - If there have been no idle pdflush instances for 1 second, create
74 * a new one. 82 * a new one.
@@ -98,7 +106,6 @@ static int __pdflush(struct pdflush_work *my_work)
98 INIT_LIST_HEAD(&my_work->list); 106 INIT_LIST_HEAD(&my_work->list);
99 107
100 spin_lock_irq(&pdflush_lock); 108 spin_lock_irq(&pdflush_lock);
101 nr_pdflush_threads++;
102 for ( ; ; ) { 109 for ( ; ; ) {
103 struct pdflush_work *pdf; 110 struct pdflush_work *pdf;
104 111
@@ -126,20 +133,25 @@ static int __pdflush(struct pdflush_work *my_work)
126 133
127 (*my_work->fn)(my_work->arg0); 134 (*my_work->fn)(my_work->arg0);
128 135
136 spin_lock_irq(&pdflush_lock);
137
129 /* 138 /*
130 * Thread creation: For how long have there been zero 139 * Thread creation: For how long have there been zero
131 * available threads? 140 * available threads?
141 *
142 * To throttle creation, we reset last_empty_jifs.
132 */ 143 */
133 if (time_after(jiffies, last_empty_jifs + 1 * HZ)) { 144 if (time_after(jiffies, last_empty_jifs + 1 * HZ)) {
134 /* unlocked list_empty() test is OK here */ 145 if (list_empty(&pdflush_list) &&
135 if (list_empty(&pdflush_list)) { 146 nr_pdflush_threads < nr_pdflush_threads_max) {
136 /* unlocked test is OK here */ 147 last_empty_jifs = jiffies;
137 if (nr_pdflush_threads < MAX_PDFLUSH_THREADS) 148 nr_pdflush_threads++;
138 start_one_pdflush_thread(); 149 spin_unlock_irq(&pdflush_lock);
150 start_one_pdflush_thread();
151 spin_lock_irq(&pdflush_lock);
139 } 152 }
140 } 153 }
141 154
142 spin_lock_irq(&pdflush_lock);
143 my_work->fn = NULL; 155 my_work->fn = NULL;
144 156
145 /* 157 /*
@@ -148,7 +160,7 @@ static int __pdflush(struct pdflush_work *my_work)
148 */ 160 */
149 if (list_empty(&pdflush_list)) 161 if (list_empty(&pdflush_list))
150 continue; 162 continue;
151 if (nr_pdflush_threads <= MIN_PDFLUSH_THREADS) 163 if (nr_pdflush_threads <= nr_pdflush_threads_min)
152 continue; 164 continue;
153 pdf = list_entry(pdflush_list.prev, struct pdflush_work, list); 165 pdf = list_entry(pdflush_list.prev, struct pdflush_work, list);
154 if (time_after(jiffies, pdf->when_i_went_to_sleep + 1 * HZ)) { 166 if (time_after(jiffies, pdf->when_i_went_to_sleep + 1 * HZ)) {
@@ -236,14 +248,27 @@ int pdflush_operation(void (*fn)(unsigned long), unsigned long arg0)
236 248
237static void start_one_pdflush_thread(void) 249static void start_one_pdflush_thread(void)
238{ 250{
239 kthread_run(pdflush, NULL, "pdflush"); 251 struct task_struct *k;
252
253 k = kthread_run(pdflush, NULL, "pdflush");
254 if (unlikely(IS_ERR(k))) {
255 spin_lock_irq(&pdflush_lock);
256 nr_pdflush_threads--;
257 spin_unlock_irq(&pdflush_lock);
258 }
240} 259}
241 260
242static int __init pdflush_init(void) 261static int __init pdflush_init(void)
243{ 262{
244 int i; 263 int i;
245 264
246 for (i = 0; i < MIN_PDFLUSH_THREADS; i++) 265 /*
266 * Pre-set nr_pdflush_threads... If we fail to create,
267 * the count will be decremented.
268 */
269 nr_pdflush_threads = nr_pdflush_threads_min;
270
271 for (i = 0; i < nr_pdflush_threads_min; i++)
247 start_one_pdflush_thread(); 272 start_one_pdflush_thread();
248 return 0; 273 return 0;
249} 274}