diff options
author | Matthew Wilcox (Oracle) <willy@infradead.org> | 2019-11-01 21:36:39 -0400 |
---|---|---|
committer | Matthew Wilcox (Oracle) <willy@infradead.org> | 2019-11-01 22:26:34 -0400 |
commit | 5a74ac4c4a97bd8b7dba054304d598e2a882fea6 (patch) | |
tree | cb2bf8f5d805d99450ce514de25bc31729b00c16 | |
parent | 91abab83839aa2eba073e4a63c729832fdb27ea1 (diff) |
idr: Fix idr_get_next_ul race with idr_remove
Commit 5c089fd0c734 ("idr: Fix idr_get_next race with idr_remove")
neglected to fix idr_get_next_ul(). As far as I can tell, nobody's
actually using this interface under the RCU read lock, but fix it now
before anybody decides to use it.
Fixes: 5c089fd0c734 ("idr: Fix idr_get_next race with idr_remove")
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
-rw-r--r-- | lib/idr.c | 31 |
1 files changed, 11 insertions, 20 deletions
@@ -215,7 +215,7 @@ int idr_for_each(const struct idr *idr, | |||
215 | EXPORT_SYMBOL(idr_for_each); | 215 | EXPORT_SYMBOL(idr_for_each); |
216 | 216 | ||
217 | /** | 217 | /** |
218 | * idr_get_next() - Find next populated entry. | 218 | * idr_get_next_ul() - Find next populated entry. |
219 | * @idr: IDR handle. | 219 | * @idr: IDR handle. |
220 | * @nextid: Pointer to an ID. | 220 | * @nextid: Pointer to an ID. |
221 | * | 221 | * |
@@ -224,7 +224,7 @@ EXPORT_SYMBOL(idr_for_each); | |||
224 | * to the ID of the found value. To use in a loop, the value pointed to by | 224 | * to the ID of the found value. To use in a loop, the value pointed to by |
225 | * nextid must be incremented by the user. | 225 | * nextid must be incremented by the user. |
226 | */ | 226 | */ |
227 | void *idr_get_next(struct idr *idr, int *nextid) | 227 | void *idr_get_next_ul(struct idr *idr, unsigned long *nextid) |
228 | { | 228 | { |
229 | struct radix_tree_iter iter; | 229 | struct radix_tree_iter iter; |
230 | void __rcu **slot; | 230 | void __rcu **slot; |
@@ -245,18 +245,14 @@ void *idr_get_next(struct idr *idr, int *nextid) | |||
245 | } | 245 | } |
246 | if (!slot) | 246 | if (!slot) |
247 | return NULL; | 247 | return NULL; |
248 | id = iter.index + base; | ||
249 | |||
250 | if (WARN_ON_ONCE(id > INT_MAX)) | ||
251 | return NULL; | ||
252 | 248 | ||
253 | *nextid = id; | 249 | *nextid = iter.index + base; |
254 | return entry; | 250 | return entry; |
255 | } | 251 | } |
256 | EXPORT_SYMBOL(idr_get_next); | 252 | EXPORT_SYMBOL(idr_get_next_ul); |
257 | 253 | ||
258 | /** | 254 | /** |
259 | * idr_get_next_ul() - Find next populated entry. | 255 | * idr_get_next() - Find next populated entry. |
260 | * @idr: IDR handle. | 256 | * @idr: IDR handle. |
261 | * @nextid: Pointer to an ID. | 257 | * @nextid: Pointer to an ID. |
262 | * | 258 | * |
@@ -265,22 +261,17 @@ EXPORT_SYMBOL(idr_get_next); | |||
265 | * to the ID of the found value. To use in a loop, the value pointed to by | 261 | * to the ID of the found value. To use in a loop, the value pointed to by |
266 | * nextid must be incremented by the user. | 262 | * nextid must be incremented by the user. |
267 | */ | 263 | */ |
268 | void *idr_get_next_ul(struct idr *idr, unsigned long *nextid) | 264 | void *idr_get_next(struct idr *idr, int *nextid) |
269 | { | 265 | { |
270 | struct radix_tree_iter iter; | ||
271 | void __rcu **slot; | ||
272 | unsigned long base = idr->idr_base; | ||
273 | unsigned long id = *nextid; | 266 | unsigned long id = *nextid; |
267 | void *entry = idr_get_next_ul(idr, &id); | ||
274 | 268 | ||
275 | id = (id < base) ? 0 : id - base; | 269 | if (WARN_ON_ONCE(id > INT_MAX)) |
276 | slot = radix_tree_iter_find(&idr->idr_rt, &iter, id); | ||
277 | if (!slot) | ||
278 | return NULL; | 270 | return NULL; |
279 | 271 | *nextid = id; | |
280 | *nextid = iter.index + base; | 272 | return entry; |
281 | return rcu_dereference_raw(*slot); | ||
282 | } | 273 | } |
283 | EXPORT_SYMBOL(idr_get_next_ul); | 274 | EXPORT_SYMBOL(idr_get_next); |
284 | 275 | ||
285 | /** | 276 | /** |
286 | * idr_replace() - replace pointer for given ID. | 277 | * idr_replace() - replace pointer for given ID. |