]> git.ipfire.org Git - people/pmueller/ipfire-2.x.git/blame - src/patches/suse-2.6.27.25/patches.fixes/mm-nr_pdflush-race-fix.patch
Reenabled linux-xen and xen-image build
[people/pmueller/ipfire-2.x.git] / src / patches / suse-2.6.27.25 / patches.fixes / mm-nr_pdflush-race-fix.patch
CommitLineData
00e5a55c
BS
1Subject: mm: fix pdflush thread creation upper bound.
2From: Peter W. Morreale <pmorreale@novell.com>
3References: bnc#460284
4Patch-upstream: not yet
5
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.
9
10 The fix involves moving the lock around to protect the check against the
11 thread count and correctly dealing with thread creation failure.
12
13 Signed-Off-By: Peter W. Morreale <pmorreale@novell.com>
14Acked-by: Nick Piggin <npiggin@suse.de>
15---
16---
17 mm/pdflush.c | 27 +++++++++++++++++++++------
18 1 file changed, 21 insertions(+), 6 deletions(-)
19
20--- a/mm/pdflush.c
21+++ b/mm/pdflush.c
22@@ -98,7 +98,6 @@ static int __pdflush(struct pdflush_work
23 INIT_LIST_HEAD(&my_work->list);
24
25 spin_lock_irq(&pdflush_lock);
26- nr_pdflush_threads++;
27 for ( ; ; ) {
28 struct pdflush_work *pdf;
29
30@@ -126,20 +125,23 @@ static int __pdflush(struct pdflush_work
31
32 (*my_work->fn)(my_work->arg0);
33
34+ spin_lock_irq(&pdflush_lock);
35+
36 /*
37 * Thread creation: For how long have there been zero
38 * available threads?
39 */
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);
50+ }
51 }
52 }
53
54- spin_lock_irq(&pdflush_lock);
55 my_work->fn = NULL;
56
57 /*
58@@ -226,13 +228,26 @@ int pdflush_operation(void (*fn)(unsigne
59
60 static void start_one_pdflush_thread(void)
61 {
62- kthread_run(pdflush, NULL, "pdflush");
63+ struct task_struct *k;
64+
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);
70+ }
71 }
72
73 static int __init pdflush_init(void)
74 {
75 int i;
76
77+ /*
78+ * Pre-set nr_pdflush_threads... If we fail to create,
79+ * the count will be decremented.
80+ */
81+ nr_pdflush_threads = MIN_PDFLUSH_THREADS;
82+
83 for (i = 0; i < MIN_PDFLUSH_THREADS; i++)
84 start_one_pdflush_thread();
85 return 0;