Skip to content

Commit 6bf377b

Browse files
howletttehcaster
authored andcommitted
maple_tree: Add single node allocation support to maple state
The fast path through a write will require replacing a single node in the tree. Using a sheaf (32 nodes) is too heavy for the fast path, so special case the node store operation by just allocating one node in the maple state. Signed-off-by: Liam R. Howlett <[email protected]> Signed-off-by: Vlastimil Babka <[email protected]>
1 parent 9b05890 commit 6bf377b

File tree

3 files changed

+51
-9
lines changed

3 files changed

+51
-9
lines changed

include/linux/maple_tree.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -443,6 +443,7 @@ struct ma_state {
443443
unsigned long min; /* The minimum index of this node - implied pivot min */
444444
unsigned long max; /* The maximum index of this node - implied pivot max */
445445
struct slab_sheaf *sheaf; /* Allocated nodes for this operation */
446+
struct maple_node *alloc; /* A single allocated node for fast path writes */
446447
unsigned long node_request; /* The number of nodes to allocate for this operation */
447448
enum maple_status status; /* The status of the state (active, start, none, etc) */
448449
unsigned char depth; /* depth of tree descent during write */
@@ -491,8 +492,9 @@ struct ma_wr_state {
491492
.status = ma_start, \
492493
.min = 0, \
493494
.max = ULONG_MAX, \
494-
.node_request = 0, \
495495
.sheaf = NULL, \
496+
.alloc = NULL, \
497+
.node_request = 0, \
496498
.mas_flags = 0, \
497499
.store_type = wr_invalid, \
498500
}

lib/maple_tree.c

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1073,16 +1073,23 @@ static int mas_ascend(struct ma_state *mas)
10731073
*
10741074
* Return: A pointer to a maple node.
10751075
*/
1076-
static inline struct maple_node *mas_pop_node(struct ma_state *mas)
1076+
static __always_inline struct maple_node *mas_pop_node(struct ma_state *mas)
10771077
{
10781078
struct maple_node *ret;
10791079

1080+
if (mas->alloc) {
1081+
ret = mas->alloc;
1082+
mas->alloc = NULL;
1083+
goto out;
1084+
}
1085+
10801086
if (WARN_ON_ONCE(!mas->sheaf))
10811087
return NULL;
10821088

10831089
ret = kmem_cache_alloc_from_sheaf(maple_node_cache, GFP_NOWAIT, mas->sheaf);
1084-
memset(ret, 0, sizeof(*ret));
10851090

1091+
out:
1092+
memset(ret, 0, sizeof(*ret));
10861093
return ret;
10871094
}
10881095

@@ -1093,9 +1100,34 @@ static inline struct maple_node *mas_pop_node(struct ma_state *mas)
10931100
*/
10941101
static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp)
10951102
{
1096-
if (unlikely(mas->sheaf)) {
1097-
unsigned long refill = mas->node_request;
1103+
if (!mas->node_request)
1104+
return;
1105+
1106+
if (mas->node_request == 1) {
1107+
if (mas->sheaf)
1108+
goto use_sheaf;
1109+
1110+
if (mas->alloc)
1111+
return;
10981112

1113+
mas->alloc = mt_alloc_one(gfp);
1114+
if (!mas->alloc)
1115+
goto error;
1116+
1117+
mas->node_request = 0;
1118+
return;
1119+
}
1120+
1121+
use_sheaf:
1122+
if (unlikely(mas->alloc)) {
1123+
kfree(mas->alloc);
1124+
mas->alloc = NULL;
1125+
}
1126+
1127+
if (mas->sheaf) {
1128+
unsigned long refill;
1129+
1130+
refill = mas->node_request;
10991131
if (kmem_cache_sheaf_size(mas->sheaf) >= refill) {
11001132
mas->node_request = 0;
11011133
return;
@@ -5180,8 +5212,11 @@ void mas_destroy(struct ma_state *mas)
51805212
mas->node_request = 0;
51815213
if (mas->sheaf)
51825214
mt_return_sheaf(mas->sheaf);
5183-
51845215
mas->sheaf = NULL;
5216+
5217+
if (mas->alloc)
5218+
kfree(mas->alloc);
5219+
mas->alloc = NULL;
51855220
}
51865221
EXPORT_SYMBOL_GPL(mas_destroy);
51875222

@@ -5816,7 +5851,7 @@ bool mas_nomem(struct ma_state *mas, gfp_t gfp)
58165851
mas_alloc_nodes(mas, gfp);
58175852
}
58185853

5819-
if (!mas->sheaf)
5854+
if (!mas->sheaf && !mas->alloc)
58205855
return false;
58215856

58225857
mas->status = ma_start;

tools/testing/radix-tree/maple.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35085,10 +35085,15 @@ static unsigned char get_vacant_height(struct ma_wr_state *wr_mas, void *entry)
3508535085

3508635086
static int mas_allocated(struct ma_state *mas)
3508735087
{
35088+
int total = 0;
35089+
35090+
if (mas->alloc)
35091+
total++;
35092+
3508835093
if (mas->sheaf)
35089-
return kmem_cache_sheaf_size(mas->sheaf);
35094+
total += kmem_cache_sheaf_size(mas->sheaf);
3509035095

35091-
return 0;
35096+
return total;
3509235097
}
3509335098
/* Preallocation testing */
3509435099
static noinline void __init check_prealloc(struct maple_tree *mt)

0 commit comments

Comments
 (0)