[PATCH] lib: add idr_replace
This patch adds idr_replace() to replace an existing pointer in a single operation. Device-mapper will use this to update the pointer it stored against a given id. Signed-off-by: Jeff Mahoney <jeffm@suse.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
This commit is contained in:
Родитель
c51c275249
Коммит
5806f07cd2
|
@ -78,6 +78,7 @@ void *idr_find(struct idr *idp, int id);
|
|||
int idr_pre_get(struct idr *idp, gfp_t gfp_mask);
|
||||
int idr_get_new(struct idr *idp, void *ptr, int *id);
|
||||
int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
|
||||
void *idr_replace(struct idr *idp, void *ptr, int id);
|
||||
void idr_remove(struct idr *idp, int id);
|
||||
void idr_destroy(struct idr *idp);
|
||||
void idr_init(struct idr *idp);
|
||||
|
|
43
lib/idr.c
43
lib/idr.c
|
@ -29,6 +29,7 @@
|
|||
#include <linux/init.h>
|
||||
#include <linux/module.h>
|
||||
#endif
|
||||
#include <linux/err.h>
|
||||
#include <linux/string.h>
|
||||
#include <linux/idr.h>
|
||||
|
||||
|
@ -398,6 +399,48 @@ void *idr_find(struct idr *idp, int id)
|
|||
}
|
||||
EXPORT_SYMBOL(idr_find);
|
||||
|
||||
/**
|
||||
* idr_replace - replace pointer for given id
|
||||
* @idp: idr handle
|
||||
* @ptr: pointer you want associated with the id
|
||||
* @id: lookup key
|
||||
*
|
||||
* Replace the pointer registered with an id and return the old value.
|
||||
* A -ENOENT return indicates that @id was not found.
|
||||
* A -EINVAL return indicates that @id was not within valid constraints.
|
||||
*
|
||||
* The caller must serialize vs idr_find(), idr_get_new(), and idr_remove().
|
||||
*/
|
||||
void *idr_replace(struct idr *idp, void *ptr, int id)
|
||||
{
|
||||
int n;
|
||||
struct idr_layer *p, *old_p;
|
||||
|
||||
n = idp->layers * IDR_BITS;
|
||||
p = idp->top;
|
||||
|
||||
id &= MAX_ID_MASK;
|
||||
|
||||
if (id >= (1 << n))
|
||||
return ERR_PTR(-EINVAL);
|
||||
|
||||
n -= IDR_BITS;
|
||||
while ((n > 0) && p) {
|
||||
p = p->ary[(id >> n) & IDR_MASK];
|
||||
n -= IDR_BITS;
|
||||
}
|
||||
|
||||
n = id & IDR_MASK;
|
||||
if (unlikely(p == NULL || !test_bit(n, &p->bitmap)))
|
||||
return ERR_PTR(-ENOENT);
|
||||
|
||||
old_p = p->ary[n];
|
||||
p->ary[n] = ptr;
|
||||
|
||||
return old_p;
|
||||
}
|
||||
EXPORT_SYMBOL(idr_replace);
|
||||
|
||||
static void idr_cache_ctor(void * idr_layer, kmem_cache_t *idr_layer_cache,
|
||||
unsigned long flags)
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче