From: Jarek Poplawski <jarkao2@o2.pl>
To: Patrick McHardy <kaber@trash.net>
Cc: David Miller <davem@davemloft.net>,
Andrew Morton <akpm@linux-foundation.org>,
netdev@vger.kernel.org,
"bugme-daemon\@kernel-bugs\.osdl\.org"
<bugme-daemon@kernel-bugs.osdl.org>,
ranko@spidernet.net
Subject: Re: [NET]: gen_estimator: fix locking and timer related bugs [Re: [Bugme-new] [Bug 8668] New: HTB Deadlock]
Date: Thu, 28 Jun 2007 08:54:48 +0200 [thread overview]
Message-ID: <20070628065448.GA1618@ff.dom.local> (raw)
In-Reply-To: <46828179.5030404@trash.net>
On Wed, Jun 27, 2007 at 05:25:45PM +0200, Patrick McHardy wrote:
> Patrick McHardy wrote:
> > [NET]: gen_estimator: fix locking and timer related bugs
> >
>
>
> That one still left a race, we could be reinitalizing the timer
> while it is still running. This patch additionally makes sure
> each timer is only initialized once.
>
> [NET]: gen_estimator: fix locking and timer related bugs
>
> As noticed by Jarek Poplawski <jarkao2@o2.pl>, the timer removal in
> gen_kill_estimator races with the timer function rearming the timer.
>
> Additionally there are a few more related problems that seem to be
> relicts from the timer when the estimator was qdisc specific and
- relicts from the timer when the estimator was qdisc specific and
+ relicts from the time when the estimator was qdisc specific and
> could rely on the rtnl or dev->qdisc_lock:
I've lost some time thinking about this rtnl and checking where
these gen_ functions are used, and how much foolish could be
asking about this here, so, it seems there should be some policy
about commenting required locking in networking - I mean after
reading e.g. sch_generic.c you could wrongly think no comments
means: no locking required. (And probably it would be better/
easier for "the more experienced" to do some supplements, if you
know what I mean...)
>
> - the check whether the list is empty and a timer needs to be started
> when adding a new estimator doesn't take the lock, so it races
> against concurrent additions, which can result in the timer beeing
> added twice or getting reinitialized after being added.
>
> - the new estimator's next pointer is also set without holding the
> lock, again racing against concurrent additions with possible
> list corruption as a result.
>
> - the timer deletion when killing an estimator is also not under
> the lock and races against timer arming when adding a new estimator.
>
> Fix by holding the lock around the entire list addition and initial
> timer arming. Removal is not done explicitly anymore, instead the
> timer function only rearms the timer when there are still estimators
> present.
>
> Signed-off-by: Patrick McHardy <kaber@trash.net>
>
> ---
> commit b6a0c468c258d96c6f132fc71ca74225235bc223
> tree 6f61004cf4810a4826aa5c7477e4d455ae3a5698
> parent 48d8d7ee5dd17c64833e0343ab4ae8ef01cc2648
> author Patrick McHardy <kaber@trash.net> Wed, 27 Jun 2007 17:06:02 +0200
> committer Patrick McHardy <kaber@trash.net> Wed, 27 Jun 2007 17:24:13 +0200
>
> net/core/gen_estimator.c | 27 +++++++++++----------------
> 1 files changed, 11 insertions(+), 16 deletions(-)
>
> diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c
> index 17daf4c..88a7805 100644
> --- a/net/core/gen_estimator.c
> +++ b/net/core/gen_estimator.c
> @@ -127,8 +127,8 @@ static void est_timer(unsigned long arg)
> e->rate_est->pps = (e->avpps+0x1FF)>>10;
> spin_unlock(e->stats_lock);
> }
> -
> - mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4));
> + if (elist[idx].list != NULL)
> + mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4));
> read_unlock(&est_lock);
> }
>
> @@ -152,6 +152,7 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
> {
> struct gen_estimator *est;
> struct gnet_estimator *parm = RTA_DATA(opt);
> + int idx;
>
> if (RTA_PAYLOAD(opt) < sizeof(*parm))
> return -EINVAL;
> @@ -163,7 +164,7 @@ int gen_new_estimator(struct gnet_stats_basic *bstats,
> if (est == NULL)
> return -ENOBUFS;
>
> - est->interval = parm->interval + 2;
> + est->interval = idx = parm->interval + 2;
> est->bstats = bstats;
> est->rate_est = rate_est;
> est->stats_lock = stats_lock;
> @@ -173,16 +174,14 @@ 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);
> - }
> write_lock_bh(&est_lock);
> - elist[est->interval].list = est;
> + if (!elist[idx].timer.function)
I think, here could be more consistency about "!" or "== NULL".
> + setup_timer(&elist[idx].timer, est_timer, est->interval);
...and about idx instead of est->interval.
> + if (elist[est->interval].list == NULL)
idx?
> + mod_timer(&elist[idx].timer, jiffies + ((HZ<<idx)/4));
> +
> + est->next = elist[idx].list;
> + elist[idx].list = est;
> write_unlock_bh(&est_lock);
> return 0;
> }
> @@ -202,7 +201,6 @@ void gen_kill_estimator(struct gnet_stats_basic *bstats,
> struct gen_estimator *est, **pest;
>
> for (idx=0; idx <= EST_MAX_INTERVAL; idx++) {
> - int killed = 0;
> pest = &elist[idx].list;
> while ((est=*pest) != NULL) {
> if (est->rate_est != rate_est || est->bstats != bstats) {
> @@ -215,10 +213,7 @@ void gen_kill_estimator(struct gnet_stats_basic *bstats,
> write_unlock_bh(&est_lock);
>
> kfree(est);
> - killed++;
> }
> - if (killed && elist[idx].list == NULL)
> - del_timer(&elist[idx].timer);
I think this is needed. The old timer could be pending, while
the gen_new_estimator() is run just after this e.g. in
gen_replace_estimator().
> }
> }
>
Regards,
Jarek P.
next prev parent reply other threads:[~2007-06-28 6:46 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <bug-8668-10286@http.bugzilla.kernel.org/>
2007-06-25 5:24 ` [Bugme-new] [Bug 8668] New: HTB Deadlock Andrew Morton
2007-06-25 9:28 ` Patrick McHardy
2007-06-25 9:30 ` Patrick McHardy
2007-06-25 11:37 ` Ranko Zivojnovic
2007-06-27 11:45 ` Jarek Poplawski
2007-06-27 11:44 ` Patrick McHardy
2007-06-27 12:10 ` Jarek Poplawski
2007-06-27 12:30 ` Jarek Poplawski
2007-06-27 14:53 ` Patrick McHardy
2007-06-27 15:09 ` [NET]: gen_estimator: fix locking and timer related bugs [Re: [Bugme-new] [Bug 8668] New: HTB Deadlock] Patrick McHardy
2007-06-27 15:25 ` Patrick McHardy
2007-06-28 6:54 ` Jarek Poplawski [this message]
2007-06-28 9:56 ` Jarek Poplawski
2007-06-28 9:13 ` Jarek Poplawski
2007-06-28 12:23 ` Patrick McHardy
2007-06-28 13:03 ` Jarek Poplawski
2007-06-28 12:55 ` Patrick McHardy
2007-06-28 13:27 ` Jarek Poplawski
2007-06-29 7:02 ` Jarek Poplawski
2007-06-29 7:56 ` Jarek Poplawski
2007-06-28 7:52 ` [Bugme-new] [Bug 8668] New: HTB Deadlock Jarek Poplawski
2007-06-28 12:24 ` Patrick McHardy
2007-06-28 13:18 ` Jarek Poplawski
2007-06-28 13:16 ` Patrick McHardy
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=20070628065448.GA1618@ff.dom.local \
--to=jarkao2@o2.pl \
--cc=akpm@linux-foundation.org \
--cc=bugme-daemon@kernel-bugs.osdl.org \
--cc=davem@davemloft.net \
--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.