提交 5806f07c 编写于 作者: J Jeff Mahoney 提交者: Linus Torvalds

[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: NJeff Mahoney <jeffm@suse.com>
Signed-off-by: NAlasdair G Kergon <agk@redhat.com>
Signed-off-by: NAndrew Morton <akpm@osdl.org>
Signed-off-by: NLinus Torvalds <torvalds@osdl.org>
上级 c51c2752
...@@ -78,6 +78,7 @@ void *idr_find(struct idr *idp, int id); ...@@ -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);
......
...@@ -29,6 +29,7 @@ ...@@ -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) ...@@ -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)
{ {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册