diff options
-rw-r--r-- | include/linux/refcount.h | 27 | ||||
-rw-r--r-- | lib/refcount.c | 53 |
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 | ||
46 | extern __must_check bool refcount_add_not_zero_checked(unsigned int i, refcount_t *r); | ||
47 | extern void refcount_add_checked(unsigned int i, refcount_t *r); | ||
48 | |||
49 | extern __must_check bool refcount_inc_not_zero_checked(refcount_t *r); | ||
50 | extern void refcount_inc_checked(refcount_t *r); | ||
51 | |||
52 | extern __must_check bool refcount_sub_and_test_checked(unsigned int i, refcount_t *r); | ||
53 | |||
54 | extern __must_check bool refcount_dec_and_test_checked(refcount_t *r); | ||
55 | extern void refcount_dec_checked(refcount_t *r); | ||
56 | |||
46 | #ifdef CONFIG_REFCOUNT_FULL | 57 | #ifdef CONFIG_REFCOUNT_FULL |
47 | extern __must_check bool refcount_add_not_zero(unsigned int i, refcount_t *r); | ||
48 | extern void refcount_add(unsigned int i, refcount_t *r); | ||
49 | 58 | ||
50 | extern __must_check bool refcount_inc_not_zero(refcount_t *r); | 59 | #define refcount_add_not_zero refcount_add_not_zero_checked |
51 | extern 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 | ||
53 | extern __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 | ||
55 | extern __must_check bool refcount_dec_and_test(refcount_t *r); | ||
56 | extern 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 | */ |
63 | bool refcount_add_not_zero(unsigned int i, refcount_t *r) | 61 | bool 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 | } |
84 | EXPORT_SYMBOL(refcount_add_not_zero); | 82 | EXPORT_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 | */ |
102 | void refcount_add(unsigned int i, refcount_t *r) | 100 | void 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 | } |
106 | EXPORT_SYMBOL(refcount_add); | 104 | EXPORT_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 | */ |
120 | bool refcount_inc_not_zero(refcount_t *r) | 118 | bool 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 | } |
139 | EXPORT_SYMBOL(refcount_inc_not_zero); | 137 | EXPORT_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 | */ |
153 | void refcount_inc(refcount_t *r) | 151 | void 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 | } |
157 | EXPORT_SYMBOL(refcount_inc); | 155 | EXPORT_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 | */ |
179 | bool refcount_sub_and_test(unsigned int i, refcount_t *r) | 177 | bool 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 | } |
197 | EXPORT_SYMBOL(refcount_sub_and_test); | 195 | EXPORT_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 | */ |
212 | bool refcount_dec_and_test(refcount_t *r) | 210 | bool 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 | } |
216 | EXPORT_SYMBOL(refcount_dec_and_test); | 214 | EXPORT_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 | */ |
228 | void refcount_dec(refcount_t *r) | 226 | void 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 | } |
232 | EXPORT_SYMBOL(refcount_dec); | 230 | EXPORT_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 |