Skip to content

Commit 8d8e810

Browse files
Alexander Duyckdavem330
authored andcommitted
fib_trie: Return pointer to tnode pointer in resize/inflate/halve
Resize related functions now all return a pointer to the pointer that references the object that was resized. Signed-off-by: Alexander Duyck <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 72be726 commit 8d8e810

File tree

1 file changed

+65
-41
lines changed

1 file changed

+65
-41
lines changed

net/ipv4/fib_trie.c

Lines changed: 65 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ struct trie {
144144
#endif
145145
};
146146

147-
static void resize(struct trie *t, struct tnode *tn);
147+
static struct tnode **resize(struct trie *t, struct tnode *tn);
148148
static size_t tnode_free_size;
149149

150150
/*
@@ -468,9 +468,11 @@ static void tnode_free(struct tnode *tn)
468468
}
469469
}
470470

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)
472473
{
473474
struct tnode *tp = node_parent(oldtnode);
475+
struct tnode **cptr;
474476
unsigned long i;
475477

476478
/* 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)
483485
/* all pointers should be clean so we are done */
484486
tnode_free(oldtnode);
485487

488+
/* record the pointer that is pointing to this node */
489+
cptr = tp ? tp->tnode : &t->trie;
490+
486491
/* resize children now that oldtnode is freed */
487492
for (i = tnode_child_length(tn); i;) {
488493
struct tnode *inode = tnode_get_child(tn, --i);
@@ -491,9 +496,11 @@ static void replace(struct trie *t, struct tnode *oldtnode, struct tnode *tn)
491496
if (tnode_full(tn, inode))
492497
resize(t, inode);
493498
}
499+
500+
return cptr;
494501
}
495502

496-
static int inflate(struct trie *t, struct tnode *oldtnode)
503+
static struct tnode __rcu **inflate(struct trie *t, struct tnode *oldtnode)
497504
{
498505
struct tnode *tn;
499506
unsigned long i;
@@ -503,7 +510,7 @@ static int inflate(struct trie *t, struct tnode *oldtnode)
503510

504511
tn = tnode_new(oldtnode->key, oldtnode->pos - 1, oldtnode->bits + 1);
505512
if (!tn)
506-
return -ENOMEM;
513+
goto notnode;
507514

508515
/* prepare oldtnode to be freed */
509516
tnode_free_init(oldtnode);
@@ -580,16 +587,15 @@ static int inflate(struct trie *t, struct tnode *oldtnode)
580587
}
581588

582589
/* 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);
586591
nomem:
587592
/* all pointers should be clean so we are done */
588593
tnode_free(tn);
589-
return -ENOMEM;
594+
notnode:
595+
return NULL;
590596
}
591597

592-
static int halve(struct trie *t, struct tnode *oldtnode)
598+
static struct tnode __rcu **halve(struct trie *t, struct tnode *oldtnode)
593599
{
594600
struct tnode *tn;
595601
unsigned long i;
@@ -598,7 +604,7 @@ static int halve(struct trie *t, struct tnode *oldtnode)
598604

599605
tn = tnode_new(oldtnode->key, oldtnode->pos + 1, oldtnode->bits - 1);
600606
if (!tn)
601-
return -ENOMEM;
607+
goto notnode;
602608

603609
/* prepare oldtnode to be freed */
604610
tnode_free_init(oldtnode);
@@ -621,10 +627,8 @@ static int halve(struct trie *t, struct tnode *oldtnode)
621627

622628
/* Two nonempty children */
623629
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;
628632
tnode_free_append(tn, inode);
629633

630634
/* initialize pointers out of node */
@@ -637,9 +641,12 @@ static int halve(struct trie *t, struct tnode *oldtnode)
637641
}
638642

639643
/* 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;
643650
}
644651

645652
static void collapse(struct trie *t, struct tnode *oldtnode)
@@ -796,10 +803,14 @@ static bool should_collapse(const struct tnode *tn)
796803
}
797804

798805
#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)
800807
{
808+
#ifdef CONFIG_IP_FIB_TRIE_STATS
809+
struct trie_use_stats __percpu *stats = t->stats;
810+
#endif
801811
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;
803814
int max_work = MAX_WORK;
804815

805816
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)
809820
* doing it ourselves. This way we can let RCU fully do its
810821
* thing without us interfering
811822
*/
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]));
814824

815825
/* Double as long as the resulting node has a number of
816826
* nonempty nodes that are above the threshold.
817827
*/
818828
while (should_inflate(tp, tn) && max_work) {
819-
if (inflate(t, tn)) {
829+
struct tnode __rcu **tcptr = inflate(t, tn);
830+
831+
if (!tcptr) {
820832
#ifdef CONFIG_IP_FIB_TRIE_STATS
821-
this_cpu_inc(t->stats->resize_node_skipped);
833+
this_cpu_inc(stats->resize_node_skipped);
822834
#endif
823835
break;
824836
}
825837

826838
max_work--;
827-
tn = rtnl_dereference(*cptr);
839+
cptr = tcptr;
840+
tn = rtnl_dereference(cptr[cindex]);
828841
}
829842

830843
/* Return if at least one inflate is run */
831844
if (max_work != MAX_WORK)
832-
return;
845+
return cptr;
833846

834847
/* Halve as long as the number of empty children in this
835848
* node is above threshold.
836849
*/
837850
while (should_halve(tp, tn) && max_work) {
838-
if (halve(t, tn)) {
851+
struct tnode __rcu **tcptr = halve(t, tn);
852+
853+
if (!tcptr) {
839854
#ifdef CONFIG_IP_FIB_TRIE_STATS
840-
this_cpu_inc(t->stats->resize_node_skipped);
855+
this_cpu_inc(stats->resize_node_skipped);
841856
#endif
842857
break;
843858
}
844859

845860
max_work--;
846-
tn = rtnl_dereference(*cptr);
861+
cptr = tcptr;
862+
tn = rtnl_dereference(cptr[cindex]);
847863
}
848864

849865
/* Only one child remains */
850866
if (should_collapse(tn)) {
851867
collapse(t, tn);
852-
return;
868+
return cptr;
853869
}
854870

855871
/* Return if at least one deflate was run */
856872
if (max_work != MAX_WORK)
857-
return;
873+
return cptr;
858874

859875
/* push the suffix length to the parent node */
860876
if (tn->slen > tn->pos) {
@@ -863,6 +879,8 @@ static void resize(struct trie *t, struct tnode *tn)
863879
if (tp && (slen > tp->slen))
864880
tp->slen = slen;
865881
}
882+
883+
return cptr;
866884
}
867885

868886
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,
952970

953971
static void trie_rebalance(struct trie *t, struct tnode *tn)
954972
{
955-
struct tnode *tp;
973+
struct tnode __rcu **cptr = &t->trie;
956974

957975
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]);
961982
}
962983
}
963984

964-
/* only used from updater-side */
965985
static int fib_insert_node(struct trie *t, struct tnode *tp,
966986
struct fib_alias *new, t_key key)
967987
{
968988
struct tnode *n, *l;
969989

970990
l = leaf_new(key, new);
971991
if (!l)
972-
return -ENOMEM;
992+
goto noleaf;
973993

974994
/* retrieve child from parent node */
975995
if (tp)
@@ -987,10 +1007,8 @@ static int fib_insert_node(struct trie *t, struct tnode *tp,
9871007
struct tnode *tn;
9881008

9891009
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;
9941012

9951013
/* initialize routes out of node */
9961014
NODE_INIT_PARENT(tn, tp);
@@ -1010,6 +1028,10 @@ static int fib_insert_node(struct trie *t, struct tnode *tp,
10101028
trie_rebalance(t, tp);
10111029

10121030
return 0;
1031+
notnode:
1032+
node_free(l);
1033+
noleaf:
1034+
return -ENOMEM;
10131035
}
10141036

10151037
static int fib_insert_alias(struct trie *t, struct tnode *tp,
@@ -1642,18 +1664,20 @@ int fib_table_flush(struct fib_table *tb)
16421664
/* walk trie in reverse order */
16431665
do {
16441666
while (!(cindex--)) {
1667+
struct tnode __rcu **cptr;
16451668
t_key pkey = pn->key;
16461669

16471670
n = pn;
16481671
pn = node_parent(n);
16491672

16501673
/* resize completed node */
1651-
resize(t, n);
1674+
cptr = resize(t, n);
16521675

16531676
/* if we got the root we are done */
16541677
if (!pn)
16551678
goto flush_complete;
16561679

1680+
pn = container_of(cptr, struct tnode, tnode[0]);
16571681
cindex = get_index(pkey, pn);
16581682
}
16591683

0 commit comments

Comments
 (0)