diff options
author | Chris Mi <chrism@mellanox.com> | 2017-08-30 02:31:57 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-08-30 17:36:44 -0400 |
commit | 388f79fda74fd3d8700ed5d899573ec58c2e0253 (patch) | |
tree | ce66187430f7273449579dbbb1cc6b1fe9ea3a71 /lib | |
parent | c2f8a6cee632cdd2e70de0089f4480ddd7998748 (diff) |
idr: Add new APIs to support unsigned long
The following new APIs are added:
int idr_alloc_ext(struct idr *idr, void *ptr, unsigned long *index,
unsigned long start, unsigned long end, gfp_t gfp);
void *idr_remove_ext(struct idr *idr, unsigned long id);
void *idr_find_ext(const struct idr *idr, unsigned long id);
void *idr_replace_ext(struct idr *idr, void *ptr, unsigned long id);
void *idr_get_next_ext(struct idr *idr, unsigned long *nextid);
Signed-off-by: Chris Mi <chrism@mellanox.com>
Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'lib')
-rw-r--r-- | lib/idr.c | 66 | ||||
-rw-r--r-- | lib/radix-tree.c | 6 |
2 files changed, 40 insertions, 32 deletions
@@ -7,45 +7,32 @@ | |||
7 | DEFINE_PER_CPU(struct ida_bitmap *, ida_bitmap); | 7 | DEFINE_PER_CPU(struct ida_bitmap *, ida_bitmap); |
8 | static DEFINE_SPINLOCK(simple_ida_lock); | 8 | static DEFINE_SPINLOCK(simple_ida_lock); |
9 | 9 | ||
10 | /** | 10 | int idr_alloc_cmn(struct idr *idr, void *ptr, unsigned long *index, |
11 | * idr_alloc - allocate an id | 11 | unsigned long start, unsigned long end, gfp_t gfp, |
12 | * @idr: idr handle | 12 | bool ext) |
13 | * @ptr: pointer to be associated with the new id | ||
14 | * @start: the minimum id (inclusive) | ||
15 | * @end: the maximum id (exclusive) | ||
16 | * @gfp: memory allocation flags | ||
17 | * | ||
18 | * Allocates an unused ID in the range [start, end). Returns -ENOSPC | ||
19 | * if there are no unused IDs in that range. | ||
20 | * | ||
21 | * Note that @end is treated as max when <= 0. This is to always allow | ||
22 | * using @start + N as @end as long as N is inside integer range. | ||
23 | * | ||
24 | * Simultaneous modifications to the @idr are not allowed and should be | ||
25 | * prevented by the user, usually with a lock. idr_alloc() may be called | ||
26 | * concurrently with read-only accesses to the @idr, such as idr_find() and | ||
27 | * idr_for_each_entry(). | ||
28 | */ | ||
29 | int idr_alloc(struct idr *idr, void *ptr, int start, int end, gfp_t gfp) | ||
30 | { | 13 | { |
31 | void __rcu **slot; | ||
32 | struct radix_tree_iter iter; | 14 | struct radix_tree_iter iter; |
15 | void __rcu **slot; | ||
33 | 16 | ||
34 | if (WARN_ON_ONCE(start < 0)) | ||
35 | return -EINVAL; | ||
36 | if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr))) | 17 | if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr))) |
37 | return -EINVAL; | 18 | return -EINVAL; |
38 | 19 | ||
39 | radix_tree_iter_init(&iter, start); | 20 | radix_tree_iter_init(&iter, start); |
40 | slot = idr_get_free(&idr->idr_rt, &iter, gfp, end); | 21 | if (ext) |
22 | slot = idr_get_free_ext(&idr->idr_rt, &iter, gfp, end); | ||
23 | else | ||
24 | slot = idr_get_free(&idr->idr_rt, &iter, gfp, end); | ||
41 | if (IS_ERR(slot)) | 25 | if (IS_ERR(slot)) |
42 | return PTR_ERR(slot); | 26 | return PTR_ERR(slot); |
43 | 27 | ||
44 | radix_tree_iter_replace(&idr->idr_rt, &iter, slot, ptr); | 28 | radix_tree_iter_replace(&idr->idr_rt, &iter, slot, ptr); |
45 | radix_tree_iter_tag_clear(&idr->idr_rt, &iter, IDR_FREE); | 29 | radix_tree_iter_tag_clear(&idr->idr_rt, &iter, IDR_FREE); |
46 | return iter.index; | 30 | |
31 | if (index) | ||
32 | *index = iter.index; | ||
33 | return 0; | ||
47 | } | 34 | } |
48 | EXPORT_SYMBOL_GPL(idr_alloc); | 35 | EXPORT_SYMBOL_GPL(idr_alloc_cmn); |
49 | 36 | ||
50 | /** | 37 | /** |
51 | * idr_alloc_cyclic - allocate new idr entry in a cyclical fashion | 38 | * idr_alloc_cyclic - allocate new idr entry in a cyclical fashion |
@@ -134,6 +121,20 @@ void *idr_get_next(struct idr *idr, int *nextid) | |||
134 | } | 121 | } |
135 | EXPORT_SYMBOL(idr_get_next); | 122 | EXPORT_SYMBOL(idr_get_next); |
136 | 123 | ||
124 | void *idr_get_next_ext(struct idr *idr, unsigned long *nextid) | ||
125 | { | ||
126 | struct radix_tree_iter iter; | ||
127 | void __rcu **slot; | ||
128 | |||
129 | slot = radix_tree_iter_find(&idr->idr_rt, &iter, *nextid); | ||
130 | if (!slot) | ||
131 | return NULL; | ||
132 | |||
133 | *nextid = iter.index; | ||
134 | return rcu_dereference_raw(*slot); | ||
135 | } | ||
136 | EXPORT_SYMBOL(idr_get_next_ext); | ||
137 | |||
137 | /** | 138 | /** |
138 | * idr_replace - replace pointer for given id | 139 | * idr_replace - replace pointer for given id |
139 | * @idr: idr handle | 140 | * @idr: idr handle |
@@ -150,12 +151,19 @@ EXPORT_SYMBOL(idr_get_next); | |||
150 | */ | 151 | */ |
151 | void *idr_replace(struct idr *idr, void *ptr, int id) | 152 | void *idr_replace(struct idr *idr, void *ptr, int id) |
152 | { | 153 | { |
154 | if (WARN_ON_ONCE(id < 0)) | ||
155 | return ERR_PTR(-EINVAL); | ||
156 | |||
157 | return idr_replace_ext(idr, ptr, id); | ||
158 | } | ||
159 | EXPORT_SYMBOL(idr_replace); | ||
160 | |||
161 | void *idr_replace_ext(struct idr *idr, void *ptr, unsigned long id) | ||
162 | { | ||
153 | struct radix_tree_node *node; | 163 | struct radix_tree_node *node; |
154 | void __rcu **slot = NULL; | 164 | void __rcu **slot = NULL; |
155 | void *entry; | 165 | void *entry; |
156 | 166 | ||
157 | if (WARN_ON_ONCE(id < 0)) | ||
158 | return ERR_PTR(-EINVAL); | ||
159 | if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr))) | 167 | if (WARN_ON_ONCE(radix_tree_is_internal_node(ptr))) |
160 | return ERR_PTR(-EINVAL); | 168 | return ERR_PTR(-EINVAL); |
161 | 169 | ||
@@ -167,7 +175,7 @@ void *idr_replace(struct idr *idr, void *ptr, int id) | |||
167 | 175 | ||
168 | return entry; | 176 | return entry; |
169 | } | 177 | } |
170 | EXPORT_SYMBOL(idr_replace); | 178 | EXPORT_SYMBOL(idr_replace_ext); |
171 | 179 | ||
172 | /** | 180 | /** |
173 | * DOC: IDA description | 181 | * DOC: IDA description |
diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 898e87998417..c191b42d1213 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c | |||
@@ -2137,13 +2137,13 @@ int ida_pre_get(struct ida *ida, gfp_t gfp) | |||
2137 | } | 2137 | } |
2138 | EXPORT_SYMBOL(ida_pre_get); | 2138 | EXPORT_SYMBOL(ida_pre_get); |
2139 | 2139 | ||
2140 | void __rcu **idr_get_free(struct radix_tree_root *root, | 2140 | void __rcu **idr_get_free_cmn(struct radix_tree_root *root, |
2141 | struct radix_tree_iter *iter, gfp_t gfp, int end) | 2141 | struct radix_tree_iter *iter, gfp_t gfp, |
2142 | unsigned long max) | ||
2142 | { | 2143 | { |
2143 | struct radix_tree_node *node = NULL, *child; | 2144 | struct radix_tree_node *node = NULL, *child; |
2144 | void __rcu **slot = (void __rcu **)&root->rnode; | 2145 | void __rcu **slot = (void __rcu **)&root->rnode; |
2145 | unsigned long maxindex, start = iter->next_index; | 2146 | unsigned long maxindex, start = iter->next_index; |
2146 | unsigned long max = end > 0 ? end - 1 : INT_MAX; | ||
2147 | unsigned int shift, offset = 0; | 2147 | unsigned int shift, offset = 0; |
2148 | 2148 | ||
2149 | grow: | 2149 | grow: |