From: Simon Horman <horms@verge.net.au>
To: Eric Dumazet <dada1@cosmosbay.com>
Cc: David Miller <davem@davemloft.net>,
"netdev@vger.kernel.org" <netdev@vger.kernel.org>
Subject: Re: [PATCH] IPV4 : Move ip route cache flush (secret_rebuild) from softirq to workqueue
Date: Fri, 16 Nov 2007 11:50:01 -0800 [thread overview]
Message-ID: <20071116194959.GE8971@verge.net.au> (raw)
In-Reply-To: <20071116174027.726e6eca.dada1@cosmosbay.com>
On Fri, Nov 16, 2007 at 05:40:27PM +0100, Eric Dumazet wrote:
> Hello David
>
> This patch against net-2.6.25 is another step to get a more resistant ip route cache.
>
> Thank you
>
> [PATCH] IPV4 : Move ip route cache flush (secret_rebuild) from softirq to workqueue
>
> Every 600 seconds (ip_rt_secret_interval), a softirq flush of the whole
> ip route cache is triggered. On loaded machines, this can starve softirq for
> many seconds and can eventually crash.
>
> This patch moves this flush to a workqueue context, using the worker we
> intoduced in commit 39c90ece7565f5c47110c2fa77409d7a9478bd5b
> (IPV4: Convert rt_check_expire() from softirq processing to workqueue.)
>
> Also, immediate flushes (echo 0 >/proc/sys/net/ipv4/route/flush) are using
> rt_do_flush() helper function, wich take attention to rescheduling.
>
> Next step will be to handle delayed flushes
> ("echo -1 >/proc/sys/net/ipv4/route/flush" or
> "ip route flush cache")
>
> Signed-off-by: Eric Dumazet <dada1@cosmosbay.com>
>
> net/ipv4/route.c | 89 ++++++++++++++++++++++++++++++++-------------
> 1 file changed, 65 insertions(+), 24 deletions(-)
>
> diff --git a/net/ipv4/route.c b/net/ipv4/route.c
> index 856807c..5d74620 100644
> --- a/net/ipv4/route.c
> +++ b/net/ipv4/route.c
> @@ -133,13 +133,14 @@ static int ip_rt_mtu_expires = 10 * 60 * HZ;
> static int ip_rt_min_pmtu = 512 + 20 + 20;
> static int ip_rt_min_advmss = 256;
> static int ip_rt_secret_interval = 10 * 60 * HZ;
> +static int ip_rt_flush_expected;
> static unsigned long rt_deadline;
>
> #define RTprint(a...) printk(KERN_DEBUG a)
>
> static struct timer_list rt_flush_timer;
> -static void rt_check_expire(struct work_struct *work);
> -static DECLARE_DELAYED_WORK(expires_work, rt_check_expire);
> +static void rt_worker_func(struct work_struct *work);
> +static DECLARE_DELAYED_WORK(expires_work, rt_worker_func);
> static struct timer_list rt_secret_timer;
>
> /*
> @@ -561,7 +562,42 @@ static inline int compare_keys(struct flowi *fl1, struct flowi *fl2)
> (fl1->iif ^ fl2->iif)) == 0;
> }
>
> -static void rt_check_expire(struct work_struct *work)
> +/*
> + * Perform a full scan of hash table and free all entries.
> + * Can be called by a softirq or a process.
> + * In the later case, we want to be reschedule if necessary
> + */
> +static void rt_do_flush(int process_context)
> +{
> + unsigned int i;
> + struct rtable *rth, *next;
> + unsigned long fake = 0, *flag_ptr;
> +
> + flag_ptr = process_context ? ¤t_thread_info()->flags : &fake;
> +
> + for (i = 0; i <= rt_hash_mask; i++) {
> + rth = rt_hash_table[i].chain;
> + if (rth) {
> + spin_lock_bh(rt_hash_lock_addr(i));
> + rth = rt_hash_table[i].chain;
> + rt_hash_table[i].chain = NULL;
> + spin_unlock_bh(rt_hash_lock_addr(i));
> + }
> + /*
> + * This is a fast version of :
> + * if (process_context && need_resched())
> + */
> + if (unlikely(test_bit(TIF_NEED_RESCHED, flag_ptr)))
> + cond_resched();
> +
> + for (; rth; rth = next) {
> + next = rth->u.dst.rt_next;
> + rt_free(rth);
> + }
> + }
> +}
Is it ever neccessary to call cond_resched() if rt_hash_table[i].chain
is NULL? If not, the following looks cleaner to my eyes:
for (i = 0; i <= rt_hash_mask; i++) {
rth = rt_hash_table[i].chain;
if (!rth)
continue;
spin_lock_bh(rt_hash_lock_addr(i));
rth = rt_hash_table[i].chain;
rt_hash_table[i].chain = NULL;
spin_unlock_bh(rt_hash_lock_addr(i));
...
--
Horms, California Edition
next prev parent reply other threads:[~2007-11-16 19:50 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-11-16 16:40 [PATCH] IPV4 : Move ip route cache flush (secret_rebuild) from softirq to workqueue Eric Dumazet
2007-11-16 19:50 ` Simon Horman [this message]
2007-11-16 21:23 ` Eric Dumazet
2007-11-17 0:54 ` David Miller
2007-11-17 9:41 ` Eric Dumazet
2007-11-17 14:36 ` Herbert Xu
2007-11-17 16:18 ` Eric Dumazet
2007-11-17 16:29 ` Herbert Xu
2007-11-18 0:45 ` David Miller
2007-11-18 2:07 ` Herbert Xu
2007-11-18 2:13 ` David Miller
2007-11-20 6:43 ` David Miller
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20071116194959.GE8971@verge.net.au \
--to=horms@verge.net.au \
--cc=dada1@cosmosbay.com \
--cc=davem@davemloft.net \
--cc=netdev@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.