]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
nohz fix and slab fix
authorChris Wright <chrisw@sous-sol.org>
Thu, 27 Mar 2008 07:32:50 +0000 (00:32 -0700)
committerChris Wright <chrisw@sous-sol.org>
Thu, 27 Mar 2008 07:32:50 +0000 (00:32 -0700)
queue-2.6.24/nohz-reevaluate-idle-sleep-length-after-add_timer_on.patch [new file with mode: 0644]
queue-2.6.24/series
queue-2.6.24/slab-fix-cache_cache-bootstrap-in-kmem_cache_init.patch [new file with mode: 0644]

diff --git a/queue-2.6.24/nohz-reevaluate-idle-sleep-length-after-add_timer_on.patch b/queue-2.6.24/nohz-reevaluate-idle-sleep-length-after-add_timer_on.patch
new file mode 100644 (file)
index 0000000..371a4e0
--- /dev/null
@@ -0,0 +1,125 @@
+From stable-bounces@linux.kernel.org  Wed Mar 26 11:54:30 2008
+Date: Wed, 26 Mar 2008 18:35:10 GMT
+Message-Id: <200803261835.m2QIZA4F017424@hera.kernel.org>
+From: jejb@kernel.org
+To: jejb@kernel.org, stable@kernel.org
+Subject: NOHZ: reevaluate idle sleep length after add_timer_on()
+
+From: Thomas Gleixner <tglx@linutronix.de>
+
+upstream commit: 06d8308c61e54346585b2691c13ee3f90cb6fb2f
+
+add_timer_on() can add a timer on a CPU which is currently in a long
+idle sleep, but the timer wheel is not reevaluated by the nohz code on
+that CPU. So a timer can be delayed for quite a long time. This
+triggered a false positive in the clocksource watchdog code.
+
+To avoid this we need to wake up the idle CPU and enforce the
+reevaluation of the timer wheel for the next timer event.
+
+Add a function, which checks a given CPU for idle state, marks the
+idle task with NEED_RESCHED and sends a reschedule IPI to notify the
+other CPU of the change in the timer wheel.
+
+Call this function from add_timer_on().
+
+Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
+Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
+Acked-by: Ingo Molnar <mingo@elte.hu>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+--
+ include/linux/sched.h |    6 ++++++
+ kernel/sched.c        |   43 +++++++++++++++++++++++++++++++++++++++++++
+ kernel/timer.c        |   10 +++++++++-
+ 3 files changed, 58 insertions(+), 1 deletion(-)
+---
+
+--- a/include/linux/sched.h
++++ b/include/linux/sched.h
+@@ -1449,6 +1449,12 @@ static inline void idle_task_exit(void) 
+ extern void sched_idle_next(void);
++#if defined(CONFIG_NO_HZ) && defined(CONFIG_SMP)
++extern void wake_up_idle_cpu(int cpu);
++#else
++static inline void wake_up_idle_cpu(int cpu) { }
++#endif
++
+ #ifdef CONFIG_SCHED_DEBUG
+ extern unsigned int sysctl_sched_latency;
+ extern unsigned int sysctl_sched_min_granularity;
+--- a/kernel/sched.c
++++ b/kernel/sched.c
+@@ -727,6 +727,49 @@ static void resched_cpu(int cpu)
+       resched_task(cpu_curr(cpu));
+       spin_unlock_irqrestore(&rq->lock, flags);
+ }
++
++#ifdef CONFIG_NO_HZ
++/*
++ * When add_timer_on() enqueues a timer into the timer wheel of an
++ * idle CPU then this timer might expire before the next timer event
++ * which is scheduled to wake up that CPU. In case of a completely
++ * idle system the next event might even be infinite time into the
++ * future. wake_up_idle_cpu() ensures that the CPU is woken up and
++ * leaves the inner idle loop so the newly added timer is taken into
++ * account when the CPU goes back to idle and evaluates the timer
++ * wheel for the next timer event.
++ */
++void wake_up_idle_cpu(int cpu)
++{
++      struct rq *rq = cpu_rq(cpu);
++
++      if (cpu == smp_processor_id())
++              return;
++
++      /*
++       * This is safe, as this function is called with the timer
++       * wheel base lock of (cpu) held. When the CPU is on the way
++       * to idle and has not yet set rq->curr to idle then it will
++       * be serialized on the timer wheel base lock and take the new
++       * timer into account automatically.
++       */
++      if (rq->curr != rq->idle)
++              return;
++
++      /*
++       * We can set TIF_RESCHED on the idle task of the other CPU
++       * lockless. The worst case is that the other CPU runs the
++       * idle task through an additional NOOP schedule()
++       */
++      set_tsk_thread_flag(rq->idle, TIF_NEED_RESCHED);
++
++      /* NEED_RESCHED must be visible before we test polling */
++      smp_mb();
++      if (!tsk_is_polling(rq->idle))
++              smp_send_reschedule(cpu);
++}
++#endif
++
+ #else
+ static inline void resched_task(struct task_struct *p)
+ {
+--- a/kernel/timer.c
++++ b/kernel/timer.c
+@@ -453,10 +453,18 @@ void add_timer_on(struct timer_list *tim
+       spin_lock_irqsave(&base->lock, flags);
+       timer_set_base(timer, base);
+       internal_add_timer(base, timer);
++      /*
++       * Check whether the other CPU is idle and needs to be
++       * triggered to reevaluate the timer wheel when nohz is
++       * active. We are protected against the other CPU fiddling
++       * with the timer by holding the timer base lock. This also
++       * makes sure that a CPU on the way to idle can not evaluate
++       * the timer wheel.
++       */
++      wake_up_idle_cpu(cpu);
+       spin_unlock_irqrestore(&base->lock, flags);
+ }
+-
+ /**
+  * mod_timer - modify a timer's timeout
+  * @timer: the timer to be modified
index dfee4f3cc18525e6281aa6ecf94ce2befb2c4813..2e59ddde0e2a637c3c3438f9a9985d68d51676a1 100644 (file)
@@ -8,3 +8,5 @@ usb-add-support-for-motorola-rokr-z6-cellphone-in-mass-storage-mode.patch
 usb-new-quirk-flag-to-avoid-set-interface.patch
 inotify-fix-race.patch
 inotify-remove-debug-code.patch
+nohz-reevaluate-idle-sleep-length-after-add_timer_on.patch
+slab-fix-cache_cache-bootstrap-in-kmem_cache_init.patch
diff --git a/queue-2.6.24/slab-fix-cache_cache-bootstrap-in-kmem_cache_init.patch b/queue-2.6.24/slab-fix-cache_cache-bootstrap-in-kmem_cache_init.patch
new file mode 100644 (file)
index 0000000..411a71a
--- /dev/null
@@ -0,0 +1,47 @@
+From stable-bounces@linux.kernel.org  Wed Mar 26 14:39:36 2008
+Date: Wed, 26 Mar 2008 23:37:41 +0200 (EET)
+From: Pekka J Enberg <penberg@cs.helsinki.fi>
+To: stable@kernel.org
+Message-ID: <Pine.LNX.4.64.0803262336220.14137@sbz-30.cs.Helsinki.FI>
+Cc: mel@csn.ul.ie, olaf@aepfle.de, dan.yeisley@unisys.com, akpm@linux-foundation.org, clameter@sgi.com
+Subject: slab: fix cache_cache bootstrap in kmem_cache_init()
+
+From: Daniel Yeisley <dan.yeisley@unisys.com>
+
+upstream commit: ec1f5eeeb5a79a0d48036de649a3498da42db565
+
+Commit 556a169dab38b5100df6f4a45b655dddd3db94c1 ("slab: fix bootstrap on
+memoryless node") introduced bootstrap-time cache_cache list3s for all nodes
+but forgot that initkmem_list3 needs to be accessed by [somevalue + node]. This
+patch fixes list_add() corruption in mm/slab.c seen on the ES7000.
+Cc: Mel Gorman <mel@csn.ul.ie>
+Cc: Olaf Hering <olaf@aepfle.de>
+Signed-off-by: Dan Yeisley <dan.yeisley@unisys.com>
+Signed-off-by: Pekka Enberg <penberg@cs.helsinki.fi>
+Signed-off-by: Christoph Lameter <clameter@sgi.com>
+Signed-off-by: Chris Wright <chrisw@sous-sol.org>
+---
+ mm/slab.c |    4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/mm/slab.c
++++ b/mm/slab.c
+@@ -1484,7 +1484,7 @@ void __init kmem_cache_init(void)
+       list_add(&cache_cache.next, &cache_chain);
+       cache_cache.colour_off = cache_line_size();
+       cache_cache.array[smp_processor_id()] = &initarray_cache.cache;
+-      cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE];
++      cache_cache.nodelists[node] = &initkmem_list3[CACHE_CACHE + node];
+       /*
+        * struct kmem_cache size depends on nr_node_ids, which
+@@ -1605,7 +1605,7 @@ void __init kmem_cache_init(void)
+               int nid;
+               for_each_online_node(nid) {
+-                      init_list(&cache_cache, &initkmem_list3[CACHE_CACHE], nid);
++                      init_list(&cache_cache, &initkmem_list3[CACHE_CACHE + nid], nid);
+                       init_list(malloc_sizes[INDEX_AC].cs_cachep,
+                                 &initkmem_list3[SIZE_AC + nid], nid);