diff options
| author | 2009-04-03 02:29:05 -0700 | |
|---|---|---|
| committer | 2009-04-03 02:29:05 -0700 | |
| commit | 65127d28e312bb6b38ce84a7bb71d762ef63ad4c (patch) | |
| tree | d5fdf52a2d0731f7fab0ce0ed394faac50b04fbc /lib/idr.c | |
| parent | xtensa: we don't need to include asm/io.h (diff) | |
| parent | Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6 (diff) | |
| download | linux-dev-65127d28e312bb6b38ce84a7bb71d762ef63ad4c.tar.xz linux-dev-65127d28e312bb6b38ce84a7bb71d762ef63ad4c.zip | |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into merge
Diffstat (limited to 'lib/idr.c')
| -rw-r--r-- | lib/idr.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/lib/idr.c b/lib/idr.c index dab4bca86f5d..80ca9aca038b 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -579,6 +579,52 @@ int idr_for_each(struct idr *idp, EXPORT_SYMBOL(idr_for_each); /** + * idr_get_next - lookup next object of id to given id. + * @idp: idr handle + * @id: pointer to lookup key + * + * Returns pointer to registered object with id, which is next number to + * given id. + */ + +void *idr_get_next(struct idr *idp, int *nextidp) +{ + struct idr_layer *p, *pa[MAX_LEVEL]; + struct idr_layer **paa = &pa[0]; + int id = *nextidp; + int n, max; + + /* find first ent */ + n = idp->layers * IDR_BITS; + max = 1 << n; + p = rcu_dereference(idp->top); + if (!p) + return NULL; + + while (id < max) { + while (n > 0 && p) { + n -= IDR_BITS; + *paa++ = p; + p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]); + } + + if (p) { + *nextidp = id; + return p; + } + + id += 1 << n; + while (n < fls(id)) { + n += IDR_BITS; + p = *--paa; + } + } + return NULL; +} + + + +/** * idr_replace - replace pointer for given id * @idp: idr handle * @ptr: pointer you want associated with the id |
