diff options
author | Roman Gushchin <guro@fb.com> | 2019-05-07 13:01:50 -0400 |
---|---|---|
committer | Dennis Zhou <dennis@kernel.org> | 2019-05-09 13:51:06 -0400 |
commit | 7d9ab9b6adffd9c474c1274acb5f6208f9a09cf3 (patch) | |
tree | 461ee811d60454e5e21fb6f567ec2e2435575a12 /lib | |
parent | ddde2af747ad79010f14691f381522987fbcb860 (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.c | 13 |
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 | /* |