[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:
parent
c51c275249
commit
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_pre_get(struct idr *idp, gfp_t gfp_mask);
|
||||||
int idr_get_new(struct idr *idp, void *ptr, int *id);
|
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);
|
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_remove(struct idr *idp, int id);
|
||||||
void idr_destroy(struct idr *idp);
|
void idr_destroy(struct idr *idp);
|
||||||
void idr_init(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/init.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <linux/err.h>
|
||||||
#include <linux/string.h>
|
#include <linux/string.h>
|
||||||
#include <linux/idr.h>
|
#include <linux/idr.h>
|
||||||
|
|
||||||
@ -398,6 +399,48 @@ void *idr_find(struct idr *idp, int id)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(idr_find);
|
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,
|
static void idr_cache_ctor(void * idr_layer, kmem_cache_t *idr_layer_cache,
|
||||||
unsigned long flags)
|
unsigned long flags)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user