aboutsummaryrefslogtreecommitdiff
path: root/lib/idr.c
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-12-04 11:05:26 +0100
committerIngo Molnar <mingo@elte.hu>2008-12-04 11:05:26 +0100
commitc0515566f3117c44b0572559bcc3cb00899b0910 (patch)
tree3c7e36ed6e78812b9276a81d6b3a2e80788003c5 /lib/idr.c
parent4385cecf1f5866fb33fc95e2ee26a44e9b6f6be2 (diff)
parent061e41fdb5047b1fb161e89664057835935ca1d2 (diff)
Merge commit 'v2.6.28-rc7' into x86/cleanups
Diffstat (limited to 'lib/idr.c')
-rw-r--r--lib/idr.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/lib/idr.c b/lib/idr.c
index e728c7fccc4..7a785a0c2ea 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -185,6 +185,7 @@ static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)
new = get_from_free_list(idp);
if (!new)
return -1;
+ new->layer = l-1;
rcu_assign_pointer(p->ary[m], new);
p->count++;
}
@@ -210,6 +211,7 @@ build_up:
if (unlikely(!p)) {
if (!(p = get_from_free_list(idp)))
return -1;
+ p->layer = 0;
layers = 1;
}
/*
@@ -237,6 +239,7 @@ build_up:
}
new->ary[0] = p;
new->count = 1;
+ new->layer = layers-1;
if (p->bitmap == IDR_FULL)
__set_bit(0, &new->bitmap);
p = new;
@@ -493,17 +496,21 @@ void *idr_find(struct idr *idp, int id)
int n;
struct idr_layer *p;
- n = idp->layers * IDR_BITS;
p = rcu_dereference(idp->top);
+ if (!p)
+ return NULL;
+ n = (p->layer+1) * IDR_BITS;
/* Mask off upper bits we don't use for the search. */
id &= MAX_ID_MASK;
if (id >= (1 << n))
return NULL;
+ BUG_ON(n == 0);
while (n > 0 && p) {
n -= IDR_BITS;
+ BUG_ON(n != p->layer*IDR_BITS);
p = rcu_dereference(p->ary[(id >> n) & IDR_MASK]);
}
return((void *)p);
@@ -582,8 +589,11 @@ void *idr_replace(struct idr *idp, void *ptr, int id)
int n;
struct idr_layer *p, *old_p;
- n = idp->layers * IDR_BITS;
p = idp->top;
+ if (!p)
+ return ERR_PTR(-EINVAL);
+
+ n = (p->layer+1) * IDR_BITS;
id &= MAX_ID_MASK;