Skip to content

Commit 3a319a2

Browse files
author
Kent Overstreet
committed
lib/generic-radix-tree.c: Make nodes more reasonably sized
this code originally used the page allocator directly, but most code shouldn't do that - PAGE_SIZE varies with architecture, and slab is faster. 4k is also on the large side for typical usage, 512 bytes is a better choice for typical usage that might be somewhat sparse. Signed-off-by: Kent Overstreet <[email protected]>
1 parent d645479 commit 3a319a2

File tree

2 files changed

+28
-36
lines changed

2 files changed

+28
-36
lines changed

include/linux/generic-radix-tree.h

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* DOC: Generic radix trees/sparse arrays
66
*
77
* Very simple and minimalistic, supporting arbitrary size entries up to
8-
* PAGE_SIZE.
8+
* GENRADIX_NODE_SIZE.
99
*
1010
* A genradix is defined with the type it will store, like so:
1111
*
@@ -45,12 +45,15 @@
4545

4646
struct genradix_root;
4747

48+
#define GENRADIX_NODE_SHIFT 9
49+
#define GENRADIX_NODE_SIZE (1U << GENRADIX_NODE_SHIFT)
50+
4851
struct __genradix {
4952
struct genradix_root *root;
5053
};
5154

5255
/*
53-
* NOTE: currently, sizeof(_type) must not be larger than PAGE_SIZE:
56+
* NOTE: currently, sizeof(_type) must not be larger than GENRADIX_NODE_SIZE:
5457
*/
5558

5659
#define __GENRADIX_INITIALIZER \
@@ -101,14 +104,14 @@ void __genradix_free(struct __genradix *);
101104
static inline size_t __idx_to_offset(size_t idx, size_t obj_size)
102105
{
103106
if (__builtin_constant_p(obj_size))
104-
BUILD_BUG_ON(obj_size > PAGE_SIZE);
107+
BUILD_BUG_ON(obj_size > GENRADIX_NODE_SIZE);
105108
else
106-
BUG_ON(obj_size > PAGE_SIZE);
109+
BUG_ON(obj_size > GENRADIX_NODE_SIZE);
107110

108111
if (!is_power_of_2(obj_size)) {
109-
size_t objs_per_page = PAGE_SIZE / obj_size;
112+
size_t objs_per_page = GENRADIX_NODE_SIZE / obj_size;
110113

111-
return (idx / objs_per_page) * PAGE_SIZE +
114+
return (idx / objs_per_page) * GENRADIX_NODE_SIZE +
112115
(idx % objs_per_page) * obj_size;
113116
} else {
114117
return idx * obj_size;
@@ -118,9 +121,9 @@ static inline size_t __idx_to_offset(size_t idx, size_t obj_size)
118121
#define __genradix_cast(_radix) (typeof((_radix)->type[0]) *)
119122
#define __genradix_obj_size(_radix) sizeof((_radix)->type[0])
120123
#define __genradix_objs_per_page(_radix) \
121-
(PAGE_SIZE / sizeof((_radix)->type[0]))
124+
(GENRADIX_NODE_SIZE / sizeof((_radix)->type[0]))
122125
#define __genradix_page_remainder(_radix) \
123-
(PAGE_SIZE % sizeof((_radix)->type[0]))
126+
(GENRADIX_NODE_SIZE % sizeof((_radix)->type[0]))
124127

125128
#define __genradix_idx_to_offset(_radix, _idx) \
126129
__idx_to_offset(_idx, __genradix_obj_size(_radix))
@@ -217,8 +220,8 @@ static inline void __genradix_iter_advance(struct genradix_iter *iter,
217220
iter->offset += obj_size;
218221

219222
if (!is_power_of_2(obj_size) &&
220-
(iter->offset & (PAGE_SIZE - 1)) + obj_size > PAGE_SIZE)
221-
iter->offset = round_up(iter->offset, PAGE_SIZE);
223+
(iter->offset & (GENRADIX_NODE_SIZE - 1)) + obj_size > GENRADIX_NODE_SIZE)
224+
iter->offset = round_up(iter->offset, GENRADIX_NODE_SIZE);
222225

223226
iter->pos++;
224227
}
@@ -235,8 +238,8 @@ static inline void __genradix_iter_rewind(struct genradix_iter *iter,
235238
return;
236239
}
237240

238-
if ((iter->offset & (PAGE_SIZE - 1)) == 0)
239-
iter->offset -= PAGE_SIZE % obj_size;
241+
if ((iter->offset & (GENRADIX_NODE_SIZE - 1)) == 0)
242+
iter->offset -= GENRADIX_NODE_SIZE % obj_size;
240243

241244
iter->offset -= obj_size;
242245
iter->pos--;
@@ -263,7 +266,7 @@ static inline void __genradix_iter_rewind(struct genradix_iter *iter,
263266
genradix_for_each_from(_radix, _iter, _p, 0)
264267

265268
#define genradix_last_pos(_radix) \
266-
(SIZE_MAX / PAGE_SIZE * __genradix_objs_per_page(_radix) - 1)
269+
(SIZE_MAX / GENRADIX_NODE_SIZE * __genradix_objs_per_page(_radix) - 1)
267270

268271
/**
269272
* genradix_for_each_reverse - iterate over entry in a genradix, reverse order

lib/generic-radix-tree.c

Lines changed: 12 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
#include <linux/gfp.h>
66
#include <linux/kmemleak.h>
77

8-
#define GENRADIX_ARY (PAGE_SIZE / sizeof(struct genradix_node *))
8+
#define GENRADIX_ARY (GENRADIX_NODE_SIZE / sizeof(struct genradix_node *))
99
#define GENRADIX_ARY_SHIFT ilog2(GENRADIX_ARY)
1010

1111
struct genradix_node {
@@ -14,13 +14,13 @@ struct genradix_node {
1414
struct genradix_node *children[GENRADIX_ARY];
1515

1616
/* Leaf: */
17-
u8 data[PAGE_SIZE];
17+
u8 data[GENRADIX_NODE_SIZE];
1818
};
1919
};
2020

2121
static inline int genradix_depth_shift(unsigned depth)
2222
{
23-
return PAGE_SHIFT + GENRADIX_ARY_SHIFT * depth;
23+
return GENRADIX_NODE_SHIFT + GENRADIX_ARY_SHIFT * depth;
2424
}
2525

2626
/*
@@ -33,7 +33,7 @@ static inline size_t genradix_depth_size(unsigned depth)
3333

3434
/* depth that's needed for a genradix that can address up to ULONG_MAX: */
3535
#define GENRADIX_MAX_DEPTH \
36-
DIV_ROUND_UP(BITS_PER_LONG - PAGE_SHIFT, GENRADIX_ARY_SHIFT)
36+
DIV_ROUND_UP(BITS_PER_LONG - GENRADIX_NODE_SHIFT, GENRADIX_ARY_SHIFT)
3737

3838
#define GENRADIX_DEPTH_MASK \
3939
((unsigned long) (roundup_pow_of_two(GENRADIX_MAX_DEPTH + 1) - 1))
@@ -79,23 +79,12 @@ EXPORT_SYMBOL(__genradix_ptr);
7979

8080
static inline struct genradix_node *genradix_alloc_node(gfp_t gfp_mask)
8181
{
82-
struct genradix_node *node;
83-
84-
node = (struct genradix_node *)__get_free_page(gfp_mask|__GFP_ZERO);
85-
86-
/*
87-
* We're using pages (not slab allocations) directly for kernel data
88-
* structures, so we need to explicitly inform kmemleak of them in order
89-
* to avoid false positive memory leak reports.
90-
*/
91-
kmemleak_alloc(node, PAGE_SIZE, 1, gfp_mask);
92-
return node;
82+
return kzalloc(GENRADIX_NODE_SIZE, gfp_mask);
9383
}
9484

9585
static inline void genradix_free_node(struct genradix_node *node)
9686
{
97-
kmemleak_free(node);
98-
free_page((unsigned long)node);
87+
kfree(node);
9988
}
10089

10190
/*
@@ -200,7 +189,7 @@ void *__genradix_iter_peek(struct genradix_iter *iter,
200189
i++;
201190
iter->offset = round_down(iter->offset + objs_per_ptr,
202191
objs_per_ptr);
203-
iter->pos = (iter->offset >> PAGE_SHIFT) *
192+
iter->pos = (iter->offset >> GENRADIX_NODE_SHIFT) *
204193
objs_per_page;
205194
if (i == GENRADIX_ARY)
206195
goto restart;
@@ -209,7 +198,7 @@ void *__genradix_iter_peek(struct genradix_iter *iter,
209198
n = n->children[i];
210199
}
211200

212-
return &n->data[iter->offset & (PAGE_SIZE - 1)];
201+
return &n->data[iter->offset & (GENRADIX_NODE_SIZE - 1)];
213202
}
214203
EXPORT_SYMBOL(__genradix_iter_peek);
215204

@@ -235,7 +224,7 @@ void *__genradix_iter_peek_prev(struct genradix_iter *iter,
235224

236225
if (ilog2(iter->offset) >= genradix_depth_shift(level)) {
237226
iter->offset = genradix_depth_size(level);
238-
iter->pos = (iter->offset >> PAGE_SHIFT) * objs_per_page;
227+
iter->pos = (iter->offset >> GENRADIX_NODE_SHIFT) * objs_per_page;
239228

240229
iter->offset -= obj_size_plus_page_remainder;
241230
iter->pos--;
@@ -251,7 +240,7 @@ void *__genradix_iter_peek_prev(struct genradix_iter *iter,
251240
size_t objs_per_ptr = genradix_depth_size(level);
252241

253242
iter->offset = round_down(iter->offset, objs_per_ptr);
254-
iter->pos = (iter->offset >> PAGE_SHIFT) * objs_per_page;
243+
iter->pos = (iter->offset >> GENRADIX_NODE_SHIFT) * objs_per_page;
255244

256245
if (!iter->offset)
257246
return NULL;
@@ -267,7 +256,7 @@ void *__genradix_iter_peek_prev(struct genradix_iter *iter,
267256
n = n->children[i];
268257
}
269258

270-
return &n->data[iter->offset & (PAGE_SIZE - 1)];
259+
return &n->data[iter->offset & (GENRADIX_NODE_SIZE - 1)];
271260
}
272261
EXPORT_SYMBOL(__genradix_iter_peek_prev);
273262

@@ -289,7 +278,7 @@ int __genradix_prealloc(struct __genradix *radix, size_t size,
289278
{
290279
size_t offset;
291280

292-
for (offset = 0; offset < size; offset += PAGE_SIZE)
281+
for (offset = 0; offset < size; offset += GENRADIX_NODE_SIZE)
293282
if (!__genradix_ptr_alloc(radix, offset, gfp_mask))
294283
return -ENOMEM;
295284

0 commit comments

Comments
 (0)