aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKristian Hoegsberg <krh@redhat.com>2007-07-16 02:37:24 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-07-16 12:05:34 -0400
commit23936cc0b5d89619c34c2dab11d8cf3d6f7ca028 (patch)
tree506ec36cc37d3bc7dbf0ca68d1b271f9247fa458
parent96d7fa421e6424ad9ef6d1d039375dc2edb63fe8 (diff)
lib: add idr_remove_all
Remove all ids from the given idr tree. idr_destroy() only frees up unused, cached idp_layers, but this function will remove all id mappings and leave all idp_layers unused. A typical clean-up sequence for objects stored in an idr tree, will use idr_for_each() to free all objects, if necessay, then idr_remove_all() to remove all ids, and idr_destroy() to free up the cached idr_layers. Signed-off-by: Kristian Hoegsberg <krh@redhat.com> Cc: Tejun Heo <htejun@gmail.com> Cc: Dave Airlie <airlied@linux.ie> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/idr.h1
-rw-r--r--lib/idr.c47
2 files changed, 48 insertions, 0 deletions
diff --git a/include/linux/idr.h b/include/linux/idr.h
index 8442c0bffc06..0edda411959c 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -82,6 +82,7 @@ int idr_for_each(struct idr *idp,
82 int (*fn)(int id, void *p, void *data), void *data); 82 int (*fn)(int id, void *p, void *data), void *data);
83void *idr_replace(struct idr *idp, void *ptr, int id); 83void *idr_replace(struct idr *idp, void *ptr, int id);
84void idr_remove(struct idr *idp, int id); 84void idr_remove(struct idr *idp, int id);
85void idr_remove_all(struct idr *idp);
85void idr_destroy(struct idr *idp); 86void idr_destroy(struct idr *idp);
86void idr_init(struct idr *idp); 87void idr_init(struct idr *idp);
87 88
diff --git a/lib/idr.c b/lib/idr.c
index d29da6159dae..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 */