| From 878d7439d0f45a95869e417576774673d1fa243f Mon Sep 17 00:00:00 2001 |
| From: Eric Dumazet <edumazet@google.com> |
| Date: Thu, 18 Oct 2012 04:55:36 -0700 |
| Subject: rcu: Fix batch-limit size problem |
| |
| From: Eric Dumazet <edumazet@google.com> |
| |
| commit 878d7439d0f45a95869e417576774673d1fa243f upstream. |
| |
| Commit 29c00b4a1d9e27 (rcu: Add event-tracing for RCU callback |
| invocation) added a regression in rcu_do_batch() |
| |
| Under stress, RCU is supposed to allow to process all items in queue, |
| instead of a batch of 10 items (blimit), but an integer overflow makes |
| the effective limit being 1. So, unless there is frequent idle periods |
| (during which RCU ignores batch limits), RCU can be forced into a |
| state where it cannot keep up with the callback-generation rate, |
| eventually resulting in OOM. |
| |
| This commit therefore converts a few variables in rcu_do_batch() from |
| int to long to fix this problem, along with the module parameters |
| controlling the batch limits. |
| |
| Signed-off-by: Eric Dumazet <edumazet@google.com> |
| Signed-off-by: Paul E. McKenney <paulmck@linux.vnet.ibm.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| kernel/rcutree.c | 16 ++++++++-------- |
| 1 file changed, 8 insertions(+), 8 deletions(-) |
| |
| --- a/kernel/rcutree.c |
| +++ b/kernel/rcutree.c |
| @@ -202,13 +202,13 @@ DEFINE_PER_CPU(struct rcu_dynticks, rcu_ |
| .dynticks = ATOMIC_INIT(1), |
| }; |
| |
| -static int blimit = 10; /* Maximum callbacks per rcu_do_batch. */ |
| -static int qhimark = 10000; /* If this many pending, ignore blimit. */ |
| -static int qlowmark = 100; /* Once only this many pending, use blimit. */ |
| - |
| -module_param(blimit, int, 0); |
| -module_param(qhimark, int, 0); |
| -module_param(qlowmark, int, 0); |
| +static long blimit = 10; /* Maximum callbacks per rcu_do_batch. */ |
| +static long qhimark = 10000; /* If this many pending, ignore blimit. */ |
| +static long qlowmark = 100; /* Once only this many pending, use blimit. */ |
| + |
| +module_param(blimit, long, 0); |
| +module_param(qhimark, long, 0); |
| +module_param(qlowmark, long, 0); |
| |
| int rcu_cpu_stall_suppress __read_mostly; /* 1 = suppress stall warnings. */ |
| int rcu_cpu_stall_timeout __read_mostly = CONFIG_RCU_CPU_STALL_TIMEOUT; |
| @@ -1476,7 +1476,7 @@ static void rcu_do_batch(struct rcu_stat |
| { |
| unsigned long flags; |
| struct rcu_head *next, *list, **tail; |
| - int bl, count, count_lazy; |
| + long bl, count, count_lazy; |
| |
| /* If no callbacks are ready, just return.*/ |
| if (!cpu_has_callbacks_ready_to_invoke(rdp)) { |