aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/refcount.h27
-rw-r--r--lib/refcount.c53
2 files changed, 45 insertions, 35 deletions
diff --git a/include/linux/refcount.h b/include/linux/refcount.h
index c36addd27dd5..53c5eca24d83 100644
--- a/include/linux/refcount.h
+++ b/include/linux/refcount.h
@@ -43,17 +43,30 @@ static inline unsigned int refcount_read(const refcount_t *r)
43 return atomic_read(&r->refs); 43 return atomic_read(&r->refs);
44} 44}
45 45
46extern __must_check bool refcount_add_not_zero_checked(unsigned int i, refcount_t *r);
47extern void refcount_add_checked(unsigned int i, refcount_t *r);
48
49extern __must_check bool refcount_inc_not_zero_checked(refcount_t *r);
50extern void refcount_inc_checked(refcount_t *r);
51
52extern __must_check bool refcount_sub_and_test_checked(unsigned int i, refcount_t *r);
53
54extern __must_check bool refcount_dec_and_test_checked(refcount_t *r);
55extern void refcount_dec_checked(refcount_t *r);
56
46#ifdef CONFIG_REFCOUNT_FULL 57#ifdef CONFIG_REFCOUNT_FULL
47extern __must_check bool refcount_add_not_zero(unsigned int i, refcount_t *r);
48extern void refcount_add(unsigned int i, refcount_t *r);
49 58
50extern __must_check bool refcount_inc_not_zero(refcount_t *r); 59#define refcount_add_not_zero refcount_add_not_zero_checked
51extern void refcount_inc(refcount_t *r); 60#define refcount_add refcount_add_checked
61
62#define refcount_inc_not_zero refcount_inc_not_zero_checked
63#define refcount_inc refcount_inc_checked
64
65#define refcount_sub_and_test refcount_sub_and_test_checked
52 66
53extern __must_check bool refcount_sub_and_test(unsigned int i, refcount_t *r); 67#define refcount_dec_and_test refcount_dec_and_test_checked
68#define refcount_dec refcount_dec_checked
54 69
55extern __must_check bool refcount_dec_and_test(refcount_t *r);
56extern void refcount_dec(refcount_t *r);
57#else 70#else
58# ifdef CONFIG_ARCH_HAS_REFCOUNT 71# ifdef CONFIG_ARCH_HAS_REFCOUNT
59# include <asm/refcount.h> 72# include <asm/refcount.h>
diff --git a/lib/refcount.c b/lib/refcount.c
index 4bd842f20749..5c4aaefc0682 100644
--- a/lib/refcount.c
+++ b/lib/refcount.c
@@ -40,10 +40,8 @@
40#include <linux/spinlock.h> 40#include <linux/spinlock.h>
41#include <linux/bug.h> 41#include <linux/bug.h>
42 42
43#ifdef CONFIG_REFCOUNT_FULL
44
45/** 43/**
46 * refcount_add_not_zero - add a value to a refcount unless it is 0 44 * refcount_add_not_zero_checked - add a value to a refcount unless it is 0
47 * @i: the value to add to the refcount 45 * @i: the value to add to the refcount
48 * @r: the refcount 46 * @r: the refcount
49 * 47 *
@@ -60,7 +58,7 @@
60 * 58 *
61 * Return: false if the passed refcount is 0, true otherwise 59 * Return: false if the passed refcount is 0, true otherwise
62 */ 60 */
63bool refcount_add_not_zero(unsigned int i, refcount_t *r) 61bool refcount_add_not_zero_checked(unsigned int i, refcount_t *r)
64{ 62{
65 unsigned int new, val = atomic_read(&r->refs); 63 unsigned int new, val = atomic_read(&r->refs);
66 64
@@ -81,10 +79,10 @@ bool refcount_add_not_zero(unsigned int i, refcount_t *r)
81 79
82 return true; 80 return true;
83} 81}
84EXPORT_SYMBOL(refcount_add_not_zero); 82EXPORT_SYMBOL(refcount_add_not_zero_checked);
85 83
86/** 84/**
87 * refcount_add - add a value to a refcount 85 * refcount_add_checked - add a value to a refcount
88 * @i: the value to add to the refcount 86 * @i: the value to add to the refcount
89 * @r: the refcount 87 * @r: the refcount
90 * 88 *
@@ -99,14 +97,14 @@ EXPORT_SYMBOL(refcount_add_not_zero);
99 * cases, refcount_inc(), or one of its variants, should instead be used to 97 * cases, refcount_inc(), or one of its variants, should instead be used to
100 * increment a reference count. 98 * increment a reference count.
101 */ 99 */
102void refcount_add(unsigned int i, refcount_t *r) 100void refcount_add_checked(unsigned int i, refcount_t *r)
103{ 101{
104 WARN_ONCE(!refcount_add_not_zero(i, r), "refcount_t: addition on 0; use-after-free.\n"); 102 WARN_ONCE(!refcount_add_not_zero_checked(i, r), "refcount_t: addition on 0; use-after-free.\n");
105} 103}
106EXPORT_SYMBOL(refcount_add); 104EXPORT_SYMBOL(refcount_add_checked);
107 105
108/** 106/**
109 * refcount_inc_not_zero - increment a refcount unless it is 0 107 * refcount_inc_not_zero_checked - increment a refcount unless it is 0
110 * @r: the refcount to increment 108 * @r: the refcount to increment
111 * 109 *
112 * Similar to atomic_inc_not_zero(), but will saturate at UINT_MAX and WARN. 110 * Similar to atomic_inc_not_zero(), but will saturate at UINT_MAX and WARN.
@@ -117,7 +115,7 @@ EXPORT_SYMBOL(refcount_add);
117 * 115 *
118 * Return: true if the increment was successful, false otherwise 116 * Return: true if the increment was successful, false otherwise
119 */ 117 */
120bool refcount_inc_not_zero(refcount_t *r) 118bool refcount_inc_not_zero_checked(refcount_t *r)
121{ 119{
122 unsigned int new, val = atomic_read(&r->refs); 120 unsigned int new, val = atomic_read(&r->refs);
123 121
@@ -136,10 +134,10 @@ bool refcount_inc_not_zero(refcount_t *r)
136 134
137 return true; 135 return true;
138} 136}
139EXPORT_SYMBOL(refcount_inc_not_zero); 137EXPORT_SYMBOL(refcount_inc_not_zero_checked);
140 138
141/** 139/**
142 * refcount_inc - increment a refcount 140 * refcount_inc_checked - increment a refcount
143 * @r: the refcount to increment 141 * @r: the refcount to increment
144 * 142 *
145 * Similar to atomic_inc(), but will saturate at UINT_MAX and WARN. 143 * Similar to atomic_inc(), but will saturate at UINT_MAX and WARN.
@@ -150,14 +148,14 @@ EXPORT_SYMBOL(refcount_inc_not_zero);
150 * Will WARN if the refcount is 0, as this represents a possible use-after-free 148 * Will WARN if the refcount is 0, as this represents a possible use-after-free
151 * condition. 149 * condition.
152 */ 150 */
153void refcount_inc(refcount_t *r) 151void refcount_inc_checked(refcount_t *r)
154{ 152{
155 WARN_ONCE(!refcount_inc_not_zero(r), "refcount_t: increment on 0; use-after-free.\n"); 153 WARN_ONCE(!refcount_inc_not_zero_checked(r), "refcount_t: increment on 0; use-after-free.\n");
156} 154}
157EXPORT_SYMBOL(refcount_inc); 155EXPORT_SYMBOL(refcount_inc_checked);
158 156
159/** 157/**
160 * refcount_sub_and_test - subtract from a refcount and test if it is 0 158 * refcount_sub_and_test_checked - subtract from a refcount and test if it is 0
161 * @i: amount to subtract from the refcount 159 * @i: amount to subtract from the refcount
162 * @r: the refcount 160 * @r: the refcount
163 * 161 *
@@ -176,7 +174,7 @@ EXPORT_SYMBOL(refcount_inc);
176 * 174 *
177 * Return: true if the resulting refcount is 0, false otherwise 175 * Return: true if the resulting refcount is 0, false otherwise
178 */ 176 */
179bool refcount_sub_and_test(unsigned int i, refcount_t *r) 177bool refcount_sub_and_test_checked(unsigned int i, refcount_t *r)
180{ 178{
181 unsigned int new, val = atomic_read(&r->refs); 179 unsigned int new, val = atomic_read(&r->refs);
182 180
@@ -194,10 +192,10 @@ bool refcount_sub_and_test(unsigned int i, refcount_t *r)
194 192
195 return !new; 193 return !new;
196} 194}
197EXPORT_SYMBOL(refcount_sub_and_test); 195EXPORT_SYMBOL(refcount_sub_and_test_checked);
198 196
199/** 197/**
200 * refcount_dec_and_test - decrement a refcount and test if it is 0 198 * refcount_dec_and_test_checked - decrement a refcount and test if it is 0
201 * @r: the refcount 199 * @r: the refcount
202 * 200 *
203 * Similar to atomic_dec_and_test(), it will WARN on underflow and fail to 201 * Similar to atomic_dec_and_test(), it will WARN on underflow and fail to
@@ -209,14 +207,14 @@ EXPORT_SYMBOL(refcount_sub_and_test);
209 * 207 *
210 * Return: true if the resulting refcount is 0, false otherwise 208 * Return: true if the resulting refcount is 0, false otherwise
211 */ 209 */
212bool refcount_dec_and_test(refcount_t *r) 210bool refcount_dec_and_test_checked(refcount_t *r)
213{ 211{
214 return refcount_sub_and_test(1, r); 212 return refcount_sub_and_test_checked(1, r);
215} 213}
216EXPORT_SYMBOL(refcount_dec_and_test); 214EXPORT_SYMBOL(refcount_dec_and_test_checked);
217 215
218/** 216/**
219 * refcount_dec - decrement a refcount 217 * refcount_dec_checked - decrement a refcount
220 * @r: the refcount 218 * @r: the refcount
221 * 219 *
222 * Similar to atomic_dec(), it will WARN on underflow and fail to decrement 220 * Similar to atomic_dec(), it will WARN on underflow and fail to decrement
@@ -225,12 +223,11 @@ EXPORT_SYMBOL(refcount_dec_and_test);
225 * Provides release memory ordering, such that prior loads and stores are done 223 * Provides release memory ordering, such that prior loads and stores are done
226 * before. 224 * before.
227 */ 225 */
228void refcount_dec(refcount_t *r) 226void refcount_dec_checked(refcount_t *r)
229{ 227{
230 WARN_ONCE(refcount_dec_and_test(r), "refcount_t: decrement hit 0; leaking memory.\n"); 228 WARN_ONCE(refcount_dec_and_test_checked(r), "refcount_t: decrement hit 0; leaking memory.\n");
231} 229}
232EXPORT_SYMBOL(refcount_dec); 230EXPORT_SYMBOL(refcount_dec_checked);
233#endif /* CONFIG_REFCOUNT_FULL */
234 231
235/** 232/**
236 * refcount_dec_if_one - decrement a refcount if it is 1 233 * refcount_dec_if_one - decrement a refcount if it is 1