aboutsummaryrefslogtreecommitdiffstats
path: root/lib/idr.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/idr.c')
-rw-r--r--lib/idr.c71
1 files changed, 46 insertions, 25 deletions
diff --git a/lib/idr.c b/lib/idr.c
index 7b5a59caa989..30b33e2e7a50 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -70,6 +70,26 @@ static void free_layer(struct idr *idp, struct idr_layer *p)
70 spin_unlock_irqrestore(&idp->lock, flags); 70 spin_unlock_irqrestore(&idp->lock, flags);
71} 71}
72 72
73static void idr_mark_full(struct idr_layer **pa, int id)
74{
75 struct idr_layer *p = pa[0];
76 int l = 0;
77
78 __set_bit(id & IDR_MASK, &p->bitmap);
79 /*
80 * If this layer is full mark the bit in the layer above to
81 * show that this part of the radix tree is full. This may
82 * complete the layer above and require walking up the radix
83 * tree.
84 */
85 while (p->bitmap == IDR_FULL) {
86 if (!(p = pa[++l]))
87 break;
88 id = id >> IDR_BITS;
89 __set_bit((id & IDR_MASK), &p->bitmap);
90 }
91}
92
73/** 93/**
74 * idr_pre_get - reserver resources for idr allocation 94 * idr_pre_get - reserver resources for idr allocation
75 * @idp: idr handle 95 * @idp: idr handle
@@ -95,11 +115,10 @@ int idr_pre_get(struct idr *idp, gfp_t gfp_mask)
95} 115}
96EXPORT_SYMBOL(idr_pre_get); 116EXPORT_SYMBOL(idr_pre_get);
97 117
98static int sub_alloc(struct idr *idp, void *ptr, int *starting_id) 118static int sub_alloc(struct idr *idp, int *starting_id, struct idr_layer **pa)
99{ 119{
100 int n, m, sh; 120 int n, m, sh;
101 struct idr_layer *p, *new; 121 struct idr_layer *p, *new;
102 struct idr_layer *pa[MAX_LEVEL];
103 int l, id, oid; 122 int l, id, oid;
104 long bm; 123 long bm;
105 124
@@ -156,30 +175,13 @@ static int sub_alloc(struct idr *idp, void *ptr, int *starting_id)
156 pa[l--] = p; 175 pa[l--] = p;
157 p = p->ary[m]; 176 p = p->ary[m];
158 } 177 }
159 /* 178
160 * We have reached the leaf node, plant the 179 pa[l] = p;
161 * users pointer and return the raw id. 180 return id;
162 */
163 p->ary[m] = (struct idr_layer *)ptr;
164 __set_bit(m, &p->bitmap);
165 p->count++;
166 /*
167 * If this layer is full mark the bit in the layer above
168 * to show that this part of the radix tree is full.
169 * This may complete the layer above and require walking
170 * up the radix tree.
171 */
172 n = id;
173 while (p->bitmap == IDR_FULL) {
174 if (!(p = pa[++l]))
175 break;
176 n = n >> IDR_BITS;
177 __set_bit((n & IDR_MASK), &p->bitmap);
178 }
179 return(id);
180} 181}
181 182
182static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id) 183static int idr_get_empty_slot(struct idr *idp, int starting_id,
184 struct idr_layer **pa)
183{ 185{
184 struct idr_layer *p, *new; 186 struct idr_layer *p, *new;
185 int layers, v, id; 187 int layers, v, id;
@@ -225,12 +227,31 @@ build_up:
225 } 227 }
226 idp->top = p; 228 idp->top = p;
227 idp->layers = layers; 229 idp->layers = layers;
228 v = sub_alloc(idp, ptr, &id); 230 v = sub_alloc(idp, &id, pa);
229 if (v == -2) 231 if (v == -2)
230 goto build_up; 232 goto build_up;
231 return(v); 233 return(v);
232} 234}
233 235
236static int idr_get_new_above_int(struct idr *idp, void *ptr, int starting_id)
237{
238 struct idr_layer *pa[MAX_LEVEL];
239 int id;
240
241 id = idr_get_empty_slot(idp, starting_id, pa);
242 if (id >= 0) {
243 /*
244 * Successfully found an empty slot. Install the user
245 * pointer and mark the slot full.
246 */
247 pa[0]->ary[id & IDR_MASK] = (struct idr_layer *)ptr;
248 pa[0]->count++;
249 idr_mark_full(pa, id);
250 }
251
252 return id;
253}
254
234/** 255/**
235 * idr_get_new_above - allocate new idr entry above or equal to a start id 256 * idr_get_new_above - allocate new idr entry above or equal to a start id
236 * @idp: idr handle 257 * @idp: idr handle