diff options
author | Hannes Frederic Sowa <hannes@stressinduktion.org> | 2014-10-06 13:58:38 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-10-07 00:02:30 -0400 |
commit | 327571cb100cad587c9eda351e7a2d182466873b (patch) | |
tree | 586acd1e34fa9855cbe336ea70f987bc62e08dc8 /net/ipv6/ip6_fib.c | |
parent | 812918c464eca0e8c145f975932ca5020e9c05cb (diff) |
ipv6: don't walk node's leaf during serial number update
Cc: YOSHIFUJI Hideaki <hideaki@yoshifuji.org>
Cc: Martin Lau <kafai@fb.com>
Signed-off-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6/ip6_fib.c')
-rw-r--r-- | net/ipv6/ip6_fib.c | 47 |
1 files changed, 30 insertions, 17 deletions
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 6f9beb1f2861..b2d1838897c9 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -50,6 +50,7 @@ struct fib6_cleaner { | |||
50 | struct fib6_walker w; | 50 | struct fib6_walker w; |
51 | struct net *net; | 51 | struct net *net; |
52 | int (*func)(struct rt6_info *, void *arg); | 52 | int (*func)(struct rt6_info *, void *arg); |
53 | int sernum; | ||
53 | void *arg; | 54 | void *arg; |
54 | }; | 55 | }; |
55 | 56 | ||
@@ -105,6 +106,10 @@ static int fib6_new_sernum(struct net *net) | |||
105 | return new; | 106 | return new; |
106 | } | 107 | } |
107 | 108 | ||
109 | enum { | ||
110 | FIB6_NO_SERNUM_CHANGE = 0, | ||
111 | }; | ||
112 | |||
108 | /* | 113 | /* |
109 | * Auxiliary address test functions for the radix tree. | 114 | * Auxiliary address test functions for the radix tree. |
110 | * | 115 | * |
@@ -1514,6 +1519,16 @@ static int fib6_clean_node(struct fib6_walker *w) | |||
1514 | .nl_net = c->net, | 1519 | .nl_net = c->net, |
1515 | }; | 1520 | }; |
1516 | 1521 | ||
1522 | if (c->sernum != FIB6_NO_SERNUM_CHANGE && | ||
1523 | w->node->fn_sernum != c->sernum) | ||
1524 | w->node->fn_sernum = c->sernum; | ||
1525 | |||
1526 | if (!c->func) { | ||
1527 | WARN_ON_ONCE(c->sernum == FIB6_NO_SERNUM_CHANGE); | ||
1528 | w->leaf = NULL; | ||
1529 | return 0; | ||
1530 | } | ||
1531 | |||
1517 | for (rt = w->leaf; rt; rt = rt->dst.rt6_next) { | 1532 | for (rt = w->leaf; rt; rt = rt->dst.rt6_next) { |
1518 | res = c->func(rt, c->arg); | 1533 | res = c->func(rt, c->arg); |
1519 | if (res < 0) { | 1534 | if (res < 0) { |
@@ -1547,7 +1562,7 @@ static int fib6_clean_node(struct fib6_walker *w) | |||
1547 | 1562 | ||
1548 | static void fib6_clean_tree(struct net *net, struct fib6_node *root, | 1563 | static void fib6_clean_tree(struct net *net, struct fib6_node *root, |
1549 | int (*func)(struct rt6_info *, void *arg), | 1564 | int (*func)(struct rt6_info *, void *arg), |
1550 | bool prune, void *arg) | 1565 | bool prune, int sernum, void *arg) |
1551 | { | 1566 | { |
1552 | struct fib6_cleaner c; | 1567 | struct fib6_cleaner c; |
1553 | 1568 | ||
@@ -1557,14 +1572,16 @@ static void fib6_clean_tree(struct net *net, struct fib6_node *root, | |||
1557 | c.w.count = 0; | 1572 | c.w.count = 0; |
1558 | c.w.skip = 0; | 1573 | c.w.skip = 0; |
1559 | c.func = func; | 1574 | c.func = func; |
1575 | c.sernum = sernum; | ||
1560 | c.arg = arg; | 1576 | c.arg = arg; |
1561 | c.net = net; | 1577 | c.net = net; |
1562 | 1578 | ||
1563 | fib6_walk(&c.w); | 1579 | fib6_walk(&c.w); |
1564 | } | 1580 | } |
1565 | 1581 | ||
1566 | void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg), | 1582 | static void __fib6_clean_all(struct net *net, |
1567 | void *arg) | 1583 | int (*func)(struct rt6_info *, void *), |
1584 | int sernum, void *arg) | ||
1568 | { | 1585 | { |
1569 | struct fib6_table *table; | 1586 | struct fib6_table *table; |
1570 | struct hlist_head *head; | 1587 | struct hlist_head *head; |
@@ -1576,13 +1593,19 @@ void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *arg), | |||
1576 | hlist_for_each_entry_rcu(table, head, tb6_hlist) { | 1593 | hlist_for_each_entry_rcu(table, head, tb6_hlist) { |
1577 | write_lock_bh(&table->tb6_lock); | 1594 | write_lock_bh(&table->tb6_lock); |
1578 | fib6_clean_tree(net, &table->tb6_root, | 1595 | fib6_clean_tree(net, &table->tb6_root, |
1579 | func, false, arg); | 1596 | func, false, sernum, arg); |
1580 | write_unlock_bh(&table->tb6_lock); | 1597 | write_unlock_bh(&table->tb6_lock); |
1581 | } | 1598 | } |
1582 | } | 1599 | } |
1583 | rcu_read_unlock(); | 1600 | rcu_read_unlock(); |
1584 | } | 1601 | } |
1585 | 1602 | ||
1603 | void fib6_clean_all(struct net *net, int (*func)(struct rt6_info *, void *), | ||
1604 | void *arg) | ||
1605 | { | ||
1606 | __fib6_clean_all(net, func, FIB6_NO_SERNUM_CHANGE, arg); | ||
1607 | } | ||
1608 | |||
1586 | static int fib6_prune_clone(struct rt6_info *rt, void *arg) | 1609 | static int fib6_prune_clone(struct rt6_info *rt, void *arg) |
1587 | { | 1610 | { |
1588 | if (rt->rt6i_flags & RTF_CACHE) { | 1611 | if (rt->rt6i_flags & RTF_CACHE) { |
@@ -1595,25 +1618,15 @@ static int fib6_prune_clone(struct rt6_info *rt, void *arg) | |||
1595 | 1618 | ||
1596 | static void fib6_prune_clones(struct net *net, struct fib6_node *fn) | 1619 | static void fib6_prune_clones(struct net *net, struct fib6_node *fn) |
1597 | { | 1620 | { |
1598 | fib6_clean_tree(net, fn, fib6_prune_clone, true, NULL); | 1621 | fib6_clean_tree(net, fn, fib6_prune_clone, true, |
1599 | } | 1622 | FIB6_NO_SERNUM_CHANGE, NULL); |
1600 | |||
1601 | static int fib6_update_sernum(struct rt6_info *rt, void *arg) | ||
1602 | { | ||
1603 | int sernum = *(int *)arg; | ||
1604 | |||
1605 | if (rt->rt6i_node && | ||
1606 | rt->rt6i_node->fn_sernum != sernum) | ||
1607 | rt->rt6i_node->fn_sernum = sernum; | ||
1608 | |||
1609 | return 0; | ||
1610 | } | 1623 | } |
1611 | 1624 | ||
1612 | static void fib6_flush_trees(struct net *net) | 1625 | static void fib6_flush_trees(struct net *net) |
1613 | { | 1626 | { |
1614 | int new_sernum = fib6_new_sernum(net); | 1627 | int new_sernum = fib6_new_sernum(net); |
1615 | 1628 | ||
1616 | fib6_clean_all(net, fib6_update_sernum, &new_sernum); | 1629 | __fib6_clean_all(net, NULL, new_sernum, NULL); |
1617 | } | 1630 | } |
1618 | 1631 | ||
1619 | /* | 1632 | /* |