17 Jun, 2013

1 commit

  • percpu-refcount was incorrectly using preempt_disable/enable() for RCU
    critical sections against call_rcu(). 6a24474da8 ("percpu-refcount:
    consistently use plain (non-sched) RCU") fixed it by converting the
    preepmtion operations with rcu_read_[un]lock() citing that there isn't
    any advantage in using sched-RCU over using the usual one; however,
    rcu_read_[un]lock() for the preemptible RCU implementation -
    CONFIG_TREE_PREEMPT_RCU, chosen when CONFIG_PREEMPT - are slightly
    more expensive than preempt_disable/enable().

    In a contrived microbench which repeats the followings,

    - percpu_ref_get()
    - copy 32 bytes of data into percpu buffer
    - percpu_put_get()
    - copy 32 bytes of data into percpu buffer

    rcu_read_[un]lock() used in percpu_ref_get/put() makes it go slower by
    about 15% when compared to using sched-RCU.

    As the RCU critical sections are extremely short, using sched-RCU
    shouldn't have any latency implications. Convert to RCU-sched.

    Signed-off-by: Tejun Heo
    Acked-by: Kent Overstreet
    Acked-by: "Paul E. McKenney"
    Cc: Michal Hocko
    Cc: Rusty Russell

    Tejun Heo
     

14 Jun, 2013

3 commits

  • Implement percpu_tryget() which stops giving out references once the
    percpu_ref is visible as killed. Because the refcnt is per-cpu,
    different CPUs will start to see a refcnt as killed at different
    points in time and tryget() may continue to succeed on subset of cpus
    for a while after percpu_ref_kill() returns.

    For use cases where it's necessary to know when all CPUs start to see
    the refcnt as dead, percpu_ref_kill_and_confirm() is added. The new
    function takes an extra argument @confirm_kill which is invoked when
    the refcnt is guaranteed to be viewed as killed on all CPUs.

    While this isn't the prettiest interface, it doesn't force synchronous
    wait and is much safer than requiring the caller to do its own
    call_rcu().

    v2: Patch description rephrased to emphasize that tryget() may
    continue to succeed on some CPUs after kill() returns as suggested
    by Kent.

    v3: Function comment in percpu_ref_kill_and_confirm() updated warning
    people to not depend on the implied RCU grace period from the
    confirm callback as it's an implementation detail.

    Signed-off-by: Tejun Heo
    Slightly-Grumpily-Acked-by: Kent Overstreet

    Tejun Heo
     
  • Normally, percpu_ref_init() initializes and percpu_ref_kill()
    initiates destruction which completes asynchronously. The
    asynchronous destruction can be problematic in init failure path where
    the caller wants to destroy half-constructed object - distinguishing
    half-constructed objects from the usual release method can be painful
    for complex objects.

    This patch implements percpu_ref_cancel_init() which synchronously
    destroys the percpu_ref without invoking release. To avoid
    unintentional misuses, the function requires the ref to have finished
    percpu_ref_init() but never used and triggers WARN otherwise.

    v2: Explain the weird name and usage restriction in the function
    comment.

    Signed-off-by: Tejun Heo
    Acked-by: Kent Overstreet

    Tejun Heo
     
  • …() in percpu_ref_kill_rcu()

    Two small changes.

    * Unlike most init functions, percpu_ref_init() allocates memory and
    may fail. Let's mark it with __must_check in case the caller
    forgets.

    * percpu_ref_kill_rcu() is unnecessarily using ACCESS_ONCE() to
    dereference @ref->pcpu_count, which can be misleading. The pointer
    is guaranteed to be valid and visible and can't change underneath
    the function. Drop ACCESS_ONCE().

    Signed-off-by: Tejun Heo <tj@kernel.org>

    Tejun Heo
     

13 Jun, 2013

2 commits

  • * s/percpu_ref_release/percpu_ref_func_t/ as it's customary to have _t
    postfix for types and the type is gonna be used for a different type
    of callback too.

    * Add @ARG to function comments.

    * Drop unnecessary and unaligned indentation from percpu_ref_init()
    function comment.

    Signed-off-by: Tejun Heo
    Acked-by: Kent Overstreet

    Tejun Heo
     
  • percpu_ref_get/put() are using preempt_disable/enable() while
    percpu_ref_kill() is using plain call_rcu() instead of
    call_rcu_sched(). This is buggy as grace periods of the two may not
    match. Fix it by using plain RCU in percpu_ref_get/put().

    (I suggested using sched RCU in the first place but there's no actual
    benefit in doing so unless we're gonna introduce different variants
    of get/put to be called while preemption is alredy disabled, which we
    definitely shouldn't.)

    Signed-off-by: Tejun Heo
    Reported-by: Rusty Russell
    Acked-by: Kent Overstreet

    Tejun Heo
     

04 Jun, 2013

1 commit

  • This implements a refcount with similar semantics to
    atomic_get()/atomic_dec_and_test() - but percpu.

    It also implements two stage shutdown, as we need it to tear down the
    percpu counts. Before dropping the initial refcount, you must call
    percpu_ref_kill(); this puts the refcount in "shutting down mode" and
    switches back to a single atomic refcount with the appropriate
    barriers (synchronize_rcu()).

    It's also legal to call percpu_ref_kill() multiple times - it only
    returns true once, so callers don't have to reimplement shutdown
    synchronization.

    [akpm@linux-foundation.org: fix build]
    [akpm@linux-foundation.org: coding-style tweak]
    Signed-off-by: Kent Overstreet
    Cc: Zach Brown
    Cc: Felipe Balbi
    Cc: Greg Kroah-Hartman
    Cc: Mark Fasheh
    Cc: Joel Becker
    Cc: Rusty Russell
    Cc: Jens Axboe
    Cc: Asai Thambi S P
    Cc: Selvan Mani
    Cc: Sam Bradshaw
    Cc: Jeff Moyer
    Cc: Al Viro
    Cc: Benjamin LaHaise
    Cc: Tejun Heo
    Cc: Oleg Nesterov
    Cc: Christoph Lameter
    Cc: Ingo Molnar
    Reviewed-by: "Theodore Ts'o"
    Signed-off-by: Tejun Heo

    Kent Overstreet