All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kent Overstreet <kmo@daterainc.com>
To: Tejun Heo <tj@kernel.org>
Cc: linux-kernel@vger.kernel.org, axboe@kernel.dk, hch@infradead.org,
	hannes@cmpxchg.org
Subject: Re: [PATCH 9/9] percpu_ref: make INIT_ATOMIC and switch_to_atomic() sticky
Date: Tue, 23 Sep 2014 14:17:27 -0700	[thread overview]
Message-ID: <20140923211727.GJ15142@kmo-pixel> (raw)
In-Reply-To: <1411451718-17807-10-git-send-email-tj@kernel.org>

On Tue, Sep 23, 2014 at 01:55:18AM -0400, Tejun Heo wrote:
> Currently, a percpu_ref which is initialized with
> PERPCU_REF_INIT_ATOMIC or switched to atomic mode via
> switch_to_atomic() automatically reverts to percpu mode on the first
> percpu_ref_reinit().  This makes the atomic mode difficult to use for
> cases where a percpu_ref is used as a persistent on/off switch which
> may be cycled multiple times.
> 
> This patch makes such atomic state sticky so that it survives through
> kill/reinit cycles.  After this patch, atomic state is cleared only by
> an explicit percpu_ref_switch_to_percpu() call.
> 
> Signed-off-by: Tejun Heo <tj@kernel.org>
> Cc: Kent Overstreet <kmo@daterainc.com>
> Cc: Jens Axboe <axboe@kernel.dk>
> Cc: Christoph Hellwig <hch@infradead.org>
> Cc: Johannes Weiner <hannes@cmpxchg.org>

Reviewed-by: Kent Overstreet <kmo@daterainc.com>

> ---
>  include/linux/percpu-refcount.h |  5 ++++-
>  lib/percpu-refcount.c           | 20 +++++++++++++++-----
>  2 files changed, 19 insertions(+), 6 deletions(-)
> 
> diff --git a/include/linux/percpu-refcount.h b/include/linux/percpu-refcount.h
> index 5f84bf0..8459d3a 100644
> --- a/include/linux/percpu-refcount.h
> +++ b/include/linux/percpu-refcount.h
> @@ -65,7 +65,9 @@ enum {
>  enum {
>  	/*
>  	 * Start w/ ref == 1 in atomic mode.  Can be switched to percpu
> -	 * operation using percpu_ref_switch_to_percpu().
> +	 * operation using percpu_ref_switch_to_percpu().  If initialized
> +	 * with this flag, the ref will stay in atomic mode until
> +	 * percpu_ref_switch_to_percpu() is invoked on it.
>  	 */
>  	PERCPU_REF_INIT_ATOMIC	= 1 << 0,
>  
> @@ -85,6 +87,7 @@ struct percpu_ref {
>  	unsigned long		percpu_count_ptr;
>  	percpu_ref_func_t	*release;
>  	percpu_ref_func_t	*confirm_switch;
> +	bool			force_atomic:1;
>  	struct rcu_head		rcu;
>  };
>  
> diff --git a/lib/percpu-refcount.c b/lib/percpu-refcount.c
> index 74ec33e..c47e496 100644
> --- a/lib/percpu-refcount.c
> +++ b/lib/percpu-refcount.c
> @@ -68,6 +68,8 @@ int percpu_ref_init(struct percpu_ref *ref, percpu_ref_func_t *release,
>  	if (!ref->percpu_count_ptr)
>  		return -ENOMEM;
>  
> +	ref->force_atomic = flags & PERCPU_REF_INIT_ATOMIC;
> +
>  	if (flags & (PERCPU_REF_INIT_ATOMIC | PERCPU_REF_INIT_DEAD))
>  		ref->percpu_count_ptr |= __PERCPU_REF_ATOMIC;
>  	else
> @@ -203,7 +205,8 @@ static void __percpu_ref_switch_to_atomic(struct percpu_ref *ref,
>   * are guaraneed to be in atomic mode, @confirm_switch, which may not
>   * block, is invoked.  This function may be invoked concurrently with all
>   * the get/put operations and can safely be mixed with kill and reinit
> - * operations.
> + * operations.  Note that @ref will stay in atomic mode across kill/reinit
> + * cycles until percpu_ref_switch_to_percpu() is called.
>   *
>   * This function normally doesn't block and can be called from any context
>   * but it may block if @confirm_kill is specified and @ref is already in
> @@ -217,6 +220,7 @@ static void __percpu_ref_switch_to_atomic(struct percpu_ref *ref,
>  void percpu_ref_switch_to_atomic(struct percpu_ref *ref,
>  				 percpu_ref_func_t *confirm_switch)
>  {
> +	ref->force_atomic = true;
>  	__percpu_ref_switch_to_atomic(ref, confirm_switch);
>  }
>  
> @@ -256,7 +260,10 @@ void __percpu_ref_switch_to_percpu(struct percpu_ref *ref)
>   *
>   * Switch @ref to percpu mode.  This function may be invoked concurrently
>   * with all the get/put operations and can safely be mixed with kill and
> - * reinit operations.
> + * reinit operations.  This function reverses the sticky atomic state set
> + * by PERCPU_REF_INIT_ATOMIC or percpu_ref_switch_to_atomic().  If @ref is
> + * dying or dead, the actual switching takes place on the following
> + * percpu_ref_reinit().
>   *
>   * This function normally doesn't block and can be called from any context
>   * but it may block if @ref is in the process of switching to atomic mode
> @@ -264,6 +271,8 @@ void __percpu_ref_switch_to_percpu(struct percpu_ref *ref)
>   */
>  void percpu_ref_switch_to_percpu(struct percpu_ref *ref)
>  {
> +	ref->force_atomic = false;
> +
>  	/* a dying or dead ref can't be switched to percpu mode w/o reinit */
>  	if (!(ref->percpu_count_ptr & __PERCPU_REF_DEAD))
>  		__percpu_ref_switch_to_percpu(ref);
> @@ -305,8 +314,8 @@ EXPORT_SYMBOL_GPL(percpu_ref_kill_and_confirm);
>   * @ref: perpcu_ref to re-initialize
>   *
>   * Re-initialize @ref so that it's in the same state as when it finished
> - * percpu_ref_init().  @ref must have been initialized successfully and
> - * reached 0 but not exited.
> + * percpu_ref_init() ignoring %PERCPU_REF_INIT_DEAD.  @ref must have been
> + * initialized successfully and reached 0 but not exited.
>   *
>   * Note that percpu_ref_tryget[_live]() are safe to perform on @ref while
>   * this function is in progress.
> @@ -317,6 +326,7 @@ void percpu_ref_reinit(struct percpu_ref *ref)
>  
>  	ref->percpu_count_ptr &= ~__PERCPU_REF_DEAD;
>  	percpu_ref_get(ref);
> -	__percpu_ref_switch_to_percpu(ref);
> +	if (!ref->force_atomic)
> +		__percpu_ref_switch_to_percpu(ref);
>  }
>  EXPORT_SYMBOL_GPL(percpu_ref_reinit);
> -- 
> 1.9.3
> 

  reply	other threads:[~2014-09-23 21:15 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-09-23  5:55 [PATCHSET percpu/for-3.18] percpu_ref: implement switch_to_atomic/percpu() Tejun Heo
2014-09-23  5:55 ` [PATCH 1/9] percpu_ref: relocate percpu_ref_reinit() Tejun Heo
2014-09-23 21:01   ` Kent Overstreet
2014-09-23 21:07   ` Kent Overstreet
2014-09-23  5:55 ` [PATCH 2/9] percpu_ref: minor code and comment updates Tejun Heo
2014-09-23 21:09   ` Kent Overstreet
2014-09-23  5:55 ` [PATCH 3/9] percpu_ref: replace pcpu_ prefix with percpu_ Tejun Heo
2014-09-23 21:10   ` Kent Overstreet
2014-09-23  5:55 ` [PATCH 4/9] percpu_ref: rename things to prepare for decoupling percpu/atomic mode switch Tejun Heo
2014-09-23 21:11   ` Kent Overstreet
2014-09-23  5:55 ` [PATCH 5/9] percpu_ref: add PCPU_REF_DEAD Tejun Heo
2014-09-23 13:48   ` [PATCH v2 " Tejun Heo
2014-09-23 21:14     ` Kent Overstreet
2014-09-23  5:55 ` [PATCH 6/9] percpu_ref: decouple switching to atomic mode and killing Tejun Heo
2014-09-23 21:13   ` Kent Overstreet
2014-09-23  5:55 ` [PATCH 7/9] percpu_ref: decouple switching to percpu mode and reinit Tejun Heo
2014-09-23 13:49   ` [PATCH v2 " Tejun Heo
2014-09-23 21:15     ` Kent Overstreet
2014-09-23  5:55 ` [PATCH 8/9] percpu_ref: add PERCPU_REF_INIT_* flags Tejun Heo
2014-09-23 21:16   ` Kent Overstreet
2014-09-23  5:55 ` [PATCH 9/9] percpu_ref: make INIT_ATOMIC and switch_to_atomic() sticky Tejun Heo
2014-09-23 21:17   ` Kent Overstreet [this message]
2014-09-24 17:32 ` [PATCHSET percpu/for-3.18] percpu_ref: implement switch_to_atomic/percpu() Tejun Heo

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=20140923211727.GJ15142@kmo-pixel \
    --to=kmo@daterainc.com \
    --cc=axboe@kernel.dk \
    --cc=hannes@cmpxchg.org \
    --cc=hch@infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=tj@kernel.org \
    /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.