aboutsummaryrefslogtreecommitdiffstats
path: root/lib/idr.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/idr.c')
-rw-r--r--lib/idr.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/lib/idr.c b/lib/idr.c
index 305117ca2d41..7b5a59caa989 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -100,10 +100,11 @@ static int sub_alloc(struct idr *idp, void *ptr, int *starting_id)
100 int n, m, sh; 100 int n, m, sh;
101 struct idr_layer *p, *new; 101 struct idr_layer *p, *new;
102 struct idr_layer *pa[MAX_LEVEL]; 102 struct idr_layer *pa[MAX_LEVEL];
103 int l, id; 103 int l, id, oid;
104 long bm; 104 long bm;
105 105
106 id = *starting_id; 106 id = *starting_id;
107 restart:
107 p = idp->top; 108 p = idp->top;
108 l = idp->layers; 109 l = idp->layers;
109 pa[l--] = NULL; 110 pa[l--] = NULL;
@@ -117,12 +118,23 @@ static int sub_alloc(struct idr *idp, void *ptr, int *starting_id)
117 if (m == IDR_SIZE) { 118 if (m == IDR_SIZE) {
118 /* no space available go back to previous layer. */ 119 /* no space available go back to previous layer. */
119 l++; 120 l++;
121 oid = id;
120 id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1; 122 id = (id | ((1 << (IDR_BITS * l)) - 1)) + 1;
123
124 /* if already at the top layer, we need to grow */
121 if (!(p = pa[l])) { 125 if (!(p = pa[l])) {
122 *starting_id = id; 126 *starting_id = id;
123 return -2; 127 return -2;
124 } 128 }
125 continue; 129
130 /* If we need to go up one layer, continue the
131 * loop; otherwise, restart from the top.
132 */
133 sh = IDR_BITS * (l + 1);
134 if (oid >> sh == id >> sh)
135 continue;
136 else
137 goto restart;
126 } 138 }
127 if (m != n) { 139 if (m != n) {
128 sh = IDR_BITS*l; 140 sh = IDR_BITS*l;