1 Subject: mm: fix pdflush thread creation upper bound.
2 From: Peter W. Morreale <pmorreale@novell.com>
4 Patch-upstream: not yet
6 This patch fixes a race on creating pdflush threads. Without the patch,
7 it is possible to create more than MAX_PDFLUSH_THREADS threads, and this
8 has been observed in practice.
10 The fix involves moving the lock around to protect the check against the
11 thread count and correctly dealing with thread creation failure.
13 Signed-Off-By: Peter W. Morreale <pmorreale@novell.com>
14 Acked-by: Nick Piggin <npiggin@suse.de>
17 mm/pdflush.c | 27 +++++++++++++++++++++------
18 1 file changed, 21 insertions(+), 6 deletions(-)
22 @@ -98,7 +98,6 @@ static int __pdflush(struct pdflush_work
23 INIT_LIST_HEAD(&my_work->list);
25 spin_lock_irq(&pdflush_lock);
26 - nr_pdflush_threads++;
28 struct pdflush_work *pdf;
30 @@ -126,20 +125,23 @@ static int __pdflush(struct pdflush_work
32 (*my_work->fn)(my_work->arg0);
34 + spin_lock_irq(&pdflush_lock);
37 * Thread creation: For how long have there been zero
40 if (time_after(jiffies, last_empty_jifs + 1 * HZ)) {
41 - /* unlocked list_empty() test is OK here */
42 if (list_empty(&pdflush_list)) {
43 - /* unlocked test is OK here */
44 - if (nr_pdflush_threads < MAX_PDFLUSH_THREADS)
45 + if (nr_pdflush_threads < MAX_PDFLUSH_THREADS) {
46 + nr_pdflush_threads++;
47 + spin_unlock_irq(&pdflush_lock);
48 start_one_pdflush_thread();
49 + spin_lock_irq(&pdflush_lock);
54 - spin_lock_irq(&pdflush_lock);
58 @@ -226,13 +228,26 @@ int pdflush_operation(void (*fn)(unsigne
60 static void start_one_pdflush_thread(void)
62 - kthread_run(pdflush, NULL, "pdflush");
63 + struct task_struct *k;
65 + k = kthread_run(pdflush, NULL, "pdflush");
66 + if (unlikely(IS_ERR(k))) {
67 + spin_lock_irq(&pdflush_lock);
68 + nr_pdflush_threads--;
69 + spin_unlock_irq(&pdflush_lock);
73 static int __init pdflush_init(void)
78 + * Pre-set nr_pdflush_threads... If we fail to create,
79 + * the count will be decremented.
81 + nr_pdflush_threads = MIN_PDFLUSH_THREADS;
83 for (i = 0; i < MIN_PDFLUSH_THREADS; i++)
84 start_one_pdflush_thread();