the pointer you associated with the ID by calling :c:func:`idr_find`
and free the ID by calling :c:func:`idr_remove`.
-If you need to change the pointer associated with an ID, you can call
-:c:func:`idr_replace`. One common reason to do this is to reserve an
-ID by passing a ``NULL`` pointer to the allocation function; initialise the
-object with the reserved ID and finally insert the initialised object
-into the IDR.
-
To perform an action on all pointers used by the IDR, you can
either use the callback-based :c:func:`idr_for_each` or the
iterator-style :c:func:`idr_for_each_entry`. You may need to use
}
EXPORT_SYMBOL(idr_get_next);
-/**
- * idr_replace() - replace pointer for given ID.
- * @idr: IDR handle.
- * @ptr: New pointer to associate with the ID.
- * @id: ID to change.
- *
- * Replace the pointer registered with an ID and return the old value.
- * This function can be called under the RCU read lock concurrently with
- * idr_alloc() and idr_remove() (as long as the ID being removed is not
- * the one being replaced!).
- *
- * Returns: the old value on success. %-ENOENT indicates that @id was not
- * found. %-EINVAL indicates that @ptr was not valid.
- */
-void *idr_replace(struct idr *idr, void *ptr, unsigned long id)
-{
- struct radix_tree_node *node;
- void __rcu **slot = NULL;
- void *entry;
-
- id -= idr->idr_base;
-
- entry = __radix_tree_lookup(&idr->idr_rt, id, &node, &slot);
- if (!slot || radix_tree_tag_get(&idr->idr_rt, id, IDR_FREE))
- return ERR_PTR(-ENOENT);
-
- __radix_tree_replace(&idr->idr_rt, node, slot, ptr);
-
- return entry;
-}
-EXPORT_SYMBOL(idr_replace);
-
/**
* DOC: IDA description
*
free(item);
}
-void idr_replace_test(void)
-{
- DEFINE_IDR(idr);
-
- idr_alloc(&idr, (void *)-1, 10, 11, GFP_KERNEL);
- idr_replace(&idr, &idr, 10);
-
- idr_destroy(&idr);
-}
-
/*
* Unlike the radix tree, you can put a NULL pointer -- with care -- into
* the IDR. Some interfaces, like idr_find() do not distinguish between
assert(idr_alloc(&idr, NULL, 0, 0, GFP_KERNEL) == i);
}
- assert(idr_replace(&idr, DUMMY_PTR, 3) == NULL);
- assert(idr_replace(&idr, DUMMY_PTR, 4) == NULL);
- assert(idr_replace(&idr, NULL, 4) == DUMMY_PTR);
- assert(idr_replace(&idr, DUMMY_PTR, 11) == ERR_PTR(-ENOENT));
idr_remove(&idr, 5);
assert(idr_alloc(&idr, NULL, 0, 0, GFP_KERNEL) == 5);
idr_remove(&idr, 5);
assert(idr_is_empty(&idr));
assert(idr_alloc(&idr, NULL, 0, 0, GFP_KERNEL) == 0);
- assert(idr_replace(&idr, DUMMY_PTR, 3) == ERR_PTR(-ENOENT));
- assert(idr_replace(&idr, DUMMY_PTR, 0) == NULL);
- assert(idr_replace(&idr, NULL, 0) == DUMMY_PTR);
idr_destroy(&idr);
assert(idr_is_empty(&idr));
BUG_ON(!idr_is_empty(idr));
}
- for (i = 0; i < 8; i++) {
- BUG_ON(idr_alloc(idr, NULL, 0, 0, GFP_KERNEL) != 0);
- idr_for_each_entry(idr, entry, id);
- idr_replace(idr, &name[i], 0);
- idr_for_each_entry(idr, entry, id);
- BUG_ON(idr_find(idr, 0) != &name[i]);
- idr_remove(idr, 0);
- }
-
for (i = 0; i < 8; i++) {
BUG_ON(idr_alloc(idr, &name[i], 0, 0, GFP_KERNEL) != 0);
BUG_ON(idr_alloc(idr, NULL, 0, 0, GFP_KERNEL) != 1);
idr_remove(idr, 1);
idr_for_each_entry(idr, entry, id);
- idr_replace(idr, &name[i + 1], 0);
- idr_for_each_entry(idr, entry, id);
idr_remove(idr, 0);
}
}
idr_for_each(&idr, item_idr_free, &idr);
idr_destroy(&idr);
- idr_replace_test();
idr_null_test();
idr_nowait_test();
idr_get_next_test(0);