28 Jun, 2014

5 commits

  • Now that explicit invocation of percpu_ref_exit() is necessary to free
    the percpu counter, we can implement percpu_ref_reinit() which
    reinitializes a released percpu_ref. This can be used implement
    scalable gating switch which can be drained and then re-opened without
    worrying about memory allocation failures.

    percpu_ref_is_zero() is added to be used in a sanity check in
    percpu_ref_exit(). As this function will be useful for other purposes
    too, make it a public interface.

    v2: Use smp_read_barrier_depends() instead of smp_load_acquire(). We
    only need data dep barrier and smp_load_acquire() is stronger and
    heavier on some archs. Spotted by Lai Jiangshan.

    Signed-off-by: Tejun Heo
    Cc: Kent Overstreet
    Cc: Christoph Lameter
    Cc: Lai Jiangshan

    Tejun Heo
     
  • Currently, a percpu_ref undoes percpu_ref_init() automatically by
    freeing the allocated percpu area when the percpu_ref is killed.
    While seemingly convenient, this has the following niggles.

    * It's impossible to re-init a released reference counter without
    going through re-allocation.

    * In the similar vein, it's impossible to initialize a percpu_ref
    count with static percpu variables.

    * We need and have an explicit destructor anyway for failure paths -
    percpu_ref_cancel_init().

    This patch removes the automatic percpu counter freeing in
    percpu_ref_kill_rcu() and repurposes percpu_ref_cancel_init() into a
    generic destructor now named percpu_ref_exit(). percpu_ref_destroy()
    is considered but it gets confusing with percpu_ref_kill() while
    "exit" clearly indicates that it's the counterpart of
    percpu_ref_init().

    All percpu_ref_cancel_init() users are updated to invoke
    percpu_ref_exit() instead and explicit percpu_ref_exit() calls are
    added to the destruction path of all percpu_ref users.

    Signed-off-by: Tejun Heo
    Acked-by: Benjamin LaHaise
    Cc: Kent Overstreet
    Cc: Christoph Lameter
    Cc: Benjamin LaHaise
    Cc: Nicholas A. Bellinger
    Cc: Li Zefan

    Tejun Heo
     
  • percpu_ref->pcpu_count is a percpu pointer with a status flag in its
    lowest bit. As such, it always goes through arithmetic operations
    which is very cumbersome to do on a pointer. It has to be first
    casted to unsigned long and then back.

    Let's just make the field unsigned long so that we can skip the first
    casts. While at it, rename it to pcpu_counter_ptr to clarify that
    it's a pointer value.

    Signed-off-by: Tejun Heo
    Cc: Kent Overstreet
    Cc: Christoph Lameter

    Tejun Heo
     
  • * All four percpu_ref_*() operations implemented in the header file
    perform the same operation to determine whether the percpu_ref is
    alive and extract the percpu pointer. Factor out the common logic
    into __pcpu_ref_alive(). This doesn't change the generated code.

    * There are a couple places in percpu-refcount.c which masks out
    PCPU_REF_DEAD to obtain the percpu pointer. Factor it out into
    pcpu_count_ptr().

    * The above changes make the WARN_ON_ONCE() conditional at the top of
    percpu_ref_kill_and_confirm() the only user of REF_STATUS(). Test
    PCPU_REF_DEAD directly and remove REF_STATUS().

    This patch doesn't introduce any functional change.

    Signed-off-by: Tejun Heo
    Cc: Kent Overstreet
    Cc: Christoph Lameter

    Tejun Heo
     
  • percpu-refcount currently reserves two lowest bits of its percpu
    pointer to indicate its state; however, only one bit is used for
    PCPU_REF_DEAD.

    Simplify it by removing PCPU_STATUS_BITS/MASK and testing
    PCPU_REF_DEAD directly. This also allows the compiler to choose a
    more efficient instruction depending on the architecture.

    Signed-off-by: Tejun Heo
    Cc: Kent Overstreet
    Cc: Christoph Lameter

    Tejun Heo
     

21 Jan, 2014

1 commit

  • AIO had a missing get, which led to an ioctx leak - after percpu_ref_kill() the
    ref was 0 so percpu_ref_put() never saw it hit 0.

    This wasn't noticed at the time because it all happened completely silently,
    this adds a WARN() which would've caught the aio bug.

    tj: Used WARN_ONCE() instead of WARN().

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

    Kent Overstreet
     

17 Oct, 2013

1 commit


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

1 commit

  • * 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
     

04 Jun, 2013

2 commits

  • The cmpxchg() was just to ensure the debug check didn't race, which was
    a bit excessive. The caller is supposed to do the appropriate
    synchronization, which means percpu_ref_kill() can just do a simple
    store.

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

    Kent Overstreet
     
  • 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