diff options
author | Kristian Hoegsberg <krh@redhat.com> | 2007-07-16 02:37:24 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-16 12:05:34 -0400 |
commit | 23936cc0b5d89619c34c2dab11d8cf3d6f7ca028 (patch) | |
tree | 506ec36cc37d3bc7dbf0ca68d1b271f9247fa458 | |
parent | 96d7fa421e6424ad9ef6d1d039375dc2edb63fe8 (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.h | 1 | ||||
-rw-r--r-- | lib/idr.c | 47 |
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); |
83 | void *idr_replace(struct idr *idp, void *ptr, int id); | 83 | void *idr_replace(struct idr *idp, void *ptr, int id); |
84 | void idr_remove(struct idr *idp, int id); | 84 | void idr_remove(struct idr *idp, int id); |
85 | void idr_remove_all(struct idr *idp); | ||
85 | void idr_destroy(struct idr *idp); | 86 | void idr_destroy(struct idr *idp); |
86 | void idr_init(struct idr *idp); | 87 | void idr_init(struct idr *idp); |
87 | 88 | ||
@@ -391,6 +391,53 @@ void idr_remove(struct idr *idp, int id) | |||
391 | EXPORT_SYMBOL(idr_remove); | 391 | EXPORT_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 | */ | ||
406 | void 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 | } | ||
438 | EXPORT_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 | */ |