03 Jun, 2013

1 commit

  • Roman Gushchin discovered that udp4_lib_lookup2() was not reloading
    first item in the rcu protected list, in case the loop was restarted.

    This produced soft lockups as in https://lkml.org/lkml/2013/4/16/37

    rcu_dereference(X)/ACCESS_ONCE(X) seem to not work as intended if X is
    ptr->field :

    In some cases, gcc caches the value or ptr->field in a register.

    Use a barrier() to disallow such caching, as documented in
    Documentation/atomic_ops.txt line 114

    Thanks a lot to Roman for providing analysis and numerous patches.

    Diagnosed-by: Roman Gushchin
    Signed-off-by: Eric Dumazet
    Reported-by: Boris Zhmurov
    Signed-off-by: Roman Gushchin
    Acked-by: Paul E. McKenney
    Signed-off-by: David S. Miller

    Eric Dumazet
     

20 Aug, 2010

1 commit

  • This avoids warnings from missing __rcu annotations
    in the rculist implementation, making it possible to
    use the same lists in both RCU and non-RCU cases.

    We can add rculist annotations later, together with
    lockdep support for rculist, which is missing as well,
    but that may involve changing all the users.

    Signed-off-by: Arnd Bergmann
    Signed-off-by: Paul E. McKenney
    Cc: Pavel Emelyanov
    Cc: Sukadev Bhattiprolu
    Reviewed-by: Josh Triplett

    Arnd Bergmann
     

25 Feb, 2010

1 commit

  • The theory is that use of bare rcu_dereference() is more prone
    to error than use of the RCU list-traversal primitives.
    Therefore, disable lockdep RCU read-side critical-section
    checking in these primitives for the time being. Once all of
    the rcu_dereference() uses have been dealt with, it may be time
    to re-enable lockdep checking for the RCU list-traversal
    primitives.

    Signed-off-by: Paul E. McKenney
    Cc: laijs@cn.fujitsu.com
    Cc: dipankar@in.ibm.com
    Cc: mathieu.desnoyers@polymtl.ca
    Cc: josh@joshtriplett.org
    Cc: dvhltc@us.ibm.com
    Cc: niv@us.ibm.com
    Cc: peterz@infradead.org
    Cc: rostedt@goodmis.org
    Cc: Valdis.Kletnieks@vt.edu
    Cc: dhowells@redhat.com
    LKML-Reference:
    Signed-off-by: Ingo Molnar

    Paul E. McKenney
     

19 Sep, 2009

1 commit

  • Fix a number of whitespace ^Ierrors in the include/linux/rcu*
    and the kernel/rcu* files.

    Signed-off-by: Paul E. McKenney
    Cc: laijs@cn.fujitsu.com
    Cc: dipankar@in.ibm.com
    Cc: akpm@linux-foundation.org
    Cc: mathieu.desnoyers@polymtl.ca
    Cc: josh@joshtriplett.org
    Cc: dvhltc@us.ibm.com
    Cc: niv@us.ibm.com
    Cc: peterz@infradead.org
    Cc: rostedt@goodmis.org
    Cc: Valdis.Kletnieks@vt.edu
    LKML-Reference:
    [ did more checkpatch fixlets ]
    Signed-off-by: Ingo Molnar

    Paul E. McKenney
     

17 Nov, 2008

1 commit

  • hlist uses NULL value to finish a chain.

    hlist_nulls variant use the low order bit set to 1 to signal an end-of-list marker.

    This allows to store many different end markers, so that some RCU lockless
    algos (used in TCP/UDP stack for example) can save some memory barriers in
    fast paths.

    Two new files are added :

    include/linux/list_nulls.h
    - mimics hlist part of include/linux/list.h, derived to hlist_nulls variant

    include/linux/rculist_nulls.h
    - mimics hlist part of include/linux/rculist.h, derived to hlist_nulls variant

    Only four helpers are declared for the moment :

    hlist_nulls_del_init_rcu(), hlist_nulls_del_rcu(),
    hlist_nulls_add_head_rcu() and hlist_nulls_for_each_entry_rcu()

    prefetches() were removed, since an end of list is not anymore NULL value.
    prefetches() could trigger useless (and possibly dangerous) memory transactions.

    Example of use (extracted from __udp4_lib_lookup())

    struct sock *sk, *result;
    struct hlist_nulls_node *node;
    unsigned short hnum = ntohs(dport);
    unsigned int hash = udp_hashfn(net, hnum);
    struct udp_hslot *hslot = &udptable->hash[hash];
    int score, badness;

    rcu_read_lock();
    begin:
    result = NULL;
    badness = -1;
    sk_nulls_for_each_rcu(sk, node, &hslot->head) {
    score = compute_score(sk, net, saddr, hnum, sport,
    daddr, dport, dif);
    if (score > badness) {
    result = sk;
    badness = score;
    }
    }
    /*
    * if the nulls value we got at the end of this lookup is
    * not the expected one, we must restart lookup.
    * We probably met an item that was moved to another chain.
    */
    if (get_nulls_value(node) != hash)
    goto begin;

    if (result) {
    if (unlikely(!atomic_inc_not_zero(&result->sk_refcnt)))
    result = NULL;
    else if (unlikely(compute_score(result, net, saddr, hnum, sport,
    daddr, dport, dif) < badness)) {
    sock_put(result);
    goto begin;
    }
    }
    rcu_read_unlock();
    return result;

    Signed-off-by: Eric Dumazet
    Acked-by: Peter Zijlstra
    Signed-off-by: David S. Miller

    Eric Dumazet