diff options
Diffstat (limited to 'lib/idr.c')
-rw-r--r-- | lib/idr.c | 46 |
1 files changed, 46 insertions, 0 deletions
@@ -579,6 +579,52 @@ int idr_for_each(struct idr *idp, | |||
579 | EXPORT_SYMBOL(idr_for_each); | 579 | EXPORT_SYMBOL(idr_for_each); |
580 | 580 | ||
581 | /** | 581 | /** |
582 | * idr_get_next - lookup next object of id to given id. | ||
583 | * @idp: idr handle | ||
584 | * @id: pointer to lookup key | ||
585 | * | ||
586 | * Returns pointer to registered object with id, which is next number to | ||
587 | * given id. | ||
588 | */ | ||
589 | |||
590 | void *idr_get_next(struct idr *idp, int *nextidp) | ||
591 | { | ||
592 | struct idr_layer *p, *pa[MAX_LEVEL]; | ||
593 | struct idr_layer **paa = &pa[0]; | ||
594 | int id = *nextidp; | ||
595 | int n, max; | ||
596 | |||
597 | /* find first ent */ | ||
598 | n = idp->layers * IDR_BITS; | ||
599 | max = 1 << n; | ||
600 | p = rcu_dereference(idp->top); | ||
601 | if (!p) | ||
602 | return NULL; | ||
603 | |||
604 | while (id < max) { | ||
605 | while (n > 0 && p) { | ||
606 | n -= IDR_BITS; | ||
607 | *paa++ = p; | ||
608 | p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]); | ||
609 | } | ||
610 | |||
611 | if (p) { | ||
612 | *nextidp = id; | ||
613 | return p; | ||
614 | } | ||
615 | |||
616 | id += 1 << n; | ||
617 | while (n < fls(id)) { | ||
618 | n += IDR_BITS; | ||
619 | p = *--paa; | ||
620 | } | ||
621 | } | ||
622 | return NULL; | ||
623 | } | ||
624 | |||
625 | |||
626 | |||
627 | /** | ||
582 | * idr_replace - replace pointer for given id | 628 | * idr_replace - replace pointer for given id |
583 | * @idp: idr handle | 629 | * @idp: idr handle |
584 | * @ptr: pointer you want associated with the id | 630 | * @ptr: pointer you want associated with the id |