aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wilcox <mawilcox@microsoft.com>2016-12-16 11:55:56 -0500
committerMatthew Wilcox <mawilcox@microsoft.com>2017-02-13 21:44:01 -0500
commit7ad3d4d85c7af9632055a6ac0aa15b6b6a321c6b (patch)
tree1586a6c01ced64d24c67859d792140853b148d20
parent0a835c4f090af2c76fc2932c539c3b32fd21fbbb (diff)
ida: Move ida_bitmap to a percpu variable
When we preload the IDA, we allocate an IDA bitmap. Instead of storing that preallocated bitmap in the IDA, we store it in a percpu variable. Generally there are more IDAs in the system than CPUs, so this cuts down on the number of preallocated bitmaps that are unused, and about half of the IDA users did not call ida_destroy() so they were leaking IDA bitmaps. Signed-off-by: Matthew Wilcox <mawilcox@microsoft.com>
-rw-r--r--include/linux/idr.h5
-rw-r--r--lib/idr.c39
-rw-r--r--lib/radix-tree.c45
-rw-r--r--tools/testing/radix-tree/linux/kernel.h2
-rw-r--r--tools/testing/radix-tree/linux/percpu.h5
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
18struct idr { 19struct 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
175DECLARE_PER_CPU(struct ida_bitmap *, ida_bitmap);
176
174struct ida { 177struct 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);
193static inline void ida_init(struct ida *ida) 195static 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/**
diff --git a/lib/idr.c b/lib/idr.c
index b87056e2cc4c..2abd7769c430 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -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
7DEFINE_PER_CPU(struct ida_bitmap *, ida_bitmap);
7static DEFINE_SPINLOCK(simple_ida_lock); 8static 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 */
204int 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}
226EXPORT_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}
368EXPORT_SYMBOL(ida_destroy); 333EXPORT_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 */
75struct radix_tree_preload { 83struct radix_tree_preload {
@@ -346,9 +354,8 @@ static void dump_ida_node(void *entry, unsigned long index)
346static void ida_dump(struct ida *ida) 354static 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}
2081EXPORT_SYMBOL(idr_preload); 2088EXPORT_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 */
2098int 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}
2118EXPORT_SYMBOL(ida_pre_get);
2119
2083void **idr_get_free(struct radix_tree_root *root, 2120void **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))