summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wilcox (Oracle) <willy@infradead.org>2019-11-01 21:36:39 -0400
committerMatthew Wilcox (Oracle) <willy@infradead.org>2019-11-01 22:26:34 -0400
commit5a74ac4c4a97bd8b7dba054304d598e2a882fea6 (patch)
treecb2bf8f5d805d99450ce514de25bc31729b00c16
parent91abab83839aa2eba073e4a63c729832fdb27ea1 (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.c31
1 files changed, 11 insertions, 20 deletions
diff --git a/lib/idr.c b/lib/idr.c
index 66a374892482..c2cf2c52bbde 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -215,7 +215,7 @@ int idr_for_each(const struct idr *idr,
215EXPORT_SYMBOL(idr_for_each); 215EXPORT_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 */
227void *idr_get_next(struct idr *idr, int *nextid) 227void *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}
256EXPORT_SYMBOL(idr_get_next); 252EXPORT_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 */
268void *idr_get_next_ul(struct idr *idr, unsigned long *nextid) 264void *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}
283EXPORT_SYMBOL(idr_get_next_ul); 274EXPORT_SYMBOL(idr_get_next);
284 275
285/** 276/**
286 * idr_replace() - replace pointer for given ID. 277 * idr_replace() - replace pointer for given ID.