diff options
-rw-r--r-- | include/linux/idr.h | 5 | ||||
-rw-r--r-- | lib/idr.c | 39 | ||||
-rw-r--r-- | lib/radix-tree.c | 45 | ||||
-rw-r--r-- | tools/testing/radix-tree/linux/kernel.h | 2 | ||||
-rw-r--r-- | tools/testing/radix-tree/linux/percpu.h | 5 |
5 files changed, 51 insertions, 45 deletions
diff --git a/include/linux/idr.h b/include/linux/idr.h index f58c0a3addc3..2027c7aba50d 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h | |||
@@ -14,6 +14,7 @@ | |||
14 | 14 | ||
15 | #include <linux/radix-tree.h> | 15 | #include <linux/radix-tree.h> |
16 | #include <linux/gfp.h> | 16 | #include <linux/gfp.h> |
17 | #include <linux/percpu.h> | ||
17 | 18 | ||
18 | struct idr { | 19 | struct idr { |
19 | struct radix_tree_root idr_rt; | 20 | struct radix_tree_root idr_rt; |
@@ -171,9 +172,10 @@ struct ida_bitmap { | |||
171 | unsigned long bitmap[IDA_BITMAP_LONGS]; | 172 | unsigned long bitmap[IDA_BITMAP_LONGS]; |
172 | }; | 173 | }; |
173 | 174 | ||
175 | DECLARE_PER_CPU(struct ida_bitmap *, ida_bitmap); | ||
176 | |||
174 | struct ida { | 177 | struct ida { |
175 | struct radix_tree_root ida_rt; | 178 | struct radix_tree_root ida_rt; |
176 | struct ida_bitmap *free_bitmap; | ||
177 | }; | 179 | }; |
178 | 180 | ||
179 | #define IDA_INIT { \ | 181 | #define IDA_INIT { \ |
@@ -193,7 +195,6 @@ void ida_simple_remove(struct ida *ida, unsigned int id); | |||
193 | static inline void ida_init(struct ida *ida) | 195 | static inline void ida_init(struct ida *ida) |
194 | { | 196 | { |
195 | INIT_RADIX_TREE(&ida->ida_rt, IDR_RT_MARKER | GFP_NOWAIT); | 197 | INIT_RADIX_TREE(&ida->ida_rt, IDR_RT_MARKER | GFP_NOWAIT); |
196 | ida->free_bitmap = NULL; | ||
197 | } | 198 | } |
198 | 199 | ||
199 | /** | 200 | /** |
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/slab.h> | 4 | #include <linux/slab.h> |
5 | #include <linux/spinlock.h> | 5 | #include <linux/spinlock.h> |
6 | 6 | ||
7 | DEFINE_PER_CPU(struct ida_bitmap *, ida_bitmap); | ||
7 | static DEFINE_SPINLOCK(simple_ida_lock); | 8 | static DEFINE_SPINLOCK(simple_ida_lock); |
8 | 9 | ||
9 | /** | 10 | /** |
@@ -193,38 +194,6 @@ EXPORT_SYMBOL(idr_replace); | |||
193 | * limitation, it should be quite straightforward to raise the maximum. | 194 | * limitation, it should be quite straightforward to raise the maximum. |
194 | */ | 195 | */ |
195 | 196 | ||
196 | /** | ||
197 | * ida_pre_get - reserve resources for ida allocation | ||
198 | * @ida: ida handle | ||
199 | * @gfp: memory allocation flags | ||
200 | * | ||
201 | * This function should be called before calling ida_get_new_above(). If it | ||
202 | * is unable to allocate memory, it will return %0. On success, it returns %1. | ||
203 | */ | ||
204 | int ida_pre_get(struct ida *ida, gfp_t gfp) | ||
205 | { | ||
206 | struct ida_bitmap *bitmap; | ||
207 | |||
208 | /* | ||
209 | * This looks weird, but the IDA API has no preload_end() equivalent. | ||
210 | * Instead, ida_get_new() can return -EAGAIN, prompting the caller | ||
211 | * to return to the ida_pre_get() step. | ||
212 | */ | ||
213 | idr_preload(gfp); | ||
214 | idr_preload_end(); | ||
215 | |||
216 | if (!ida->free_bitmap) { | ||
217 | bitmap = kmalloc(sizeof(struct ida_bitmap), gfp); | ||
218 | if (!bitmap) | ||
219 | return 0; | ||
220 | bitmap = xchg(&ida->free_bitmap, bitmap); | ||
221 | kfree(bitmap); | ||
222 | } | ||
223 | |||
224 | return 1; | ||
225 | } | ||
226 | EXPORT_SYMBOL(ida_pre_get); | ||
227 | |||
228 | #define IDA_MAX (0x80000000U / IDA_BITMAP_BITS) | 197 | #define IDA_MAX (0x80000000U / IDA_BITMAP_BITS) |
229 | 198 | ||
230 | /** | 199 | /** |
@@ -292,10 +261,9 @@ int ida_get_new_above(struct ida *ida, int start, int *id) | |||
292 | new += bit; | 261 | new += bit; |
293 | if (new < 0) | 262 | if (new < 0) |
294 | return -ENOSPC; | 263 | return -ENOSPC; |
295 | bitmap = ida->free_bitmap; | 264 | bitmap = this_cpu_xchg(ida_bitmap, NULL); |
296 | if (!bitmap) | 265 | if (!bitmap) |
297 | return -EAGAIN; | 266 | return -EAGAIN; |
298 | ida->free_bitmap = NULL; | ||
299 | memset(bitmap, 0, sizeof(*bitmap)); | 267 | memset(bitmap, 0, sizeof(*bitmap)); |
300 | __set_bit(bit, bitmap->bitmap); | 268 | __set_bit(bit, bitmap->bitmap); |
301 | radix_tree_iter_replace(root, &iter, slot, bitmap); | 269 | radix_tree_iter_replace(root, &iter, slot, bitmap); |
@@ -361,9 +329,6 @@ void ida_destroy(struct ida *ida) | |||
361 | kfree(bitmap); | 329 | kfree(bitmap); |
362 | radix_tree_iter_delete(&ida->ida_rt, &iter, slot); | 330 | radix_tree_iter_delete(&ida->ida_rt, &iter, slot); |
363 | } | 331 | } |
364 | |||
365 | kfree(ida->free_bitmap); | ||
366 | ida->free_bitmap = NULL; | ||
367 | } | 332 | } |
368 | EXPORT_SYMBOL(ida_destroy); | 333 | EXPORT_SYMBOL(ida_destroy); |
369 | 334 | ||
diff --git a/lib/radix-tree.c b/lib/radix-tree.c index eaea14b8f2ca..7b9f8515033e 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c | |||
@@ -70,6 +70,14 @@ static struct kmem_cache *radix_tree_node_cachep; | |||
70 | #define IDR_PRELOAD_SIZE (IDR_MAX_PATH * 2 - 1) | 70 | #define IDR_PRELOAD_SIZE (IDR_MAX_PATH * 2 - 1) |
71 | 71 | ||
72 | /* | 72 | /* |
73 | * The IDA is even shorter since it uses a bitmap at the last level. | ||
74 | */ | ||
75 | #define IDA_INDEX_BITS (8 * sizeof(int) - 1 - ilog2(IDA_BITMAP_BITS)) | ||
76 | #define IDA_MAX_PATH (DIV_ROUND_UP(IDA_INDEX_BITS, \ | ||
77 | RADIX_TREE_MAP_SHIFT)) | ||
78 | #define IDA_PRELOAD_SIZE (IDA_MAX_PATH * 2 - 1) | ||
79 | |||
80 | /* | ||
73 | * Per-cpu pool of preloaded nodes | 81 | * Per-cpu pool of preloaded nodes |
74 | */ | 82 | */ |
75 | struct radix_tree_preload { | 83 | struct radix_tree_preload { |
@@ -346,9 +354,8 @@ static void dump_ida_node(void *entry, unsigned long index) | |||
346 | static void ida_dump(struct ida *ida) | 354 | static void ida_dump(struct ida *ida) |
347 | { | 355 | { |
348 | struct radix_tree_root *root = &ida->ida_rt; | 356 | struct radix_tree_root *root = &ida->ida_rt; |
349 | pr_debug("ida: %p %p free %d bitmap %p\n", ida, root->rnode, | 357 | pr_debug("ida: %p node %p free %d\n", ida, root->rnode, |
350 | root->gfp_mask >> ROOT_TAG_SHIFT, | 358 | root->gfp_mask >> ROOT_TAG_SHIFT); |
351 | ida->free_bitmap); | ||
352 | dump_ida_node(root->rnode, 0); | 359 | dump_ida_node(root->rnode, 0); |
353 | } | 360 | } |
354 | #endif | 361 | #endif |
@@ -2080,6 +2087,36 @@ void idr_preload(gfp_t gfp_mask) | |||
2080 | } | 2087 | } |
2081 | EXPORT_SYMBOL(idr_preload); | 2088 | EXPORT_SYMBOL(idr_preload); |
2082 | 2089 | ||
2090 | /** | ||
2091 | * ida_pre_get - reserve resources for ida allocation | ||
2092 | * @ida: ida handle | ||
2093 | * @gfp: memory allocation flags | ||
2094 | * | ||
2095 | * This function should be called before calling ida_get_new_above(). If it | ||
2096 | * is unable to allocate memory, it will return %0. On success, it returns %1. | ||
2097 | */ | ||
2098 | int ida_pre_get(struct ida *ida, gfp_t gfp) | ||
2099 | { | ||
2100 | __radix_tree_preload(gfp, IDA_PRELOAD_SIZE); | ||
2101 | /* | ||
2102 | * The IDA API has no preload_end() equivalent. Instead, | ||
2103 | * ida_get_new() can return -EAGAIN, prompting the caller | ||
2104 | * to return to the ida_pre_get() step. | ||
2105 | */ | ||
2106 | preempt_enable(); | ||
2107 | |||
2108 | if (!this_cpu_read(ida_bitmap)) { | ||
2109 | struct ida_bitmap *bitmap = kmalloc(sizeof(*bitmap), gfp); | ||
2110 | if (!bitmap) | ||
2111 | return 0; | ||
2112 | bitmap = this_cpu_cmpxchg(ida_bitmap, NULL, bitmap); | ||
2113 | kfree(bitmap); | ||
2114 | } | ||
2115 | |||
2116 | return 1; | ||
2117 | } | ||
2118 | EXPORT_SYMBOL(ida_pre_get); | ||
2119 | |||
2083 | void **idr_get_free(struct radix_tree_root *root, | 2120 | void **idr_get_free(struct radix_tree_root *root, |
2084 | struct radix_tree_iter *iter, gfp_t gfp, int end) | 2121 | struct radix_tree_iter *iter, gfp_t gfp, int end) |
2085 | { | 2122 | { |
@@ -2219,6 +2256,8 @@ static int radix_tree_cpu_dead(unsigned int cpu) | |||
2219 | kmem_cache_free(radix_tree_node_cachep, node); | 2256 | kmem_cache_free(radix_tree_node_cachep, node); |
2220 | rtp->nr--; | 2257 | rtp->nr--; |
2221 | } | 2258 | } |
2259 | kfree(per_cpu(ida_bitmap, cpu)); | ||
2260 | per_cpu(ida_bitmap, cpu) = NULL; | ||
2222 | return 0; | 2261 | return 0; |
2223 | } | 2262 | } |
2224 | 2263 | ||
diff --git a/tools/testing/radix-tree/linux/kernel.h b/tools/testing/radix-tree/linux/kernel.h index 63fce553781a..677b8c0f60f9 100644 --- a/tools/testing/radix-tree/linux/kernel.h +++ b/tools/testing/radix-tree/linux/kernel.h | |||
@@ -24,6 +24,4 @@ | |||
24 | 24 | ||
25 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) | 25 | #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) |
26 | 26 | ||
27 | #define xchg(ptr, x) uatomic_xchg(ptr, x) | ||
28 | |||
29 | #endif /* _KERNEL_H */ | 27 | #endif /* _KERNEL_H */ |
diff --git a/tools/testing/radix-tree/linux/percpu.h b/tools/testing/radix-tree/linux/percpu.h index 5837f1d56f17..3ea01a1a88c2 100644 --- a/tools/testing/radix-tree/linux/percpu.h +++ b/tools/testing/radix-tree/linux/percpu.h | |||
@@ -1,7 +1,10 @@ | |||
1 | 1 | #define DECLARE_PER_CPU(type, val) extern type val | |
2 | #define DEFINE_PER_CPU(type, val) type val | 2 | #define DEFINE_PER_CPU(type, val) type val |
3 | 3 | ||
4 | #define __get_cpu_var(var) var | 4 | #define __get_cpu_var(var) var |
5 | #define this_cpu_ptr(var) var | 5 | #define this_cpu_ptr(var) var |
6 | #define this_cpu_read(var) var | ||
7 | #define this_cpu_xchg(var, val) uatomic_xchg(&var, val) | ||
8 | #define this_cpu_cmpxchg(var, old, new) uatomic_cmpxchg(&var, old, new) | ||
6 | #define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); }) | 9 | #define per_cpu_ptr(ptr, cpu) ({ (void)(cpu); (ptr); }) |
7 | #define per_cpu(var, cpu) (*per_cpu_ptr(&(var), cpu)) | 10 | #define per_cpu(var, cpu) (*per_cpu_ptr(&(var), cpu)) |