aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorRoman Gushchin <guro@fb.com>2019-05-07 13:01:50 -0400
committerDennis Zhou <dennis@kernel.org>2019-05-09 13:51:06 -0400
commit7d9ab9b6adffd9c474c1274acb5f6208f9a09cf3 (patch)
tree461ee811d60454e5e21fb6f567ec2e2435575a12 /lib
parentddde2af747ad79010f14691f381522987fbcb860 (diff)
percpu_ref: release percpu memory early without PERCPU_REF_ALLOW_REINIT
Release percpu memory after finishing the switch to the atomic mode if only PERCPU_REF_ALLOW_REINIT isn't set. Signed-off-by: Roman Gushchin <guro@fb.com> Acked-by: Tejun Heo <tj@kernel.org> Signed-off-by: Dennis Zhou <dennis@kernel.org>
Diffstat (limited to 'lib')
-rw-r--r--lib/percpu-refcount.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/lib/percpu-refcount.c b/lib/percpu-refcount.c
index 9877682e49c7..501b517bd3db 100644
--- a/lib/percpu-refcount.c
+++ b/lib/percpu-refcount.c
@@ -69,11 +69,14 @@ int percpu_ref_init(struct percpu_ref *ref, percpu_ref_func_t *release,
69 return -ENOMEM; 69 return -ENOMEM;
70 70
71 ref->force_atomic = flags & PERCPU_REF_INIT_ATOMIC; 71 ref->force_atomic = flags & PERCPU_REF_INIT_ATOMIC;
72 ref->allow_reinit = flags & PERCPU_REF_ALLOW_REINIT;
72 73
73 if (flags & (PERCPU_REF_INIT_ATOMIC | PERCPU_REF_INIT_DEAD)) 74 if (flags & (PERCPU_REF_INIT_ATOMIC | PERCPU_REF_INIT_DEAD)) {
74 ref->percpu_count_ptr |= __PERCPU_REF_ATOMIC; 75 ref->percpu_count_ptr |= __PERCPU_REF_ATOMIC;
75 else 76 ref->allow_reinit = true;
77 } else {
76 start_count += PERCPU_COUNT_BIAS; 78 start_count += PERCPU_COUNT_BIAS;
79 }
77 80
78 if (flags & PERCPU_REF_INIT_DEAD) 81 if (flags & PERCPU_REF_INIT_DEAD)
79 ref->percpu_count_ptr |= __PERCPU_REF_DEAD; 82 ref->percpu_count_ptr |= __PERCPU_REF_DEAD;
@@ -119,6 +122,9 @@ static void percpu_ref_call_confirm_rcu(struct rcu_head *rcu)
119 ref->confirm_switch = NULL; 122 ref->confirm_switch = NULL;
120 wake_up_all(&percpu_ref_switch_waitq); 123 wake_up_all(&percpu_ref_switch_waitq);
121 124
125 if (!ref->allow_reinit)
126 percpu_ref_exit(ref);
127
122 /* drop ref from percpu_ref_switch_to_atomic() */ 128 /* drop ref from percpu_ref_switch_to_atomic() */
123 percpu_ref_put(ref); 129 percpu_ref_put(ref);
124} 130}
@@ -194,6 +200,9 @@ static void __percpu_ref_switch_to_percpu(struct percpu_ref *ref)
194 if (!(ref->percpu_count_ptr & __PERCPU_REF_ATOMIC)) 200 if (!(ref->percpu_count_ptr & __PERCPU_REF_ATOMIC))
195 return; 201 return;
196 202
203 if (WARN_ON_ONCE(!ref->allow_reinit))
204 return;
205
197 atomic_long_add(PERCPU_COUNT_BIAS, &ref->count); 206 atomic_long_add(PERCPU_COUNT_BIAS, &ref->count);
198 207
199 /* 208 /*