lkml.org 
[lkml]   [2007]   [Jun]   [8]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[patch 27/54] timer statistics: fix race
    -stable review patch.  If anyone has any objections, please let us know.
    ---------------------

    From: Bjorn Steinbrink <B.Steinbrink@gmx.de>

    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 any "pre-inserted" entries.

    Thanks to Eric Dumazet for reminding me of the memory barriers.

    Signed-off-by: Bjorn Steinbrink <B.Steinbrink@gmx.de>
    Signed-off-by: Ian Kumlien <pomac@vapor.com>
    Acked-by: Ingo Molnar <mingo@elte.hu>
    Cc: Eric Dumazet <dada1@cosmosbay.com>
    Cc: Thomas Gleixner <tglx@linutronix.de>
    Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
    Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: Chris Wright <chrisw@sous-sol.org>
    Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
    ---
    kernel/time/timer_stats.c | 37 +++++++++++++++++++++----------------
    1 file changed, 21 insertions(+), 16 deletions(-)

    --- linux-2.6.21.4.orig/kernel/time/timer_stats.c
    +++ linux-2.6.21.4/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
    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);
    @@ -364,6 +368,7 @@ static ssize_t tstats_write(struct file
    if (!active) {
    reset_entries();
    time_start = ktime_get();
    + smp_mb();
    active = 1;
    }
    break;
    --
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

    \
     
     \ /
      Last update: 2007-06-08 09:59    [W:0.026 / U:88.604 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site