From: Dave Chinner <david@fromorbit.com>
To: Alex Elder <aelder@sgi.com>
Cc: XFS Mailing List <xfs@oss.sgi.com>
Subject: Re: [PATCH 2/5] percpu_counter: avoid potential underflow in add_unless_lt
Date: Thu, 23 Dec 2010 17:39:57 +1100 [thread overview]
Message-ID: <20101223063957.GG18264@dastard> (raw)
In-Reply-To: <1293076587.2408.431.camel@doink>
On Wed, Dec 22, 2010 at 09:56:27PM -0600, Alex Elder wrote:
> In __percpu_counter_add_unless_lt(), an assumption is made that
> under certain conditions it's possible to determine that an amount
> can be safely added to a counter, possibly without having to acquire
> the lock. This assumption is not valid, however.
>
> These lines encode the assumption:
> if (count + amount > threshold + error) {
> __percpu_counter_add(fbc, amount, batch);
>
> Inside __percpu_counter_add(), the addition is performed
> without acquiring the lock if the *sum* of the batch size
> and the CPU-local delta is within the batch size. Otherwise
> it does the addition after acquiring the lock.
>
> The problem is that *that* sum may actually end up being greater
> than the batch size, forcing the addition to be performed under
> protection of the lock. And by the time the lock is acquired, the
> value of fbc->count may have been updated such that adding the given
> amount allows the result to go negative.
>
> Fix this by open-coding the portion of the __percpu_counter_add()
> that avoids the lock.
>
> Signed-off-by: Alex Elder <aelder@sgi.com>
>
> ---
> lib/percpu_counter.c | 11 ++++++++---
> 1 file changed, 8 insertions(+), 3 deletions(-)
>
> Index: b/lib/percpu_counter.c
> ===================================================================
> --- a/lib/percpu_counter.c
> +++ b/lib/percpu_counter.c
> @@ -243,9 +243,14 @@ int __percpu_counter_add_unless_lt(struc
> * we can safely add, and might be able to avoid locking.
> */
> if (count + amount > threshold + error) {
> - __percpu_counter_add(fbc, amount, batch);
> - ret = 1;
> - goto out;
> + s32 *pcount = this_cpu_ptr(fbc->counters);
> +
> + count = *pcount + amount;
> + if (abs(count) < batch) {
> + *pcount = count;
> + ret = 1;
> + goto out;
> + }
> }
The problem with this is that it never zeros pcount. That means
after a bunch of increments or decrements, abs(*pcount) == 31,
and ever further increment/decrement will drop through to the path
that requires locking. Then we simply have a very expensive global
counter.
We need to take the lock to zero the pcount value because it has to
be added to fbc->count. i.e. if you want this path to remain mostly
lockless, then it needs to do exactly what __percpu_counter_add()
does....
Cheers,
Dave.
--
Dave Chinner
david@fromorbit.com
_______________________________________________
xfs mailing list
xfs@oss.sgi.com
http://oss.sgi.com/mailman/listinfo/xfs
next prev parent reply other threads:[~2010-12-23 6:38 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-12-23 3:56 [PATCH 2/5] percpu_counter: avoid potential underflow in add_unless_lt Alex Elder
2010-12-23 6:39 ` Dave Chinner [this message]
2010-12-29 20:56 ` Alex Elder
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=20101223063957.GG18264@dastard \
--to=david@fromorbit.com \
--cc=aelder@sgi.com \
--cc=xfs@oss.sgi.com \
/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.