diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 05ffa54fcf21..5550a8113a6d 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c @@ -1771,6 +1771,7 @@ struct ipv6_route_iter { struct fib6_walker_t w; loff_t skip; struct fib6_table *tbl; + __u32 sernum; }; static int ipv6_route_seq_show(struct seq_file *seq, void *v) @@ -1823,6 +1824,7 @@ static void ipv6_route_seq_setup_walk(struct ipv6_route_iter *iter) iter->w.state = FWS_INIT; iter->w.node = iter->w.root; iter->w.args = iter; + iter->sernum = iter->w.root->fn_sernum; INIT_LIST_HEAD(&iter->w.lh); fib6_walker_link(&iter->w); } @@ -1848,6 +1850,17 @@ static struct fib6_table *ipv6_route_seq_next_table(struct fib6_table *tbl, return hlist_entry_safe(node, struct fib6_table, tb6_hlist); } +static void ipv6_route_check_sernum(struct ipv6_route_iter *iter) +{ + if (iter->sernum != iter->w.root->fn_sernum) { + iter->sernum = iter->w.root->fn_sernum; + iter->w.state = FWS_INIT; + iter->w.node = iter->w.root; + WARN_ON(iter->w.skip); + iter->w.skip = iter->w.count; + } +} + static void *ipv6_route_seq_next(struct seq_file *seq, void *v, loff_t *pos) { int r; @@ -1865,6 +1878,7 @@ static void *ipv6_route_seq_next(struct seq_file *seq, void *v, loff_t *pos) } iter_table: + ipv6_route_check_sernum(iter); read_lock(&iter->tbl->tb6_lock); r = fib6_walk_continue(&iter->w); read_unlock(&iter->tbl->tb6_lock);