@@ -824,6 +824,11 @@ static inline void *mt_slot(const struct maple_tree *mt,
824
824
return rcu_dereference_check (slots [offset ], mt_locked (mt ));
825
825
}
826
826
827
+ static inline void * mt_slot_locked (struct maple_tree * mt , void __rcu * * slots ,
828
+ unsigned char offset )
829
+ {
830
+ return rcu_dereference_protected (slots [offset ], mt_locked (mt ));
831
+ }
827
832
/*
828
833
* mas_slot_locked() - Get the slot value when holding the maple tree lock.
829
834
* @mas: The maple state
@@ -835,7 +840,7 @@ static inline void *mt_slot(const struct maple_tree *mt,
835
840
static inline void * mas_slot_locked (struct ma_state * mas , void __rcu * * slots ,
836
841
unsigned char offset )
837
842
{
838
- return rcu_dereference_protected ( slots [ offset ], mt_locked ( mas -> tree ) );
843
+ return mt_slot_locked ( mas -> tree , slots , offset );
839
844
}
840
845
841
846
/*
@@ -907,34 +912,35 @@ static inline void ma_set_meta(struct maple_node *mn, enum maple_type mt,
907
912
}
908
913
909
914
/*
910
- * mas_clear_meta () - clear the metadata information of a node, if it exists
911
- * @mas : The maple state
915
+ * mt_clear_meta () - clear the metadata information of a node, if it exists
916
+ * @mt : The maple tree
912
917
* @mn: The maple node
913
- * @mt : The maple node type
918
+ * @type : The maple node type
914
919
* @offset: The offset of the highest sub-gap in this node.
915
920
* @end: The end of the data in this node.
916
921
*/
917
- static inline void mas_clear_meta (struct ma_state * mas , struct maple_node * mn ,
918
- enum maple_type mt )
922
+ static inline void mt_clear_meta (struct maple_tree * mt , struct maple_node * mn ,
923
+ enum maple_type type )
919
924
{
920
925
struct maple_metadata * meta ;
921
926
unsigned long * pivots ;
922
927
void __rcu * * slots ;
923
928
void * next ;
924
929
925
- switch (mt ) {
930
+ switch (type ) {
926
931
case maple_range_64 :
927
932
pivots = mn -> mr64 .pivot ;
928
933
if (unlikely (pivots [MAPLE_RANGE64_SLOTS - 2 ])) {
929
934
slots = mn -> mr64 .slot ;
930
- next = mas_slot_locked (mas , slots ,
931
- MAPLE_RANGE64_SLOTS - 1 );
932
- if (unlikely ((mte_to_node (next ) && mte_node_type (next ))))
933
- return ; /* The last slot is a node, no metadata */
935
+ next = mt_slot_locked (mt , slots ,
936
+ MAPLE_RANGE64_SLOTS - 1 );
937
+ if (unlikely ((mte_to_node (next ) &&
938
+ mte_node_type (next ))))
939
+ return ; /* no metadata, could be node */
934
940
}
935
941
fallthrough ;
936
942
case maple_arange_64 :
937
- meta = ma_meta (mn , mt );
943
+ meta = ma_meta (mn , type );
938
944
break ;
939
945
default :
940
946
return ;
@@ -5483,7 +5489,7 @@ static inline int mas_rev_alloc(struct ma_state *mas, unsigned long min,
5483
5489
}
5484
5490
5485
5491
/*
5486
- * mas_dead_leaves () - Mark all leaves of a node as dead.
5492
+ * mte_dead_leaves () - Mark all leaves of a node as dead.
5487
5493
* @mas: The maple state
5488
5494
* @slots: Pointer to the slot array
5489
5495
* @type: The maple node type
@@ -5493,16 +5499,16 @@ static inline int mas_rev_alloc(struct ma_state *mas, unsigned long min,
5493
5499
* Return: The number of leaves marked as dead.
5494
5500
*/
5495
5501
static inline
5496
- unsigned char mas_dead_leaves (struct ma_state * mas , void __rcu * * slots ,
5497
- enum maple_type mt )
5502
+ unsigned char mte_dead_leaves (struct maple_enode * enode , struct maple_tree * mt ,
5503
+ void __rcu * * slots )
5498
5504
{
5499
5505
struct maple_node * node ;
5500
5506
enum maple_type type ;
5501
5507
void * entry ;
5502
5508
int offset ;
5503
5509
5504
- for (offset = 0 ; offset < mt_slots [ mt ] ; offset ++ ) {
5505
- entry = mas_slot_locked ( mas , slots , offset );
5510
+ for (offset = 0 ; offset < mt_slot_count ( enode ) ; offset ++ ) {
5511
+ entry = mt_slot ( mt , slots , offset );
5506
5512
type = mte_node_type (entry );
5507
5513
node = mte_to_node (entry );
5508
5514
/* Use both node and type to catch LE & BE metadata */
@@ -5517,162 +5523,160 @@ unsigned char mas_dead_leaves(struct ma_state *mas, void __rcu **slots,
5517
5523
return offset ;
5518
5524
}
5519
5525
5520
- static void __rcu * * mas_dead_walk (struct ma_state * mas , unsigned char offset )
5526
+ /**
5527
+ * mte_dead_walk() - Walk down a dead tree to just before the leaves
5528
+ * @enode: The maple encoded node
5529
+ * @offset: The starting offset
5530
+ *
5531
+ * Note: This can only be used from the RCU callback context.
5532
+ */
5533
+ static void __rcu * * mte_dead_walk (struct maple_enode * * enode , unsigned char offset )
5521
5534
{
5522
- struct maple_node * next ;
5535
+ struct maple_node * node , * next ;
5523
5536
void __rcu * * slots = NULL ;
5524
5537
5525
- next = mas_mn ( mas );
5538
+ next = mte_to_node ( * enode );
5526
5539
do {
5527
- mas -> node = mt_mk_node (next , next -> type );
5528
- slots = ma_slots (next , next -> type );
5529
- next = mas_slot_locked (mas , slots , offset );
5540
+ * enode = ma_enode_ptr (next );
5541
+ node = mte_to_node (* enode );
5542
+ slots = ma_slots (node , node -> type );
5543
+ next = rcu_dereference_protected (slots [offset ],
5544
+ lock_is_held (& rcu_callback_map ));
5530
5545
offset = 0 ;
5531
5546
} while (!ma_is_leaf (next -> type ));
5532
5547
5533
5548
return slots ;
5534
5549
}
5535
5550
5551
+ /**
5552
+ * mt_free_walk() - Walk & free a tree in the RCU callback context
5553
+ * @head: The RCU head that's within the node.
5554
+ *
5555
+ * Note: This can only be used from the RCU callback context.
5556
+ */
5536
5557
static void mt_free_walk (struct rcu_head * head )
5537
5558
{
5538
5559
void __rcu * * slots ;
5539
5560
struct maple_node * node , * start ;
5540
- struct maple_tree mt ;
5561
+ struct maple_enode * enode ;
5541
5562
unsigned char offset ;
5542
5563
enum maple_type type ;
5543
- MA_STATE (mas , & mt , 0 , 0 );
5544
5564
5545
5565
node = container_of (head , struct maple_node , rcu );
5546
5566
5547
5567
if (ma_is_leaf (node -> type ))
5548
5568
goto free_leaf ;
5549
5569
5550
- mt_init_flags (& mt , node -> ma_flags );
5551
- mas_lock (& mas );
5552
5570
start = node ;
5553
- mas . node = mt_mk_node (node , node -> type );
5554
- slots = mas_dead_walk ( & mas , 0 );
5555
- node = mas_mn ( & mas );
5571
+ enode = mt_mk_node (node , node -> type );
5572
+ slots = mte_dead_walk ( & enode , 0 );
5573
+ node = mte_to_node ( enode );
5556
5574
do {
5557
5575
mt_free_bulk (node -> slot_len , slots );
5558
5576
offset = node -> parent_slot + 1 ;
5559
- mas .node = node -> piv_parent ;
5560
- if (mas_mn (& mas ) == node )
5561
- goto start_slots_free ;
5562
-
5563
- type = mte_node_type (mas .node );
5564
- slots = ma_slots (mte_to_node (mas .node ), type );
5565
- if ((offset < mt_slots [type ]) && (slots [offset ]))
5566
- slots = mas_dead_walk (& mas , offset );
5567
-
5568
- node = mas_mn (& mas );
5577
+ enode = node -> piv_parent ;
5578
+ if (mte_to_node (enode ) == node )
5579
+ goto free_leaf ;
5580
+
5581
+ type = mte_node_type (enode );
5582
+ slots = ma_slots (mte_to_node (enode ), type );
5583
+ if ((offset < mt_slots [type ]) &&
5584
+ rcu_dereference_protected (slots [offset ],
5585
+ lock_is_held (& rcu_callback_map )))
5586
+ slots = mte_dead_walk (& enode , offset );
5587
+ node = mte_to_node (enode );
5569
5588
} while ((node != start ) || (node -> slot_len < offset ));
5570
5589
5571
5590
slots = ma_slots (node , node -> type );
5572
5591
mt_free_bulk (node -> slot_len , slots );
5573
5592
5574
- start_slots_free :
5575
- mas_unlock (& mas );
5576
5593
free_leaf :
5577
5594
mt_free_rcu (& node -> rcu );
5578
5595
}
5579
5596
5580
- static inline void __rcu * * mas_destroy_descend (struct ma_state * mas ,
5581
- struct maple_enode * prev , unsigned char offset )
5597
+ static inline void __rcu * * mte_destroy_descend (struct maple_enode * * enode ,
5598
+ struct maple_tree * mt , struct maple_enode * prev , unsigned char offset )
5582
5599
{
5583
5600
struct maple_node * node ;
5584
- struct maple_enode * next = mas -> node ;
5601
+ struct maple_enode * next = * enode ;
5585
5602
void __rcu * * slots = NULL ;
5603
+ enum maple_type type ;
5604
+ unsigned char next_offset = 0 ;
5586
5605
5587
5606
do {
5588
- mas -> node = next ;
5589
- node = mas_mn (mas );
5590
- slots = ma_slots (node , mte_node_type (mas -> node ));
5591
- next = mas_slot_locked (mas , slots , 0 );
5592
- if ((mte_dead_node (next ))) {
5593
- mte_to_node (next )-> type = mte_node_type (next );
5594
- next = mas_slot_locked (mas , slots , 1 );
5595
- }
5607
+ * enode = next ;
5608
+ node = mte_to_node (* enode );
5609
+ type = mte_node_type (* enode );
5610
+ slots = ma_slots (node , type );
5611
+ next = mt_slot_locked (mt , slots , next_offset );
5612
+ if ((mte_dead_node (next )))
5613
+ next = mt_slot_locked (mt , slots , ++ next_offset );
5596
5614
5597
- mte_set_node_dead (mas -> node );
5598
- node -> type = mte_node_type (mas -> node );
5599
- mas_clear_meta (mas , node , node -> type );
5615
+ mte_set_node_dead (* enode );
5616
+ node -> type = type ;
5600
5617
node -> piv_parent = prev ;
5601
5618
node -> parent_slot = offset ;
5602
- offset = 0 ;
5603
- prev = mas -> node ;
5619
+ offset = next_offset ;
5620
+ next_offset = 0 ;
5621
+ prev = * enode ;
5604
5622
} while (!mte_is_leaf (next ));
5605
5623
5606
5624
return slots ;
5607
5625
}
5608
5626
5609
- static void mt_destroy_walk (struct maple_enode * enode , unsigned char ma_flags ,
5627
+ static void mt_destroy_walk (struct maple_enode * enode , struct maple_tree * mt ,
5610
5628
bool free )
5611
5629
{
5612
5630
void __rcu * * slots ;
5613
5631
struct maple_node * node = mte_to_node (enode );
5614
5632
struct maple_enode * start ;
5615
- struct maple_tree mt ;
5616
-
5617
- MA_STATE (mas , & mt , 0 , 0 );
5618
5633
5619
- mas .node = enode ;
5620
5634
if (mte_is_leaf (enode )) {
5621
5635
node -> type = mte_node_type (enode );
5622
5636
goto free_leaf ;
5623
5637
}
5624
5638
5625
- ma_flags &= ~MT_FLAGS_LOCK_MASK ;
5626
- mt_init_flags (& mt , ma_flags );
5627
- mas_lock (& mas );
5628
-
5629
- mte_to_node (enode )-> ma_flags = ma_flags ;
5630
5639
start = enode ;
5631
- slots = mas_destroy_descend ( & mas , start , 0 );
5632
- node = mas_mn ( & mas );
5640
+ slots = mte_destroy_descend ( & enode , mt , start , 0 );
5641
+ node = mte_to_node ( enode ); // Updated in the above call.
5633
5642
do {
5634
5643
enum maple_type type ;
5635
5644
unsigned char offset ;
5636
5645
struct maple_enode * parent , * tmp ;
5637
5646
5638
- node -> type = mte_node_type (mas .node );
5639
- node -> slot_len = mas_dead_leaves (& mas , slots , node -> type );
5647
+ node -> slot_len = mte_dead_leaves (enode , mt , slots );
5640
5648
if (free )
5641
5649
mt_free_bulk (node -> slot_len , slots );
5642
5650
offset = node -> parent_slot + 1 ;
5643
- mas . node = node -> piv_parent ;
5644
- if (mas_mn ( & mas ) == node )
5645
- goto start_slots_free ;
5651
+ enode = node -> piv_parent ;
5652
+ if (mte_to_node ( enode ) == node )
5653
+ goto free_leaf ;
5646
5654
5647
- type = mte_node_type (mas . node );
5648
- slots = ma_slots (mte_to_node (mas . node ), type );
5655
+ type = mte_node_type (enode );
5656
+ slots = ma_slots (mte_to_node (enode ), type );
5649
5657
if (offset >= mt_slots [type ])
5650
5658
goto next ;
5651
5659
5652
- tmp = mas_slot_locked ( & mas , slots , offset );
5660
+ tmp = mt_slot_locked ( mt , slots , offset );
5653
5661
if (mte_node_type (tmp ) && mte_to_node (tmp )) {
5654
- parent = mas . node ;
5655
- mas . node = tmp ;
5656
- slots = mas_destroy_descend ( & mas , parent , offset );
5662
+ parent = enode ;
5663
+ enode = tmp ;
5664
+ slots = mte_destroy_descend ( & enode , mt , parent , offset );
5657
5665
}
5658
5666
next :
5659
- node = mas_mn ( & mas );
5660
- } while (start != mas . node );
5667
+ node = mte_to_node ( enode );
5668
+ } while (start != enode );
5661
5669
5662
- node = mas_mn (& mas );
5663
- node -> type = mte_node_type (mas .node );
5664
- node -> slot_len = mas_dead_leaves (& mas , slots , node -> type );
5670
+ node = mte_to_node (enode );
5671
+ node -> slot_len = mte_dead_leaves (enode , mt , slots );
5665
5672
if (free )
5666
5673
mt_free_bulk (node -> slot_len , slots );
5667
5674
5668
- start_slots_free :
5669
- mas_unlock (& mas );
5670
-
5671
5675
free_leaf :
5672
5676
if (free )
5673
5677
mt_free_rcu (& node -> rcu );
5674
5678
else
5675
- mas_clear_meta ( & mas , node , node -> type );
5679
+ mt_clear_meta ( mt , node , node -> type );
5676
5680
}
5677
5681
5678
5682
/*
@@ -5688,10 +5692,10 @@ static inline void mte_destroy_walk(struct maple_enode *enode,
5688
5692
struct maple_node * node = mte_to_node (enode );
5689
5693
5690
5694
if (mt_in_rcu (mt )) {
5691
- mt_destroy_walk (enode , mt -> ma_flags , false);
5695
+ mt_destroy_walk (enode , mt , false);
5692
5696
call_rcu (& node -> rcu , mt_free_walk );
5693
5697
} else {
5694
- mt_destroy_walk (enode , mt -> ma_flags , true);
5698
+ mt_destroy_walk (enode , mt , true);
5695
5699
}
5696
5700
}
5697
5701
0 commit comments