diff options
author | Kent Overstreet <kmo@daterainc.com> | 2013-08-13 15:31:20 -0700 |
---|---|---|
committer | Kent Overstreet <kmo@daterainc.com> | 2013-08-13 15:31:20 -0700 |
commit | 483cfa0c809b7dc3b0abad93407468f273416578 (patch) | |
tree | 6ebdddfbd95dc2e61b013d6e529c1e7cf2b0dedf | |
parent | c24de588c5f31fa77fb8fcbf4c457b32062fee0c (diff) |
ida: Use order 2 allocations when COMPACTION=nidr
And fall back to vmalloc for the array of pointers to sections so we can
still allocate up to INT_MAX ids.
-rw-r--r-- | lib/idr.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/lib/idr.c b/lib/idr.c index 02a221c01e29..3bffb525ba6d 100644 --- a/lib/idr.c +++ b/lib/idr.c @@ -21,16 +21,20 @@ #include <linux/export.h> #include <linux/idr.h> #include <linux/kernel.h> +#include <linux/mm.h> #include <linux/percpu.h> #include <linux/rcupdate.h> #include <linux/sched.h> #include <linux/slab.h> #include <linux/string.h> #include <linux/spinlock.h> +#include <linux/vmalloc.h> static void kgfree(void *ptr, size_t size) { - if (size < PAGE_SIZE) + if (is_vmalloc_addr(ptr)) + vfree(ptr); + else if (size < PAGE_SIZE) kfree(ptr); else free_pages((unsigned long) ptr, get_order(size)); @@ -102,7 +106,14 @@ static void *kgalloc(size_t size, gfp_t gfp) */ #define IDA_TREE_ARY BITS_PER_LONG -#define IDA_SECTION_SIZE (64UL << 10) + +/* Max section size, in bytes */ +#ifdef CONFIG_COMPACTION +#define IDA_SECTION_SIZE (64UL << 10) /* order 4 page allocation */ +#else +#define IDA_SECTION_SIZE (16UL << 10) /* order 2 */ +#endif + #define IDA_NODES_PER_SECTION (IDA_SECTION_SIZE / sizeof(unsigned long)) static inline unsigned long *ida_index_to_node(struct ida *ida, unsigned node) @@ -251,8 +262,15 @@ again: if (ida->nodes >= IDA_NODES_PER_SECTION && is_power_of_2(cur_sections)) { - sections = kgalloc(cur_sections * 2 * sizeof(unsigned long *), - __GFP_ZERO|gfp); + size_t bytes = cur_sections * 2 * sizeof(unsigned long *); + + if (bytes <= IDA_SECTION_SIZE) + sections = kgalloc(bytes, __GFP_ZERO|gfp); + else if (gfp & GFP_KERNEL) + sections = vzalloc(bytes); + else + sections = NULL; + if (!sections) goto err; } |