aboutsummaryrefslogtreecommitdiffstats
path: root/lib/idr.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/idr.c')
-rw-r--r--lib/idr.c102
1 files changed, 102 insertions, 0 deletions
diff --git a/lib/idr.c b/lib/idr.c
index b98f01a2eb94..5ca67b3cfd35 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -391,6 +391,53 @@ void idr_remove(struct idr *idp, int id)
391EXPORT_SYMBOL(idr_remove); 391EXPORT_SYMBOL(idr_remove);
392 392
393/** 393/**
394 * idr_remove_all - remove all ids from the given idr tree
395 * @idp: idr handle
396 *
397 * idr_destroy() only frees up unused, cached idp_layers, but this
398 * function will remove all id mappings and leave all idp_layers
399 * unused.
400 *
401 * A typical clean-up sequence for objects stored in an idr tree, will
402 * use idr_for_each() to free all objects, if necessay, then
403 * idr_remove_all() to remove all ids, and idr_destroy() to free
404 * up the cached idr_layers.
405 */
406void idr_remove_all(struct idr *idp)
407{
408 int n, id, max, error = 0;
409 struct idr_layer *p;
410 struct idr_layer *pa[MAX_LEVEL];
411 struct idr_layer **paa = &pa[0];
412
413 n = idp->layers * IDR_BITS;
414 p = idp->top;
415 max = 1 << n;
416
417 id = 0;
418 while (id < max && !error) {
419 while (n > IDR_BITS && p) {
420 n -= IDR_BITS;
421 *paa++ = p;
422 p = p->ary[(id >> n) & IDR_MASK];
423 }
424
425 id += 1 << n;
426 while (n < fls(id)) {
427 if (p) {
428 memset(p, 0, sizeof *p);
429 free_layer(idp, p);
430 }
431 n += IDR_BITS;
432 p = *--paa;
433 }
434 }
435 idp->top = NULL;
436 idp->layers = 0;
437}
438EXPORT_SYMBOL(idr_remove_all);
439
440/**
394 * idr_destroy - release all cached layers within an idr tree 441 * idr_destroy - release all cached layers within an idr tree
395 * idp: idr handle 442 * idp: idr handle
396 */ 443 */
@@ -437,6 +484,61 @@ void *idr_find(struct idr *idp, int id)
437EXPORT_SYMBOL(idr_find); 484EXPORT_SYMBOL(idr_find);
438 485
439/** 486/**
487 * idr_for_each - iterate through all stored pointers
488 * @idp: idr handle
489 * @fn: function to be called for each pointer
490 * @data: data passed back to callback function
491 *
492 * Iterate over the pointers registered with the given idr. The
493 * callback function will be called for each pointer currently
494 * registered, passing the id, the pointer and the data pointer passed
495 * to this function. It is not safe to modify the idr tree while in
496 * the callback, so functions such as idr_get_new and idr_remove are
497 * not allowed.
498 *
499 * We check the return of @fn each time. If it returns anything other
500 * than 0, we break out and return that value.
501 *
502 * The caller must serialize idr_for_each() vs idr_get_new() and idr_remove().
503 */
504int idr_for_each(struct idr *idp,
505 int (*fn)(int id, void *p, void *data), void *data)
506{
507 int n, id, max, error = 0;
508 struct idr_layer *p;
509 struct idr_layer *pa[MAX_LEVEL];
510 struct idr_layer **paa = &pa[0];
511
512 n = idp->layers * IDR_BITS;
513 p = idp->top;
514 max = 1 << n;
515
516 id = 0;
517 while (id < max) {
518 while (n > 0 && p) {
519 n -= IDR_BITS;
520 *paa++ = p;
521 p = p->ary[(id >> n) & IDR_MASK];
522 }
523
524 if (p) {
525 error = fn(id, (void *)p, data);
526 if (error)
527 break;
528 }
529
530 id += 1 << n;
531 while (n < fls(id)) {
532 n += IDR_BITS;
533 p = *--paa;
534 }
535 }
536
537 return error;
538}
539EXPORT_SYMBOL(idr_for_each);
540
541/**
440 * idr_replace - replace pointer for given id 542 * idr_replace - replace pointer for given id
441 * @idp: idr handle 543 * @idp: idr handle
442 * @ptr: pointer you want associated with the id 544 * @ptr: pointer you want associated with the id