summaryrefslogtreecommitdiff
path: root/source4/lib
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2008-09-30 07:14:31 -0700
committerAndrew Tridgell <tridge@samba.org>2008-09-30 07:14:31 -0700
commit717b36c672441f8cd86bf550ab0fabc52a3a3821 (patch)
tree18f8f1f8519afc156aa11b4c4d595e097df7a3a5 /source4/lib
parentd87e9ba56b00962be6b797464e77619bc6f0ba2c (diff)
downloadsamba-717b36c672441f8cd86bf550ab0fabc52a3a3821.tar.gz
samba-717b36c672441f8cd86bf550ab0fabc52a3a3821.tar.bz2
samba-717b36c672441f8cd86bf550ab0fabc52a3a3821.zip
merged a bugfix for the idtree code from the Linux kernel. This
matches commit 7aae6dd80e265aa9402ed507caaff4a5dba55069 in the kernel. Many thanks to Jim Houston for pointing out this fix to us
Diffstat (limited to 'source4/lib')
-rw-r--r--source4/lib/util/idtree.c14
1 files changed, 13 insertions, 1 deletions
diff --git a/source4/lib/util/idtree.c b/source4/lib/util/idtree.c
index 1e2cc2976a..392f4e81f8 100644
--- a/source4/lib/util/idtree.c
+++ b/source4/lib/util/idtree.c
@@ -105,12 +105,13 @@ static int sub_alloc(struct idr_context *idp, void *ptr, int *starting_id)
int n, m, sh;
struct idr_layer *p, *new;
struct idr_layer *pa[MAX_LEVEL];
- int l, id;
+ int l, id, oid;
uint32_t bm;
memset(pa, 0, sizeof(pa));
id = *starting_id;
+restart:
p = idp->top;
l = idp->layers;
pa[l--] = NULL;
@@ -124,12 +125,23 @@ static int sub_alloc(struct idr_context *idp, void *ptr, int *starting_id)
if (m == IDR_SIZE) {
/* no space available go back to previous layer. */
l++;
+ oid = id;
id = (id | ((1 << (IDR_BITS*l))-1)) + 1;
+
+ /* if already at the top layer, we need to grow */
if (!(p = pa[l])) {
*starting_id = id;
return -2;
}
+
+ /* If we need to go up one layer, continue the
+ * loop; otherwise, restart from the top.
+ */
+ sh = IDR_BITS * (l + 1);
+ if (oid >> sh == id >> sh)
continue;
+ else
+ goto restart;
}
if (m != n) {
sh = IDR_BITS*l;