aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2018-03-14 15:45:12 -0400
committerTejun Heo <tj@kernel.org>2018-03-19 13:09:44 -0400
commitb3a5d111994450909158929560906f2c1c6c1d85 (patch)
tree2c6c4c0a295c3522ed41e47b63ba6b84356bfe28
parentf52ba1fef7b92e74d58efef8eae7b6f48c6d218d (diff)
percpu_ref: Update doc to dissuade users from depending on internal RCU grace periods
percpu_ref internally uses sched-RCU to implement the percpu -> atomic mode switching and the documentation suggested that this could be depended upon. This doesn't seem like a good idea. * percpu_ref uses sched-RCU which has different grace periods regular RCU. Users may combine percpu_ref with regular RCU usage and incorrectly believe that regular RCU grace periods are performed by percpu_ref. This can lead to, for example, use-after-free due to premature freeing. * percpu_ref has a grace period when switching from percpu to atomic mode. It doesn't have one between the last put and release. This distinction is subtle and can lead to surprising bugs. * percpu_ref allows starting in and switching to atomic mode manually for debugging and other purposes. This means that there may not be any grace periods from kill to release. This patch makes it clear that the grace periods are percpu_ref's internal implementation detail and can't be depended upon by the users. Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Kent Overstreet <kent.overstreet@gmail.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r--include/linux/percpu-refcount.h18
-rw-r--r--lib/percpu-refcount.c2
2 files changed, 14 insertions, 6 deletions
diff --git a/include/linux/percpu-refcount.h b/include/linux/percpu-refcount.h
index 864d167a1073..009cdf3d65b6 100644
--- a/include/linux/percpu-refcount.h
+++ b/include/linux/percpu-refcount.h
@@ -30,10 +30,14 @@
30 * calls io_destroy() or the process exits. 30 * calls io_destroy() or the process exits.
31 * 31 *
32 * In the aio code, kill_ioctx() is called when we wish to destroy a kioctx; it 32 * In the aio code, kill_ioctx() is called when we wish to destroy a kioctx; it
33 * calls percpu_ref_kill(), then hlist_del_rcu() and synchronize_rcu() to remove 33 * removes the kioctx from the proccess's table of kioctxs and kills percpu_ref.
34 * the kioctx from the proccess's list of kioctxs - after that, there can't be 34 * After that, there can't be any new users of the kioctx (from lookup_ioctx())
35 * any new users of the kioctx (from lookup_ioctx()) and it's then safe to drop 35 * and it's then safe to drop the initial ref with percpu_ref_put().
36 * the initial ref with percpu_ref_put(). 36 *
37 * Note that the free path, free_ioctx(), needs to go through explicit call_rcu()
38 * to synchronize with RCU protected lookup_ioctx(). percpu_ref operations don't
39 * imply RCU grace periods of any kind and if a user wants to combine percpu_ref
40 * with RCU protection, it must be done explicitly.
37 * 41 *
38 * Code that does a two stage shutdown like this often needs some kind of 42 * Code that does a two stage shutdown like this often needs some kind of
39 * explicit synchronization to ensure the initial refcount can only be dropped 43 * explicit synchronization to ensure the initial refcount can only be dropped
@@ -113,8 +117,10 @@ void percpu_ref_reinit(struct percpu_ref *ref);
113 * Must be used to drop the initial ref on a percpu refcount; must be called 117 * Must be used to drop the initial ref on a percpu refcount; must be called
114 * precisely once before shutdown. 118 * precisely once before shutdown.
115 * 119 *
116 * Puts @ref in non percpu mode, then does a call_rcu() before gathering up the 120 * Switches @ref into atomic mode before gathering up the percpu counters
117 * percpu counters and dropping the initial ref. 121 * and dropping the initial ref.
122 *
123 * There are no implied RCU grace periods between kill and release.
118 */ 124 */
119static inline void percpu_ref_kill(struct percpu_ref *ref) 125static inline void percpu_ref_kill(struct percpu_ref *ref)
120{ 126{
diff --git a/lib/percpu-refcount.c b/lib/percpu-refcount.c
index 30e7dd88148b..9f96fa7bc000 100644
--- a/lib/percpu-refcount.c
+++ b/lib/percpu-refcount.c
@@ -322,6 +322,8 @@ EXPORT_SYMBOL_GPL(percpu_ref_switch_to_percpu);
322 * This function normally doesn't block and can be called from any context 322 * This function normally doesn't block and can be called from any context
323 * but it may block if @confirm_kill is specified and @ref is in the 323 * but it may block if @confirm_kill is specified and @ref is in the
324 * process of switching to atomic mode by percpu_ref_switch_to_atomic(). 324 * process of switching to atomic mode by percpu_ref_switch_to_atomic().
325 *
326 * There are no implied RCU grace periods between kill and release.
325 */ 327 */
326void percpu_ref_kill_and_confirm(struct percpu_ref *ref, 328void percpu_ref_kill_and_confirm(struct percpu_ref *ref,
327 percpu_ref_func_t *confirm_kill) 329 percpu_ref_func_t *confirm_kill)