+++ /dev/null
-Subject: mm: fix pdflush thread creation upper bound.
-From: Peter W. Morreale <pmorreale@novell.com>
-References: bnc#460284
-Patch-upstream: not yet
-
- This patch fixes a race on creating pdflush threads. Without the patch,
- it is possible to create more than MAX_PDFLUSH_THREADS threads, and this
- has been observed in practice.
-
- The fix involves moving the lock around to protect the check against the
- thread count and correctly dealing with thread creation failure.
-
- Signed-Off-By: Peter W. Morreale <pmorreale@novell.com>
-Acked-by: Nick Piggin <npiggin@suse.de>
----
----
- mm/pdflush.c | 27 +++++++++++++++++++++------
- 1 file changed, 21 insertions(+), 6 deletions(-)
-
---- a/mm/pdflush.c
-+++ b/mm/pdflush.c
-@@ -98,7 +98,6 @@ static int __pdflush(struct pdflush_work
- INIT_LIST_HEAD(&my_work->list);
-
- spin_lock_irq(&pdflush_lock);
-- nr_pdflush_threads++;
- for ( ; ; ) {
- struct pdflush_work *pdf;
-
-@@ -126,20 +125,23 @@ static int __pdflush(struct pdflush_work
-
- (*my_work->fn)(my_work->arg0);
-
-+ spin_lock_irq(&pdflush_lock);
-+
- /*
- * Thread creation: For how long have there been zero
- * available threads?
- */
- if (time_after(jiffies, last_empty_jifs + 1 * HZ)) {
-- /* unlocked list_empty() test is OK here */
- if (list_empty(&pdflush_list)) {
-- /* unlocked test is OK here */
-- if (nr_pdflush_threads < MAX_PDFLUSH_THREADS)
-+ if (nr_pdflush_threads < MAX_PDFLUSH_THREADS) {
-+ nr_pdflush_threads++;
-+ spin_unlock_irq(&pdflush_lock);
- start_one_pdflush_thread();
-+ spin_lock_irq(&pdflush_lock);
-+ }
- }
- }
-
-- spin_lock_irq(&pdflush_lock);
- my_work->fn = NULL;
-
- /*
-@@ -226,13 +228,26 @@ int pdflush_operation(void (*fn)(unsigne
-
- static void start_one_pdflush_thread(void)
- {
-- kthread_run(pdflush, NULL, "pdflush");
-+ struct task_struct *k;
-+
-+ k = kthread_run(pdflush, NULL, "pdflush");
-+ if (unlikely(IS_ERR(k))) {
-+ spin_lock_irq(&pdflush_lock);
-+ nr_pdflush_threads--;
-+ spin_unlock_irq(&pdflush_lock);
-+ }
- }
-
- static int __init pdflush_init(void)
- {
- int i;
-
-+ /*
-+ * Pre-set nr_pdflush_threads... If we fail to create,
-+ * the count will be decremented.
-+ */
-+ nr_pdflush_threads = MIN_PDFLUSH_THREADS;
-+
- for (i = 0; i < MIN_PDFLUSH_THREADS; i++)
- start_one_pdflush_thread();
- return 0;