Skip to content

Commit 55ee5b5

Browse files
howlettakpm00
authored andcommitted
maple_tree: introduce mas_next_slot() interface
Sometimes, during a tree walk, the user needs the next slot regardless of if it is empty or not. Add an interface to get the next slot. Since there are no consecutive NULLs allowed in the tree, the mas_next() function can only advance two slots at most. So use the new mas_next_slot() interface to align both implementations. Use this method for mas_find() as well. Link: https://lkml.kernel.org/r/[email protected] Signed-off-by: Liam R. Howlett <[email protected]> Cc: David Binderman <[email protected]> Cc: Peng Zhang <[email protected]> Cc: Sergey Senozhatsky <[email protected]> Cc: Vernon Yang <[email protected]> Cc: Wei Yang <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 7ee257f commit 55ee5b5

File tree

1 file changed

+104
-125
lines changed

1 file changed

+104
-125
lines changed

lib/maple_tree.c

Lines changed: 104 additions & 125 deletions
Original file line numberDiff line numberDiff line change
@@ -4607,31 +4607,27 @@ static inline int mas_prev_node(struct ma_state *mas, unsigned long min)
46074607
static inline int mas_next_node(struct ma_state *mas, struct maple_node *node,
46084608
unsigned long max)
46094609
{
4610-
unsigned long min, pivot;
4610+
unsigned long min;
46114611
unsigned long *pivots;
46124612
struct maple_enode *enode;
46134613
int level = 0;
4614-
unsigned char offset;
46154614
unsigned char node_end;
46164615
enum maple_type mt;
46174616
void __rcu **slots;
46184617

46194618
if (mas->max >= max)
46204619
goto no_entry;
46214620

4621+
min = mas->max + 1;
46224622
level = 0;
46234623
do {
46244624
if (ma_is_root(node))
46254625
goto no_entry;
46264626

4627-
min = mas->max + 1;
4628-
if (min > max)
4629-
goto no_entry;
4630-
4627+
/* Walk up. */
46314628
if (unlikely(mas_ascend(mas)))
46324629
return 1;
46334630

4634-
offset = mas->offset;
46354631
level++;
46364632
node = mas_mn(mas);
46374633
mt = mte_node_type(mas->node);
@@ -4640,36 +4636,37 @@ static inline int mas_next_node(struct ma_state *mas, struct maple_node *node,
46404636
if (unlikely(ma_dead_node(node)))
46414637
return 1;
46424638

4643-
} while (unlikely(offset == node_end));
4639+
} while (unlikely(mas->offset == node_end));
46444640

46454641
slots = ma_slots(node, mt);
4646-
pivot = mas_safe_pivot(mas, pivots, ++offset, mt);
4647-
while (unlikely(level > 1)) {
4648-
/* Descend, if necessary */
4649-
enode = mas_slot(mas, slots, offset);
4650-
if (unlikely(ma_dead_node(node)))
4651-
return 1;
4642+
mas->offset++;
4643+
enode = mas_slot(mas, slots, mas->offset);
4644+
if (unlikely(ma_dead_node(node)))
4645+
return 1;
46524646

4653-
mas->node = enode;
4647+
if (level > 1)
4648+
mas->offset = 0;
4649+
4650+
while (unlikely(level > 1)) {
46544651
level--;
4652+
mas->node = enode;
46554653
node = mas_mn(mas);
46564654
mt = mte_node_type(mas->node);
46574655
slots = ma_slots(node, mt);
4658-
pivots = ma_pivots(node, mt);
4656+
enode = mas_slot(mas, slots, 0);
46594657
if (unlikely(ma_dead_node(node)))
46604658
return 1;
4661-
4662-
offset = 0;
4663-
pivot = pivots[0];
46644659
}
46654660

4666-
enode = mas_slot(mas, slots, offset);
4661+
if (!mas->offset)
4662+
pivots = ma_pivots(node, mt);
4663+
4664+
mas->max = mas_safe_pivot(mas, pivots, mas->offset, mt);
46674665
if (unlikely(ma_dead_node(node)))
46684666
return 1;
46694667

46704668
mas->node = enode;
46714669
mas->min = min;
4672-
mas->max = pivot;
46734670
return 0;
46744671

46754672
no_entry:
@@ -4680,83 +4677,106 @@ static inline int mas_next_node(struct ma_state *mas, struct maple_node *node,
46804677
return 0;
46814678
}
46824679

4680+
static inline void mas_rewalk(struct ma_state *mas, unsigned long index)
4681+
{
4682+
retry:
4683+
mas_set(mas, index);
4684+
mas_state_walk(mas);
4685+
if (mas_is_start(mas))
4686+
goto retry;
4687+
}
4688+
4689+
static inline bool mas_rewalk_if_dead(struct ma_state *mas,
4690+
struct maple_node *node, const unsigned long index)
4691+
{
4692+
if (unlikely(ma_dead_node(node))) {
4693+
mas_rewalk(mas, index);
4694+
return true;
4695+
}
4696+
return false;
4697+
}
4698+
46834699
/*
4684-
* mas_next_nentry() - Get the next node entry
4685-
* @mas: The maple state
4686-
* @max: The maximum value to check
4687-
* @*range_start: Pointer to store the start of the range.
4700+
* mas_next_slot() - Get the entry in the next slot
46884701
*
4689-
* Sets @mas->offset to the offset of the next node entry, @mas->last to the
4690-
* pivot of the entry.
4702+
* @mas: The maple state
4703+
* @max: The maximum starting range
4704+
* @empty: Can be empty
46914705
*
4692-
* Return: The next entry, %NULL otherwise
4706+
* Return: The entry in the next slot which is possibly NULL
46934707
*/
4694-
static inline void *mas_next_nentry(struct ma_state *mas,
4695-
struct maple_node *node, unsigned long max, enum maple_type type)
4708+
static void *mas_next_slot(struct ma_state *mas, unsigned long max, bool empty)
46964709
{
4697-
unsigned char count;
4698-
unsigned long pivot;
4699-
unsigned long *pivots;
47004710
void __rcu **slots;
4711+
unsigned long *pivots;
4712+
unsigned long pivot;
4713+
enum maple_type type;
4714+
struct maple_node *node;
4715+
unsigned char data_end;
4716+
unsigned long save_point = mas->last;
47014717
void *entry;
47024718

4703-
if (mas->last == mas->max) {
4704-
mas->index = mas->max;
4705-
return NULL;
4706-
}
4707-
4708-
slots = ma_slots(node, type);
4719+
retry:
4720+
node = mas_mn(mas);
4721+
type = mte_node_type(mas->node);
47094722
pivots = ma_pivots(node, type);
4710-
count = ma_data_end(node, type, pivots, mas->max);
4711-
if (unlikely(ma_dead_node(node)))
4712-
return NULL;
4713-
4714-
mas->index = mas_safe_min(mas, pivots, mas->offset);
4715-
if (unlikely(ma_dead_node(node)))
4716-
return NULL;
4717-
4718-
if (mas->index > max)
4719-
return NULL;
4720-
4721-
if (mas->offset > count)
4722-
return NULL;
4723+
data_end = ma_data_end(node, type, pivots, mas->max);
4724+
if (unlikely(mas_rewalk_if_dead(mas, node, save_point)))
4725+
goto retry;
47234726

4724-
while (mas->offset < count) {
4725-
pivot = pivots[mas->offset];
4726-
entry = mas_slot(mas, slots, mas->offset);
4727-
if (ma_dead_node(node))
4728-
return NULL;
4727+
again:
4728+
if (mas->max >= max) {
4729+
if (likely(mas->offset < data_end))
4730+
pivot = pivots[mas->offset];
4731+
else
4732+
return NULL; /* must be mas->max */
47294733

4730-
mas->last = pivot;
4731-
if (entry)
4732-
return entry;
4734+
if (unlikely(mas_rewalk_if_dead(mas, node, save_point)))
4735+
goto retry;
47334736

47344737
if (pivot >= max)
47354738
return NULL;
4739+
}
47364740

4737-
if (pivot >= mas->max)
4741+
if (likely(mas->offset < data_end)) {
4742+
mas->index = pivots[mas->offset] + 1;
4743+
mas->offset++;
4744+
if (likely(mas->offset < data_end))
4745+
mas->last = pivots[mas->offset];
4746+
else
4747+
mas->last = mas->max;
4748+
} else {
4749+
if (mas_next_node(mas, node, max)) {
4750+
mas_rewalk(mas, save_point);
4751+
goto retry;
4752+
}
4753+
4754+
if (mas_is_none(mas))
47384755
return NULL;
47394756

4740-
mas->index = pivot + 1;
4741-
mas->offset++;
4757+
mas->offset = 0;
4758+
mas->index = mas->min;
4759+
node = mas_mn(mas);
4760+
type = mte_node_type(mas->node);
4761+
pivots = ma_pivots(node, type);
4762+
mas->last = pivots[0];
47424763
}
47434764

4744-
pivot = mas_logical_pivot(mas, pivots, mas->offset, type);
4745-
entry = mas_slot(mas, slots, mas->offset);
4746-
if (ma_dead_node(node))
4747-
return NULL;
4765+
slots = ma_slots(node, type);
4766+
entry = mt_slot(mas->tree, slots, mas->offset);
4767+
if (unlikely(mas_rewalk_if_dead(mas, node, save_point)))
4768+
goto retry;
47484769

4749-
mas->last = pivot;
4750-
return entry;
4751-
}
4770+
if (entry)
4771+
return entry;
47524772

4753-
static inline void mas_rewalk(struct ma_state *mas, unsigned long index)
4754-
{
4755-
retry:
4756-
mas_set(mas, index);
4757-
mas_state_walk(mas);
4758-
if (mas_is_start(mas))
4759-
goto retry;
4773+
if (!empty) {
4774+
if (!mas->offset)
4775+
data_end = 2;
4776+
goto again;
4777+
}
4778+
4779+
return entry;
47604780
}
47614781

47624782
/*
@@ -4774,47 +4794,12 @@ static inline void mas_rewalk(struct ma_state *mas, unsigned long index)
47744794
static inline void *mas_next_entry(struct ma_state *mas, unsigned long limit)
47754795
{
47764796
void *entry = NULL;
4777-
struct maple_node *node;
4778-
unsigned long last;
4779-
enum maple_type mt;
47804797

47814798
if (mas->last >= limit)
47824799
return NULL;
47834800

4784-
last = mas->last;
4785-
retry:
4786-
node = mas_mn(mas);
4787-
mt = mte_node_type(mas->node);
4788-
mas->offset++;
4789-
if (unlikely(mas->offset >= mt_slots[mt])) {
4790-
mas->offset = mt_slots[mt] - 1;
4791-
goto next_node;
4792-
}
4793-
4794-
while (!mas_is_none(mas)) {
4795-
entry = mas_next_nentry(mas, node, limit, mt);
4796-
if (unlikely(ma_dead_node(node))) {
4797-
mas_rewalk(mas, last);
4798-
goto retry;
4799-
}
4800-
4801-
if (likely(entry))
4802-
return entry;
4803-
4804-
if (unlikely((mas->last >= limit)))
4805-
return NULL;
4806-
4807-
next_node:
4808-
if (unlikely(mas_next_node(mas, node, limit))) {
4809-
mas_rewalk(mas, last);
4810-
goto retry;
4811-
}
4812-
mas->offset = 0;
4813-
node = mas_mn(mas);
4814-
mt = mte_node_type(mas->node);
4815-
}
4816-
4817-
return NULL;
4801+
entry = mas_next_slot(mas, limit, false);
4802+
return entry;
48184803
}
48194804

48204805
/*
@@ -4845,10 +4830,8 @@ static inline void *mas_prev_nentry(struct ma_state *mas, unsigned long limit,
48454830
slots = ma_slots(mn, mt);
48464831
pivots = ma_pivots(mn, mt);
48474832
count = ma_data_end(mn, mt, pivots, mas->max);
4848-
if (unlikely(ma_dead_node(mn))) {
4849-
mas_rewalk(mas, index);
4833+
if (unlikely(mas_rewalk_if_dead(mas, mn, index)))
48504834
goto retry;
4851-
}
48524835

48534836
offset = mas->offset - 1;
48544837
if (offset >= mt_slots[mt])
@@ -4861,10 +4844,8 @@ static inline void *mas_prev_nentry(struct ma_state *mas, unsigned long limit,
48614844
pivot = pivots[offset];
48624845
}
48634846

4864-
if (unlikely(ma_dead_node(mn))) {
4865-
mas_rewalk(mas, index);
4847+
if (unlikely(mas_rewalk_if_dead(mas, mn, index)))
48664848
goto retry;
4867-
}
48684849

48694850
while (offset && !mas_slot(mas, slots, offset)) {
48704851
pivot = pivots[--offset];
@@ -4881,10 +4862,8 @@ static inline void *mas_prev_nentry(struct ma_state *mas, unsigned long limit,
48814862

48824863
min = mas_safe_min(mas, pivots, offset);
48834864
entry = mas_slot(mas, slots, offset);
4884-
if (unlikely(ma_dead_node(mn))) {
4885-
mas_rewalk(mas, index);
4865+
if (unlikely(mas_rewalk_if_dead(mas, mn, index)))
48864866
goto retry;
4887-
}
48884867

48894868
mas->offset = offset;
48904869
mas->last = pivot;
@@ -6103,8 +6082,8 @@ void *mas_find(struct ma_state *mas, unsigned long max)
61036082
if (mas->index == max)
61046083
return NULL;
61056084

6106-
/* Retries on dead nodes handled by mas_next_entry */
6107-
return mas_next_entry(mas, max);
6085+
/* Retries on dead nodes handled by mas_next_slot */
6086+
return mas_next_slot(mas, max, false);
61086087

61096088
ptr_out_of_range:
61106089
mas->node = MAS_NONE;

0 commit comments

Comments
 (0)