From: Eric Dumazet <dada1@cosmosbay.com>
To: "Björn Steinbrink" <B.Steinbrink@gmx.de>
Cc: iank@bredband.net, Thomas Gleixner <tglx@linutronix.de>,
Michal Piotrowski <michal.k.k.piotrowski@gmail.com>,
Ingo Molnar <mingo@elte.hu>,
Arjan van de Ven <arjan@infradead.org>,
linux-kernel@vger.kernel.org
Subject: Re: [BUG] Something goes wrong with timer statistics.
Date: Thu, 31 May 2007 17:10:07 +0200 [thread overview]
Message-ID: <20070531171007.5780e5e6.dada1@cosmosbay.com> (raw)
In-Reply-To: <20070531142522.GA16690@atjola.homenet>
On Thu, 31 May 2007 16:25:22 +0200
Björn Steinbrink <B.Steinbrink@gmx.de> wrote:
> On 2007.05.31 12:20:47 +0200, iank@bredband.net wrote:
> > On Wed, May 30, 2007 at 03:14:58PM +0200, Björn Steinbrink wrote:
> > > Initialize the "next" field of a timer stats entry before it is inserted
> > > into the list to avoid a race with the fastpath lookup.
> >
> > Sorry to say... but this does not fix my problem, however, i can't reach
> > that machine at all atm, but i will post the oops later today.
>
> Ok, three times is a charm, right? ;-) The previous patch did fix a
> race, but there's still one left. The hash table is never cleared, so it
> can still point into the entries array.
>
> As long as we do not race with the insertion, that's not a directly
> visible problem as all fields are 0, so we get no match and the lookup
> finishes right away. We probably _can_ get weird results though, as the
> all-zero entry isn't marked as used, but is used as "head" and "prev" in
> this case and even multiple hash entries might point to it in some
> cases. That would eventually lead to lost entries because the "next"
> field gets overwritten when alloc_entry() finally claims the entry.
>
> But when we race, we can still end up between "*curr = *entry" (makes
> "next" contain garbage) and "curr->next = NULL", while we're doing the
> fastpath lookup, because the insertion basically already took place!
> Replacing "curr->next = NULL" with "entry->next = NULL" and moving it up
> is pointless, as "*curr = *entry" isn't atomic, so instead, we have to
> simply clean the hash table when the entries are cleared.
>
> Björn
>
>
> Fix two races in the timer stats lookup code. One by ensuring that the
> initialization of a new entry is finished upon insertion of that entry.
> The other by cleaning up the hash table when the entries array is
> cleared, so that we don't have "pre-inserted" entries.
>
> Thanks to Eric Dumazet for reminding me of the memory barrier.
>
> Signed-off-by: Björn Steinbrink <B.Steinbrink@gmx.de>
> ---
> diff --git a/kernel/time/timer_stats.c b/kernel/time/timer_stats.c
> index 868f1bc..611b844 100644
> --- a/kernel/time/timer_stats.c
> +++ b/kernel/time/timer_stats.c
> @@ -117,21 +117,6 @@ static struct entry entries[MAX_ENTRIES];
>
> static atomic_t overflow_count;
>
> -static void reset_entries(void)
> -{
> - nr_entries = 0;
> - memset(entries, 0, sizeof(entries));
> - atomic_set(&overflow_count, 0);
> -}
> -
> -static struct entry *alloc_entry(void)
> -{
> - if (nr_entries >= MAX_ENTRIES)
> - return NULL;
> -
> - return entries + nr_entries++;
> -}
> -
> /*
> * The entries are in a hash-table, for fast lookup:
> */
> @@ -149,6 +134,22 @@ static struct entry *alloc_entry(void)
>
> static struct entry *tstat_hash_table[TSTAT_HASH_SIZE] __read_mostly;
>
> +static void reset_entries(void)
> +{
> + nr_entries = 0;
> + memset(entries, 0, sizeof(entries));
> + memset(tstat_hash_table, 0, sizeof(tstat_hash_table));
> + atomic_set(&overflow_count, 0);
> +}
> +
> +static struct entry *alloc_entry(void)
> +{
> + if (nr_entries >= MAX_ENTRIES)
> + return NULL;
> +
> + return entries + nr_entries++;
> +}
> +
> static int match_entries(struct entry *entry1, struct entry *entry2)
> {
> return entry1->timer == entry2->timer &&
> @@ -202,12 +203,15 @@ static struct entry *tstat_lookup(struct entry *entry, char *comm)
> if (curr) {
> *curr = *entry;
> curr->count = 0;
> + curr->next = NULL;
> memcpy(curr->comm, comm, TASK_COMM_LEN);
> +
> + smp_mb(); /* Ensure that curr is initialized before insert */
> +
> if (prev)
> prev->next = curr;
> else
> *head = curr;
> - curr->next = NULL;
> }
> out_unlock:
> spin_unlock(&table_lock);
> -
Well... :) , there is still a memory barrier missing it seems.
Another cpu might see a bad value if 'active=1' is set before tstat_hash_table is really cleared.
diff -urp linux/kernel/time/timer_stats.c.orig linux/kernel/time/timer_stats.c
--- kernel/time/timer_stats.c.orig
+++ kernel/time/timer_stats.c
@@ -361,6 +361,7 @@ static ssize_t tstats_write(struct file
if (!active) {
reset_entries();
time_start = ktime_get();
+ smp_mb();
active = 1;
}
break;
next prev parent reply other threads:[~2007-05-31 15:10 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2007-05-29 21:38 [BUG] Something goes wrong with timer statistics Ian Kumlien
[not found] ` <6bffcb0e0705291524y2752d646p94b0bf6ca87af68f@mail.gmail.com>
2007-05-29 22:35 ` Ian Kumlien
2007-05-29 22:38 ` Thomas Gleixner
2007-05-29 22:50 ` Ian Kumlien
2007-05-30 6:52 ` Björn Steinbrink
2007-05-30 7:10 ` Björn Steinbrink
2007-05-30 11:38 ` Björn Steinbrink
2007-05-30 12:44 ` Eric Dumazet
2007-05-30 13:14 ` Björn Steinbrink
[not found] ` <20070531102047.GG19272@pomac.netswarm.net>
2007-05-31 14:25 ` Björn Steinbrink
2007-05-31 15:10 ` Eric Dumazet [this message]
2007-05-31 15:27 ` Björn Steinbrink
2007-05-31 22:59 ` Ian Kumlien
2007-05-31 23:09 ` Björn Steinbrink
2007-06-01 6:21 ` Ingo Molnar
2007-05-29 22:37 ` David Miller
2007-05-29 22:42 ` Thomas Gleixner
2007-05-29 22:44 ` David Miller
2007-05-29 22:53 ` Thomas Gleixner
[not found] ` <6bffcb0e0705291541q7e6d6faen5cd6345074c4c92a@mail.gmail.com>
2007-05-29 22:44 ` David Miller
2007-05-29 22:51 ` Ian Kumlien
2007-05-29 23:03 ` David Miller
2007-05-30 0:04 ` Ian Kumlien
2007-05-30 0:13 ` Stephane Casset
2007-05-31 23:53 ` Björn Steinbrink
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=20070531171007.5780e5e6.dada1@cosmosbay.com \
--to=dada1@cosmosbay.com \
--cc=B.Steinbrink@gmx.de \
--cc=arjan@infradead.org \
--cc=iank@bredband.net \
--cc=linux-kernel@vger.kernel.org \
--cc=michal.k.k.piotrowski@gmail.com \
--cc=mingo@elte.hu \
--cc=tglx@linutronix.de \
/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.