From: Jiri Olsa <jolsa@redhat.com> Date: Mon, 22 Mar 2010 08:26:32 -0400 Subject: [net] route: fix BUG_ON in rt_secret_rebuild_oneshot Message-id: <20100322082632.GB1851@jolsa.sde> Patchwork-id: 23684 O-Subject: Re: [PATCH RHEL5] BZ#566104 - route: Fix caught BUG_ON during rt_secret_rebuild_oneshot() Bugzilla: 566104 RH-Acked-by: Dean Nelson <dnelson@redhat.com> Bugzilla: 566104 https://bugzilla.redhat.com/show_bug.cgi?id=566104 Description: ============ Call rt_secret_rebuild can cause BUG_ON(timer_pending(&net->ipv4.rt_secret_timer)) in add_timer as there is not any synchronization for call rt_secret_rebuild_oneshot() for the same net namespace. Also this issue affects to rt_secret_reschedule(). Thus use mod_timer enstead. Upstream status: ================ - route: Fix caught BUG_ON during rt_secret_rebuild_oneshot() commit 858a18a6a2f74e8f0e5b2e9671d4b74694aba708 Author: Vitaliy Gusev<vgusev@openvz.org> Brew: ===== https://brewweb.devel.redhat.com/taskinfo?taskID=2328590 Tested: ======= booted, I tried to stress setting of secret_interval, but did not succeed to trigger the BUG wbr, jirka Signed-off-by: Jarod Wilson <jarod@redhat.com> diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 8251ce8..261c70f 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -822,11 +822,9 @@ static void rt_secret_rebuild(unsigned long dummy) static void rt_secret_rebuild_oneshot(void) { del_timer_sync(&rt_secret_timer); - rt_cache_flush(0); - if (ip_rt_secret_interval) { - rt_secret_timer.expires += ip_rt_secret_interval; - add_timer(&rt_secret_timer); - } + rt_cache_flush(0); + if (ip_rt_secret_interval) + mod_timer(&rt_secret_timer, jiffies + ip_rt_secret_interval); } static void rt_emergency_hash_rebuild(void) @@ -3134,6 +3132,7 @@ static void rt_secret_reschedule(int old) int new = ip_rt_secret_interval; int diff = new - old; int deleted; + long time; if (!diff) return; @@ -3145,17 +3144,14 @@ static void rt_secret_reschedule(int old) goto unlock; if (deleted) { - long time = rt_secret_timer.expires - jiffies; + time = rt_secret_timer.expires - jiffies; if (time <= 0 || (time += diff) <= 0) time = 0; - - rt_secret_timer.expires = time; } else - rt_secret_timer.expires = new; + time = new; - rt_secret_timer.expires += jiffies; - add_timer(&rt_secret_timer); + mod_timer(&rt_secret_timer, jiffies + time); unlock: rtnl_unlock(); }