@@ -144,7 +144,7 @@ struct trie {
144
144
#endif
145
145
};
146
146
147
- static void resize (struct trie * t , struct tnode * tn );
147
+ static struct tnode * * resize (struct trie * t , struct tnode * tn );
148
148
static size_t tnode_free_size ;
149
149
150
150
/*
@@ -468,9 +468,11 @@ static void tnode_free(struct tnode *tn)
468
468
}
469
469
}
470
470
471
- static void replace (struct trie * t , struct tnode * oldtnode , struct tnode * tn )
471
+ static struct tnode __rcu * * replace (struct trie * t , struct tnode * oldtnode ,
472
+ struct tnode * tn )
472
473
{
473
474
struct tnode * tp = node_parent (oldtnode );
475
+ struct tnode * * cptr ;
474
476
unsigned long i ;
475
477
476
478
/* setup the parent pointer out of and back into this node */
@@ -483,6 +485,9 @@ static void replace(struct trie *t, struct tnode *oldtnode, struct tnode *tn)
483
485
/* all pointers should be clean so we are done */
484
486
tnode_free (oldtnode );
485
487
488
+ /* record the pointer that is pointing to this node */
489
+ cptr = tp ? tp -> tnode : & t -> trie ;
490
+
486
491
/* resize children now that oldtnode is freed */
487
492
for (i = tnode_child_length (tn ); i ;) {
488
493
struct tnode * inode = tnode_get_child (tn , -- i );
@@ -491,9 +496,11 @@ static void replace(struct trie *t, struct tnode *oldtnode, struct tnode *tn)
491
496
if (tnode_full (tn , inode ))
492
497
resize (t , inode );
493
498
}
499
+
500
+ return cptr ;
494
501
}
495
502
496
- static int inflate (struct trie * t , struct tnode * oldtnode )
503
+ static struct tnode __rcu * * inflate (struct trie * t , struct tnode * oldtnode )
497
504
{
498
505
struct tnode * tn ;
499
506
unsigned long i ;
@@ -503,7 +510,7 @@ static int inflate(struct trie *t, struct tnode *oldtnode)
503
510
504
511
tn = tnode_new (oldtnode -> key , oldtnode -> pos - 1 , oldtnode -> bits + 1 );
505
512
if (!tn )
506
- return - ENOMEM ;
513
+ goto notnode ;
507
514
508
515
/* prepare oldtnode to be freed */
509
516
tnode_free_init (oldtnode );
@@ -580,16 +587,15 @@ static int inflate(struct trie *t, struct tnode *oldtnode)
580
587
}
581
588
582
589
/* setup the parent pointers into and out of this node */
583
- replace (t , oldtnode , tn );
584
-
585
- return 0 ;
590
+ return replace (t , oldtnode , tn );
586
591
nomem :
587
592
/* all pointers should be clean so we are done */
588
593
tnode_free (tn );
589
- return - ENOMEM ;
594
+ notnode :
595
+ return NULL ;
590
596
}
591
597
592
- static int halve (struct trie * t , struct tnode * oldtnode )
598
+ static struct tnode __rcu * * halve (struct trie * t , struct tnode * oldtnode )
593
599
{
594
600
struct tnode * tn ;
595
601
unsigned long i ;
@@ -598,7 +604,7 @@ static int halve(struct trie *t, struct tnode *oldtnode)
598
604
599
605
tn = tnode_new (oldtnode -> key , oldtnode -> pos + 1 , oldtnode -> bits - 1 );
600
606
if (!tn )
601
- return - ENOMEM ;
607
+ goto notnode ;
602
608
603
609
/* prepare oldtnode to be freed */
604
610
tnode_free_init (oldtnode );
@@ -621,10 +627,8 @@ static int halve(struct trie *t, struct tnode *oldtnode)
621
627
622
628
/* Two nonempty children */
623
629
inode = tnode_new (node0 -> key , oldtnode -> pos , 1 );
624
- if (!inode ) {
625
- tnode_free (tn );
626
- return - ENOMEM ;
627
- }
630
+ if (!inode )
631
+ goto nomem ;
628
632
tnode_free_append (tn , inode );
629
633
630
634
/* initialize pointers out of node */
@@ -637,9 +641,12 @@ static int halve(struct trie *t, struct tnode *oldtnode)
637
641
}
638
642
639
643
/* setup the parent pointers into and out of this node */
640
- replace (t , oldtnode , tn );
641
-
642
- return 0 ;
644
+ return replace (t , oldtnode , tn );
645
+ nomem :
646
+ /* all pointers should be clean so we are done */
647
+ tnode_free (tn );
648
+ notnode :
649
+ return NULL ;
643
650
}
644
651
645
652
static void collapse (struct trie * t , struct tnode * oldtnode )
@@ -796,10 +803,14 @@ static bool should_collapse(const struct tnode *tn)
796
803
}
797
804
798
805
#define MAX_WORK 10
799
- static void resize (struct trie * t , struct tnode * tn )
806
+ static struct tnode __rcu * * resize (struct trie * t , struct tnode * tn )
800
807
{
808
+ #ifdef CONFIG_IP_FIB_TRIE_STATS
809
+ struct trie_use_stats __percpu * stats = t -> stats ;
810
+ #endif
801
811
struct tnode * tp = node_parent (tn );
802
- struct tnode __rcu * * cptr ;
812
+ unsigned long cindex = tp ? get_index (tn -> key , tp ) : 0 ;
813
+ struct tnode __rcu * * cptr = tp ? tp -> tnode : & t -> trie ;
803
814
int max_work = MAX_WORK ;
804
815
805
816
pr_debug ("In tnode_resize %p inflate_threshold=%d threshold=%d\n" ,
@@ -809,52 +820,57 @@ static void resize(struct trie *t, struct tnode *tn)
809
820
* doing it ourselves. This way we can let RCU fully do its
810
821
* thing without us interfering
811
822
*/
812
- cptr = tp ? & tp -> tnode [get_index (tn -> key , tp )] : & t -> trie ;
813
- BUG_ON (tn != rtnl_dereference (* cptr ));
823
+ BUG_ON (tn != rtnl_dereference (cptr [cindex ]));
814
824
815
825
/* Double as long as the resulting node has a number of
816
826
* nonempty nodes that are above the threshold.
817
827
*/
818
828
while (should_inflate (tp , tn ) && max_work ) {
819
- if (inflate (t , tn )) {
829
+ struct tnode __rcu * * tcptr = inflate (t , tn );
830
+
831
+ if (!tcptr ) {
820
832
#ifdef CONFIG_IP_FIB_TRIE_STATS
821
- this_cpu_inc (t -> stats -> resize_node_skipped );
833
+ this_cpu_inc (stats -> resize_node_skipped );
822
834
#endif
823
835
break ;
824
836
}
825
837
826
838
max_work -- ;
827
- tn = rtnl_dereference (* cptr );
839
+ cptr = tcptr ;
840
+ tn = rtnl_dereference (cptr [cindex ]);
828
841
}
829
842
830
843
/* Return if at least one inflate is run */
831
844
if (max_work != MAX_WORK )
832
- return ;
845
+ return cptr ;
833
846
834
847
/* Halve as long as the number of empty children in this
835
848
* node is above threshold.
836
849
*/
837
850
while (should_halve (tp , tn ) && max_work ) {
838
- if (halve (t , tn )) {
851
+ struct tnode __rcu * * tcptr = halve (t , tn );
852
+
853
+ if (!tcptr ) {
839
854
#ifdef CONFIG_IP_FIB_TRIE_STATS
840
- this_cpu_inc (t -> stats -> resize_node_skipped );
855
+ this_cpu_inc (stats -> resize_node_skipped );
841
856
#endif
842
857
break ;
843
858
}
844
859
845
860
max_work -- ;
846
- tn = rtnl_dereference (* cptr );
861
+ cptr = tcptr ;
862
+ tn = rtnl_dereference (cptr [cindex ]);
847
863
}
848
864
849
865
/* Only one child remains */
850
866
if (should_collapse (tn )) {
851
867
collapse (t , tn );
852
- return ;
868
+ return cptr ;
853
869
}
854
870
855
871
/* Return if at least one deflate was run */
856
872
if (max_work != MAX_WORK )
857
- return ;
873
+ return cptr ;
858
874
859
875
/* push the suffix length to the parent node */
860
876
if (tn -> slen > tn -> pos ) {
@@ -863,6 +879,8 @@ static void resize(struct trie *t, struct tnode *tn)
863
879
if (tp && (slen > tp -> slen ))
864
880
tp -> slen = slen ;
865
881
}
882
+
883
+ return cptr ;
866
884
}
867
885
868
886
static void leaf_pull_suffix (struct tnode * tp , struct tnode * l )
@@ -952,24 +970,26 @@ static struct fib_alias *fib_find_alias(struct hlist_head *fah, u8 slen,
952
970
953
971
static void trie_rebalance (struct trie * t , struct tnode * tn )
954
972
{
955
- struct tnode * tp ;
973
+ struct tnode __rcu * * cptr = & t -> trie ;
956
974
957
975
while (tn ) {
958
- tp = node_parent (tn );
959
- resize (t , tn );
960
- tn = tp ;
976
+ struct tnode * tp = node_parent (tn );
977
+
978
+ cptr = resize (t , tn );
979
+ if (!tp )
980
+ break ;
981
+ tn = container_of (cptr , struct tnode , tnode [0 ]);
961
982
}
962
983
}
963
984
964
- /* only used from updater-side */
965
985
static int fib_insert_node (struct trie * t , struct tnode * tp ,
966
986
struct fib_alias * new , t_key key )
967
987
{
968
988
struct tnode * n , * l ;
969
989
970
990
l = leaf_new (key , new );
971
991
if (!l )
972
- return - ENOMEM ;
992
+ goto noleaf ;
973
993
974
994
/* retrieve child from parent node */
975
995
if (tp )
@@ -987,10 +1007,8 @@ static int fib_insert_node(struct trie *t, struct tnode *tp,
987
1007
struct tnode * tn ;
988
1008
989
1009
tn = tnode_new (key , __fls (key ^ n -> key ), 1 );
990
- if (!tn ) {
991
- node_free (l );
992
- return - ENOMEM ;
993
- }
1010
+ if (!tn )
1011
+ goto notnode ;
994
1012
995
1013
/* initialize routes out of node */
996
1014
NODE_INIT_PARENT (tn , tp );
@@ -1010,6 +1028,10 @@ static int fib_insert_node(struct trie *t, struct tnode *tp,
1010
1028
trie_rebalance (t , tp );
1011
1029
1012
1030
return 0 ;
1031
+ notnode :
1032
+ node_free (l );
1033
+ noleaf :
1034
+ return - ENOMEM ;
1013
1035
}
1014
1036
1015
1037
static int fib_insert_alias (struct trie * t , struct tnode * tp ,
@@ -1642,18 +1664,20 @@ int fib_table_flush(struct fib_table *tb)
1642
1664
/* walk trie in reverse order */
1643
1665
do {
1644
1666
while (!(cindex -- )) {
1667
+ struct tnode __rcu * * cptr ;
1645
1668
t_key pkey = pn -> key ;
1646
1669
1647
1670
n = pn ;
1648
1671
pn = node_parent (n );
1649
1672
1650
1673
/* resize completed node */
1651
- resize (t , n );
1674
+ cptr = resize (t , n );
1652
1675
1653
1676
/* if we got the root we are done */
1654
1677
if (!pn )
1655
1678
goto flush_complete ;
1656
1679
1680
+ pn = container_of (cptr , struct tnode , tnode [0 ]);
1657
1681
cindex = get_index (pkey , pn );
1658
1682
}
1659
1683
0 commit comments