@@ -1399,25 +1399,6 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp,
1399
1399
}
1400
1400
EXPORT_SYMBOL_GPL (fib_table_lookup );
1401
1401
1402
- /*
1403
- * Remove the leaf and return parent.
1404
- */
1405
- static void trie_leaf_remove (struct trie * t , struct tnode * l )
1406
- {
1407
- struct tnode * tp = node_parent (l );
1408
-
1409
- pr_debug ("entering trie_leaf_remove(%p)\n" , l );
1410
-
1411
- if (tp ) {
1412
- put_child (tp , get_index (l -> key , tp ), NULL );
1413
- trie_rebalance (t , tp );
1414
- } else {
1415
- RCU_INIT_POINTER (t -> trie , NULL );
1416
- }
1417
-
1418
- node_free (l );
1419
- }
1420
-
1421
1402
/*
1422
1403
* Caller must hold RTNL.
1423
1404
*/
@@ -1483,8 +1464,18 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
1483
1464
if (!plen )
1484
1465
tb -> tb_num_default -- ;
1485
1466
1486
- if (hlist_empty (& l -> leaf ))
1487
- trie_leaf_remove (t , l );
1467
+ if (hlist_empty (& l -> leaf )) {
1468
+ struct tnode * tp = node_parent (l );
1469
+
1470
+ if (tp ) {
1471
+ put_child (tp , get_index (l -> key , tp ), NULL );
1472
+ trie_rebalance (t , tp );
1473
+ } else {
1474
+ RCU_INIT_POINTER (t -> trie , NULL );
1475
+ }
1476
+
1477
+ node_free (l );
1478
+ }
1488
1479
1489
1480
if (fa -> fa_state & FA_S_ACCESSED )
1490
1481
rt_cache_flush (cfg -> fc_nlinfo .nl_net );
@@ -1494,33 +1485,6 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
1494
1485
return 0 ;
1495
1486
}
1496
1487
1497
- static int trie_flush_leaf (struct tnode * l )
1498
- {
1499
- struct hlist_node * tmp ;
1500
- unsigned char slen = 0 ;
1501
- struct fib_alias * fa ;
1502
- int found = 0 ;
1503
-
1504
- hlist_for_each_entry_safe (fa , tmp , & l -> leaf , fa_list ) {
1505
- struct fib_info * fi = fa -> fa_info ;
1506
-
1507
- if (fi && (fi -> fib_flags & RTNH_F_DEAD )) {
1508
- hlist_del_rcu (& fa -> fa_list );
1509
- fib_release_info (fa -> fa_info );
1510
- alias_free_mem_rcu (fa );
1511
- found ++ ;
1512
-
1513
- continue ;
1514
- }
1515
-
1516
- slen = fa -> fa_slen ;
1517
- }
1518
-
1519
- l -> slen = slen ;
1520
-
1521
- return found ;
1522
- }
1523
-
1524
1488
/* Scan for the next right leaf starting at node p->child[idx]
1525
1489
* Since we have back pointer, no recursion necessary.
1526
1490
*/
@@ -1588,30 +1552,81 @@ static struct tnode *trie_leafindex(struct trie *t, int index)
1588
1552
*/
1589
1553
int fib_table_flush (struct fib_table * tb )
1590
1554
{
1591
- struct trie * t = (struct trie * ) tb -> tb_data ;
1592
- struct tnode * l , * ll = NULL ;
1555
+ struct trie * t = (struct trie * )tb -> tb_data ;
1556
+ struct hlist_node * tmp ;
1557
+ struct fib_alias * fa ;
1558
+ struct tnode * n , * pn ;
1559
+ unsigned long cindex ;
1560
+ unsigned char slen ;
1593
1561
int found = 0 ;
1594
1562
1595
- for (l = trie_firstleaf (t ); l ; l = trie_nextleaf (l )) {
1596
- found += trie_flush_leaf (l );
1563
+ n = rcu_dereference (t -> trie );
1564
+ if (!n )
1565
+ goto flush_complete ;
1566
+
1567
+ pn = NULL ;
1568
+ cindex = 0 ;
1569
+
1570
+ while (IS_TNODE (n )) {
1571
+ /* record pn and cindex for leaf walking */
1572
+ pn = n ;
1573
+ cindex = 1ul << n -> bits ;
1574
+ backtrace :
1575
+ /* walk trie in reverse order */
1576
+ do {
1577
+ while (!(cindex -- )) {
1578
+ t_key pkey = pn -> key ;
1579
+
1580
+ n = pn ;
1581
+ pn = node_parent (n );
1582
+
1583
+ /* resize completed node */
1584
+ resize (t , n );
1585
+
1586
+ /* if we got the root we are done */
1587
+ if (!pn )
1588
+ goto flush_complete ;
1597
1589
1598
- if (ll ) {
1599
- if (hlist_empty (& ll -> leaf ))
1600
- trie_leaf_remove (t , ll );
1601
- else
1602
- leaf_pull_suffix (ll );
1590
+ cindex = get_index (pkey , pn );
1591
+ }
1592
+
1593
+ /* grab the next available node */
1594
+ n = tnode_get_child (pn , cindex );
1595
+ } while (!n );
1596
+ }
1597
+
1598
+ /* track slen in case any prefixes survive */
1599
+ slen = 0 ;
1600
+
1601
+ hlist_for_each_entry_safe (fa , tmp , & n -> leaf , fa_list ) {
1602
+ struct fib_info * fi = fa -> fa_info ;
1603
+
1604
+ if (fi && (fi -> fib_flags & RTNH_F_DEAD )) {
1605
+ hlist_del_rcu (& fa -> fa_list );
1606
+ fib_release_info (fa -> fa_info );
1607
+ alias_free_mem_rcu (fa );
1608
+ found ++ ;
1609
+
1610
+ continue ;
1603
1611
}
1604
1612
1605
- ll = l ;
1613
+ slen = fa -> fa_slen ;
1606
1614
}
1607
1615
1608
- if (ll ) {
1609
- if (hlist_empty (& ll -> leaf ))
1610
- trie_leaf_remove (t , ll );
1611
- else
1612
- leaf_pull_suffix (ll );
1616
+ /* update leaf slen */
1617
+ n -> slen = slen ;
1618
+
1619
+ if (hlist_empty (& n -> leaf )) {
1620
+ put_child_root (pn , t , n -> key , NULL );
1621
+ node_free (n );
1622
+ } else {
1623
+ leaf_pull_suffix (n );
1613
1624
}
1614
1625
1626
+ /* if trie is leaf only loop is completed */
1627
+ if (pn )
1628
+ goto backtrace ;
1629
+ flush_complete :
1615
1630
pr_debug ("trie_flush found=%d\n" , found );
1616
1631
return found ;
1617
1632
}
0 commit comments