From: Jarek Poplawski <jarkao2@o2.pl>
To: Ranko Zivojnovic <ranko@spidernet.net>
Cc: netdev@vger.kernel.org, Andrew Morton <akpm@linux-foundation.org>,
Patrick McHardy <kaber@trash.net>
Subject: Re: [NET]: gen_estimator deadlock fix
Date: Thu, 12 Jul 2007 09:37:46 +0200 [thread overview]
Message-ID: <20070712073746.GA1708@ff.dom.local> (raw)
In-Reply-To: <1184161297.1141.53.camel@ranko-fc2.spidernet.net>
On Wed, Jul 11, 2007 at 04:41:37PM +0300, Ranko Zivojnovic wrote:
> Fixes ABBA deadlock noted by Patrick McHardy <kaber@trash.net>:
> > There is at least one ABBA deadlock, est_timer() does:
> > read_lock(&est_lock)
> > spin_lock(e->stats_lock) (which is dev->queue_lock)
> >
> > and qdisc_destroy calls htb_destroy under dev->queue_lock, which
> > calls htb_destroy_class, then gen_kill_estimator and this
> > write_locks est_lock.
>
> est_lock completely removed and the RCU list implemented instead.
> Both gen_kill_estimator and gen_new_estimator are already called under
> rtnl_mutex.
>
> Signed-off-by: Ranko Zivojnovic <ranko@spidernet.net>
Maybe it's only my issue, but it seems there are no tabs: all spaces...
...plus some old doubts:
> ---
> net/core/gen_estimator.c | 73 ++++++++++++++++++++++++----------------------
> 1 files changed, 38 insertions(+), 35 deletions(-)
>
> diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
> index cc84d8d..444b2bd 100644
> --- a/net/core/gen_estimator.c
> +++ b/net/core/gen_estimator.c
...
> @@ -174,20 +175,25 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
> est->last_packets = bstats->packets;
> est->avpps = rate_est->pps<<10;
>
> - est->next = elist[est->interval].list;
> - if (est->next == NULL) {
> - init_timer(&elist[est->interval].timer);
> - elist[est->interval].timer.data = est->interval;
> - elist[est->interval].timer.expires = jiffies + ((HZ<<est->interval)/4);
> - elist[est->interval].timer.function = est_timer;
> - add_timer(&elist[est->interval].timer);
> + if (!elist[idx].timer.function) {
> + INIT_LIST_HEAD(&elist[idx].list);
> + setup_timer(&elist[idx].timer, est_timer, est->interval);
- setup_timer(&elist[idx].timer, est_timer, est->interval);
+ setup_timer(&elist[idx].timer, est_timer, idx);
...
> /**
> * gen_kill_estimator - remove a rate estimator
> * @bstats: basic statistics
> @@ -195,31 +201,28 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
> *
> * Removes the rate estimator specified by &bstats and &rate_est
> * and deletes the timer.
> + *
> + * NOTE: Called under rtnl_mutex
> */
> void gen_kill_estimator(struct gnet_stats_basic *bstats,
> struct gnet_stats_rate_est *rate_est)
> {
...
> + list_for_each_entry_safe(e, n, &elist[idx].list, list) {
> + if (e->rate_est != rate_est || e->bstats != bstats)
> + continue;
>
> - kfree(est);
> - killed++;
> + list_del_rcu(&e->list);
> + call_rcu(&e->e_rcu, __gen_kill_estimator);
> }
> - if (killed && elist[idx].list == NULL)
> - del_timer(&elist[idx].timer);
> }
> }
I've done a bit of mess last time, so maybe it was forgotten, but I
still think this kind of race is possible:
- gen_kill_estimator is called during qdisc_destroy under
dev->queue_lock,
- est_timer is running and waiting on this lock just on the
list entry of the destroyed class,
- gen_kill_estimator kills the entry and returns,
- in xxx_destroy_class kfree(cl) is done etc.,
- est_timer gets the lock and does nbytes = e->bstats->bytes or
e->rate_est-bps = ... with freed memory.
Regards,
Jarek P.
next prev parent reply other threads:[~2007-07-12 7:29 UTC|newest]
Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-07-11 13:41 [NET]: gen_estimator deadlock fix Ranko Zivojnovic
2007-07-12 7:37 ` Jarek Poplawski [this message]
2007-07-12 9:18 ` Ranko Zivojnovic
2007-07-12 9:40 ` Ranko Zivojnovic
2007-07-12 10:46 ` Jarek Poplawski
2007-07-12 11:47 ` Ranko Zivojnovic
2007-07-12 12:07 ` Patrick McHardy
2007-07-12 17:48 ` Ranko Zivojnovic
2007-07-13 12:17 ` Jarek Poplawski
2007-07-13 12:26 ` Ranko Zivojnovic
2007-07-13 13:42 ` Jarek Poplawski
2007-07-16 7:00 ` Jarek Poplawski
2007-07-16 13:03 ` Patrick McHardy
2007-07-16 17:45 ` Ranko Zivojnovic
2007-07-17 1:28 ` David Miller
2007-07-17 12:04 ` Jarek Poplawski
2007-07-17 12:01 ` Patrick McHardy
2007-07-17 12:28 ` Jarek Poplawski
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=20070712073746.GA1708@ff.dom.local \
--to=jarkao2@o2.pl \
--cc=akpm@linux-foundation.org \
--cc=kaber@trash.net \
--cc=netdev@vger.kernel.org \
--cc=ranko@spidernet.net \
/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.