aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-10-10 07:26:02 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-10-10 07:26:02 -0400
commitc798360cd1438090d51eeaa8e67985da11362eba (patch)
tree0107d3b9ee7476264c3357287787d393545bd2d9 /lib
parentb211e9d7c861bdb37b86d6384da9edfb80949ceb (diff)
parent6ae833c7fe0c6ef1f0ab13cc775da230d6f4c256 (diff)
Merge branch 'for-3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu
Pull percpu updates from Tejun Heo: "A lot of activities on percpu front. Notable changes are... - percpu allocator now can take @gfp. If @gfp doesn't contain GFP_KERNEL, it tries to allocate from what's already available to the allocator and a work item tries to keep the reserve around certain level so that these atomic allocations usually succeed. This will replace the ad-hoc percpu memory pool used by blk-throttle and also be used by the planned blkcg support for writeback IOs. Please note that I noticed a bug in how @gfp is interpreted while preparing this pull request and applied the fix 6ae833c7fe0c ("percpu: fix how @gfp is interpreted by the percpu allocator") just now. - percpu_ref now uses longs for percpu and global counters instead of ints. It leads to more sparse packing of the percpu counters on 64bit machines but the overhead should be negligible and this allows using percpu_ref for refcnting pages and in-memory objects directly. - The switching between percpu and single counter modes of a percpu_ref is made independent of putting the base ref and a percpu_ref can now optionally be initialized in single or killed mode. This allows avoiding percpu shutdown latency for cases where the refcounted objects may be synchronously created and destroyed in rapid succession with only a fraction of them reaching fully operational status (SCSI probing does this when combined with blk-mq support). It's also planned to be used to implement forced single mode to detect underflow more timely for debugging. There's a separate branch percpu/for-3.18-consistent-ops which cleans up the duplicate percpu accessors. That branch causes a number of conflicts with s390 and other trees. I'll send a separate pull request w/ resolutions once other branches are merged" * 'for-3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/percpu: (33 commits) percpu: fix how @gfp is interpreted by the percpu allocator blk-mq, percpu_ref: start q->mq_usage_counter in atomic mode percpu_ref: make INIT_ATOMIC and switch_to_atomic() sticky percpu_ref: add PERCPU_REF_INIT_* flags percpu_ref: decouple switching to percpu mode and reinit percpu_ref: decouple switching to atomic mode and killing percpu_ref: add PCPU_REF_DEAD percpu_ref: rename things to prepare for decoupling percpu/atomic mode switch percpu_ref: replace pcpu_ prefix with percpu_ percpu_ref: minor code and comment updates percpu_ref: relocate percpu_ref_reinit() Revert "blk-mq, percpu_ref: implement a kludge for SCSI blk-mq stall during probe" Revert "percpu: free percpu allocation info for uniprocessor system" percpu-refcount: make percpu_ref based on longs instead of ints percpu-refcount: improve WARN messages percpu: fix locking regression in the failure path of pcpu_alloc() percpu-refcount: add @gfp to percpu_ref_init() proportions: add @gfp to init functions percpu_counter: add @gfp to percpu_counter_init() percpu_counter: make percpu_counters_lock irq-safe ...
Diffstat (limited to 'lib')
-rw-r--r--lib/flex_proportions.c8
-rw-r--r--lib/percpu-refcount.c305
-rw-r--r--lib/percpu_counter.c20
-rw-r--r--lib/proportions.c10
4 files changed, 238 insertions, 105 deletions
diff --git a/lib/flex_proportions.c b/lib/flex_proportions.c
index ebf3bac460b0..8f25652f40d4 100644
--- a/lib/flex_proportions.c
+++ b/lib/flex_proportions.c
@@ -34,13 +34,13 @@
34 */ 34 */
35#include <linux/flex_proportions.h> 35#include <linux/flex_proportions.h>
36 36
37int fprop_global_init(struct fprop_global *p) 37int fprop_global_init(struct fprop_global *p, gfp_t gfp)
38{ 38{
39 int err; 39 int err;
40 40
41 p->period = 0; 41 p->period = 0;
42 /* Use 1 to avoid dealing with periods with 0 events... */ 42 /* Use 1 to avoid dealing with periods with 0 events... */
43 err = percpu_counter_init(&p->events, 1); 43 err = percpu_counter_init(&p->events, 1, gfp);
44 if (err) 44 if (err)
45 return err; 45 return err;
46 seqcount_init(&p->sequence); 46 seqcount_init(&p->sequence);
@@ -168,11 +168,11 @@ void fprop_fraction_single(struct fprop_global *p,
168 */ 168 */
169#define PROP_BATCH (8*(1+ilog2(nr_cpu_ids))) 169#define PROP_BATCH (8*(1+ilog2(nr_cpu_ids)))
170 170
171int fprop_local_init_percpu(struct fprop_local_percpu *pl) 171int fprop_local_init_percpu(struct fprop_local_percpu *pl, gfp_t gfp)
172{ 172{
173 int err; 173 int err;
174 174
175 err = percpu_counter_init(&pl->events, 0); 175 err = percpu_counter_init(&pl->events, 0, gfp);
176 if (err) 176 if (err)
177 return err; 177 return err;
178 pl->period = 0; 178 pl->period = 0;
diff --git a/lib/percpu-refcount.c b/lib/percpu-refcount.c
index a89cf09a8268..6111bcb28376 100644
--- a/lib/percpu-refcount.c
+++ b/lib/percpu-refcount.c
@@ -1,6 +1,8 @@
1#define pr_fmt(fmt) "%s: " fmt "\n", __func__ 1#define pr_fmt(fmt) "%s: " fmt "\n", __func__
2 2
3#include <linux/kernel.h> 3#include <linux/kernel.h>
4#include <linux/sched.h>
5#include <linux/wait.h>
4#include <linux/percpu-refcount.h> 6#include <linux/percpu-refcount.h>
5 7
6/* 8/*
@@ -11,8 +13,8 @@
11 * percpu counters will all sum to the correct value 13 * percpu counters will all sum to the correct value
12 * 14 *
13 * (More precisely: because moduler arithmatic is commutative the sum of all the 15 * (More precisely: because moduler arithmatic is commutative the sum of all the
14 * pcpu_count vars will be equal to what it would have been if all the gets and 16 * percpu_count vars will be equal to what it would have been if all the gets
15 * puts were done to a single integer, even if some of the percpu integers 17 * and puts were done to a single integer, even if some of the percpu integers
16 * overflow or underflow). 18 * overflow or underflow).
17 * 19 *
18 * The real trick to implementing percpu refcounts is shutdown. We can't detect 20 * The real trick to implementing percpu refcounts is shutdown. We can't detect
@@ -25,75 +27,64 @@
25 * works. 27 * works.
26 * 28 *
27 * Converting to non percpu mode is done with some RCUish stuff in 29 * Converting to non percpu mode is done with some RCUish stuff in
28 * percpu_ref_kill. Additionally, we need a bias value so that the atomic_t 30 * percpu_ref_kill. Additionally, we need a bias value so that the
29 * can't hit 0 before we've added up all the percpu refs. 31 * atomic_long_t can't hit 0 before we've added up all the percpu refs.
30 */ 32 */
31 33
32#define PCPU_COUNT_BIAS (1U << 31) 34#define PERCPU_COUNT_BIAS (1LU << (BITS_PER_LONG - 1))
33 35
34static unsigned __percpu *pcpu_count_ptr(struct percpu_ref *ref) 36static DECLARE_WAIT_QUEUE_HEAD(percpu_ref_switch_waitq);
37
38static unsigned long __percpu *percpu_count_ptr(struct percpu_ref *ref)
35{ 39{
36 return (unsigned __percpu *)(ref->pcpu_count_ptr & ~PCPU_REF_DEAD); 40 return (unsigned long __percpu *)
41 (ref->percpu_count_ptr & ~__PERCPU_REF_ATOMIC_DEAD);
37} 42}
38 43
39/** 44/**
40 * percpu_ref_init - initialize a percpu refcount 45 * percpu_ref_init - initialize a percpu refcount
41 * @ref: percpu_ref to initialize 46 * @ref: percpu_ref to initialize
42 * @release: function which will be called when refcount hits 0 47 * @release: function which will be called when refcount hits 0
48 * @flags: PERCPU_REF_INIT_* flags
49 * @gfp: allocation mask to use
43 * 50 *
44 * Initializes the refcount in single atomic counter mode with a refcount of 1; 51 * Initializes @ref. If @flags is zero, @ref starts in percpu mode with a
45 * analagous to atomic_set(ref, 1). 52 * refcount of 1; analagous to atomic_long_set(ref, 1). See the
53 * definitions of PERCPU_REF_INIT_* flags for flag behaviors.
46 * 54 *
47 * Note that @release must not sleep - it may potentially be called from RCU 55 * Note that @release must not sleep - it may potentially be called from RCU
48 * callback context by percpu_ref_kill(). 56 * callback context by percpu_ref_kill().
49 */ 57 */
50int percpu_ref_init(struct percpu_ref *ref, percpu_ref_func_t *release) 58int percpu_ref_init(struct percpu_ref *ref, percpu_ref_func_t *release,
59 unsigned int flags, gfp_t gfp)
51{ 60{
52 atomic_set(&ref->count, 1 + PCPU_COUNT_BIAS); 61 size_t align = max_t(size_t, 1 << __PERCPU_REF_FLAG_BITS,
62 __alignof__(unsigned long));
63 unsigned long start_count = 0;
53 64
54 ref->pcpu_count_ptr = (unsigned long)alloc_percpu(unsigned); 65 ref->percpu_count_ptr = (unsigned long)
55 if (!ref->pcpu_count_ptr) 66 __alloc_percpu_gfp(sizeof(unsigned long), align, gfp);
67 if (!ref->percpu_count_ptr)
56 return -ENOMEM; 68 return -ENOMEM;
57 69
58 ref->release = release; 70 ref->force_atomic = flags & PERCPU_REF_INIT_ATOMIC;
59 return 0;
60}
61EXPORT_SYMBOL_GPL(percpu_ref_init);
62
63/**
64 * percpu_ref_reinit - re-initialize a percpu refcount
65 * @ref: perpcu_ref to re-initialize
66 *
67 * Re-initialize @ref so that it's in the same state as when it finished
68 * percpu_ref_init(). @ref must have been initialized successfully, killed
69 * and reached 0 but not exited.
70 *
71 * Note that percpu_ref_tryget[_live]() are safe to perform on @ref while
72 * this function is in progress.
73 */
74void percpu_ref_reinit(struct percpu_ref *ref)
75{
76 unsigned __percpu *pcpu_count = pcpu_count_ptr(ref);
77 int cpu;
78 71
79 BUG_ON(!pcpu_count); 72 if (flags & (PERCPU_REF_INIT_ATOMIC | PERCPU_REF_INIT_DEAD))
80 WARN_ON(!percpu_ref_is_zero(ref)); 73 ref->percpu_count_ptr |= __PERCPU_REF_ATOMIC;
74 else
75 start_count += PERCPU_COUNT_BIAS;
81 76
82 atomic_set(&ref->count, 1 + PCPU_COUNT_BIAS); 77 if (flags & PERCPU_REF_INIT_DEAD)
78 ref->percpu_count_ptr |= __PERCPU_REF_DEAD;
79 else
80 start_count++;
83 81
84 /* 82 atomic_long_set(&ref->count, start_count);
85 * Restore per-cpu operation. smp_store_release() is paired with
86 * smp_read_barrier_depends() in __pcpu_ref_alive() and guarantees
87 * that the zeroing is visible to all percpu accesses which can see
88 * the following PCPU_REF_DEAD clearing.
89 */
90 for_each_possible_cpu(cpu)
91 *per_cpu_ptr(pcpu_count, cpu) = 0;
92 83
93 smp_store_release(&ref->pcpu_count_ptr, 84 ref->release = release;
94 ref->pcpu_count_ptr & ~PCPU_REF_DEAD); 85 return 0;
95} 86}
96EXPORT_SYMBOL_GPL(percpu_ref_reinit); 87EXPORT_SYMBOL_GPL(percpu_ref_init);
97