Commit 86f9bd1f authored by Jeff Barnhill's avatar Jeff Barnhill Committed by David S. Miller

net/ipv6: Display all addresses in output of /proc/net/if_inet6

The backend handling for /proc/net/if_inet6 in addrconf.c doesn't properly
handle starting/stopping the iteration.  The problem is that at some point
during the iteration, an overflow is detected and the process is
subsequently stopped.  The item being shown via seq_printf() when the
overflow occurs is not actually shown, though.  When start() is
subsequently called to resume iterating, it returns the next item, and
thus the item that was being processed when the overflow occurred never
gets printed.

Alter the meaning of the private data member "offset".  Currently, when it
is not 0 (which only happens at the very beginning), "offset" represents
the next hlist item to be printed.  After this change, "offset" always
represents the current item.

This is also consistent with the private data member "bucket", which
represents the current bucket, and also the use of "pos" as defined in
seq_file.txt:
    The pos passed to start() will always be either zero, or the most
    recent pos used in the previous session.
Signed-off-by: default avatarJeff Barnhill <0xeffeff@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f88b4c01
...@@ -4201,7 +4201,6 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq, loff_t pos) ...@@ -4201,7 +4201,6 @@ static struct inet6_ifaddr *if6_get_first(struct seq_file *seq, loff_t pos)
p++; p++;
continue; continue;
} }
state->offset++;
return ifa; return ifa;
} }
...@@ -4225,13 +4224,12 @@ static struct inet6_ifaddr *if6_get_next(struct seq_file *seq, ...@@ -4225,13 +4224,12 @@ static struct inet6_ifaddr *if6_get_next(struct seq_file *seq,
return ifa; return ifa;
} }
state->offset = 0;
while (++state->bucket < IN6_ADDR_HSIZE) { while (++state->bucket < IN6_ADDR_HSIZE) {
state->offset = 0;
hlist_for_each_entry_rcu(ifa, hlist_for_each_entry_rcu(ifa,
&inet6_addr_lst[state->bucket], addr_lst) { &inet6_addr_lst[state->bucket], addr_lst) {
if (!net_eq(dev_net(ifa->idev->dev), net)) if (!net_eq(dev_net(ifa->idev->dev), net))
continue; continue;
state->offset++;
return ifa; return ifa;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment