@@ -36,18 +36,21 @@ int idr_alloc_u32(struct idr *idr, void *ptr, u32 *nextid,
36
36
{
37
37
struct radix_tree_iter iter ;
38
38
void __rcu * * slot ;
39
+ int base = idr -> idr_base ;
40
+ int id = * nextid ;
39
41
40
42
if (WARN_ON_ONCE (radix_tree_is_internal_node (ptr )))
41
43
return - EINVAL ;
42
44
if (WARN_ON_ONCE (!(idr -> idr_rt .gfp_mask & ROOT_IS_IDR )))
43
45
idr -> idr_rt .gfp_mask |= IDR_RT_MARKER ;
44
46
45
- radix_tree_iter_init (& iter , * nextid );
46
- slot = idr_get_free (& idr -> idr_rt , & iter , gfp , max );
47
+ id = (id < base ) ? 0 : id - base ;
48
+ radix_tree_iter_init (& iter , id );
49
+ slot = idr_get_free (& idr -> idr_rt , & iter , gfp , max - base );
47
50
if (IS_ERR (slot ))
48
51
return PTR_ERR (slot );
49
52
50
- * nextid = iter .index ;
53
+ * nextid = iter .index + base ;
51
54
/* there is a memory barrier inside radix_tree_iter_replace() */
52
55
radix_tree_iter_replace (& idr -> idr_rt , & iter , slot , ptr );
53
56
radix_tree_iter_tag_clear (& idr -> idr_rt , & iter , IDR_FREE );
@@ -135,6 +138,46 @@ int idr_alloc_cyclic(struct idr *idr, void *ptr, int start, int end, gfp_t gfp)
135
138
}
136
139
EXPORT_SYMBOL (idr_alloc_cyclic );
137
140
141
+ /**
142
+ * idr_remove() - Remove an ID from the IDR.
143
+ * @idr: IDR handle.
144
+ * @id: Pointer ID.
145
+ *
146
+ * Removes this ID from the IDR. If the ID was not previously in the IDR,
147
+ * this function returns %NULL.
148
+ *
149
+ * Since this function modifies the IDR, the caller should provide their
150
+ * own locking to ensure that concurrent modification of the same IDR is
151
+ * not possible.
152
+ *
153
+ * Return: The pointer formerly associated with this ID.
154
+ */
155
+ void * idr_remove (struct idr * idr , unsigned long id )
156
+ {
157
+ return radix_tree_delete_item (& idr -> idr_rt , id - idr -> idr_base , NULL );
158
+ }
159
+ EXPORT_SYMBOL_GPL (idr_remove );
160
+
161
+ /**
162
+ * idr_find() - Return pointer for given ID.
163
+ * @idr: IDR handle.
164
+ * @id: Pointer ID.
165
+ *
166
+ * Looks up the pointer associated with this ID. A %NULL pointer may
167
+ * indicate that @id is not allocated or that the %NULL pointer was
168
+ * associated with this ID.
169
+ *
170
+ * This function can be called under rcu_read_lock(), given that the leaf
171
+ * pointers lifetimes are correctly managed.
172
+ *
173
+ * Return: The pointer associated with this ID.
174
+ */
175
+ void * idr_find (const struct idr * idr , unsigned long id )
176
+ {
177
+ return radix_tree_lookup (& idr -> idr_rt , id - idr -> idr_base );
178
+ }
179
+ EXPORT_SYMBOL_GPL (idr_find );
180
+
138
181
/**
139
182
* idr_for_each() - Iterate through all stored pointers.
140
183
* @idr: IDR handle.
@@ -157,13 +200,14 @@ int idr_for_each(const struct idr *idr,
157
200
{
158
201
struct radix_tree_iter iter ;
159
202
void __rcu * * slot ;
203
+ int base = idr -> idr_base ;
160
204
161
205
radix_tree_for_each_slot (slot , & idr -> idr_rt , & iter , 0 ) {
162
206
int ret ;
163
207
164
208
if (WARN_ON_ONCE (iter .index > INT_MAX ))
165
209
break ;
166
- ret = fn (iter .index , rcu_dereference_raw (* slot ), data );
210
+ ret = fn (iter .index + base , rcu_dereference_raw (* slot ), data );
167
211
if (ret )
168
212
return ret ;
169
213
}
@@ -186,15 +230,19 @@ void *idr_get_next(struct idr *idr, int *nextid)
186
230
{
187
231
struct radix_tree_iter iter ;
188
232
void __rcu * * slot ;
233
+ int base = idr -> idr_base ;
234
+ int id = * nextid ;
189
235
190
- slot = radix_tree_iter_find (& idr -> idr_rt , & iter , * nextid );
236
+ id = (id < base ) ? 0 : id - base ;
237
+ slot = radix_tree_iter_find (& idr -> idr_rt , & iter , id );
191
238
if (!slot )
192
239
return NULL ;
240
+ id = iter .index + base ;
193
241
194
- if (WARN_ON_ONCE (iter . index > INT_MAX ))
242
+ if (WARN_ON_ONCE (id > INT_MAX ))
195
243
return NULL ;
196
244
197
- * nextid = iter . index ;
245
+ * nextid = id ;
198
246
return rcu_dereference_raw (* slot );
199
247
}
200
248
EXPORT_SYMBOL (idr_get_next );
@@ -213,12 +261,15 @@ void *idr_get_next_ul(struct idr *idr, unsigned long *nextid)
213
261
{
214
262
struct radix_tree_iter iter ;
215
263
void __rcu * * slot ;
264
+ unsigned long base = idr -> idr_base ;
265
+ unsigned long id = * nextid ;
216
266
217
- slot = radix_tree_iter_find (& idr -> idr_rt , & iter , * nextid );
267
+ id = (id < base ) ? 0 : id - base ;
268
+ slot = radix_tree_iter_find (& idr -> idr_rt , & iter , id );
218
269
if (!slot )
219
270
return NULL ;
220
271
221
- * nextid = iter .index ;
272
+ * nextid = iter .index + base ;
222
273
return rcu_dereference_raw (* slot );
223
274
}
224
275
EXPORT_SYMBOL (idr_get_next_ul );
@@ -245,6 +296,7 @@ void *idr_replace(struct idr *idr, void *ptr, unsigned long id)
245
296
246
297
if (WARN_ON_ONCE (radix_tree_is_internal_node (ptr )))
247
298
return ERR_PTR (- EINVAL );
299
+ id -= idr -> idr_base ;
248
300
249
301
entry = __radix_tree_lookup (& idr -> idr_rt , id , & node , & slot );
250
302
if (!slot || radix_tree_tag_get (& idr -> idr_rt , id , IDR_FREE ))
0 commit comments