diff options
author | Eric Dumazet <edumazet@google.com> | 2024-03-06 15:51:42 +0000 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2024-03-08 11:15:35 +0000 |
commit | 46f5182dd792c55940ca520576d1544744732b81 (patch) | |
tree | fa56bda077703e9b4d55ac0a3694cd8254e4df83 /net/ipv6 | |
parent | f0a7da702093d5ff2c54ea18d6b47658be1b4522 (diff) | |
download | linux-46f5182dd792c55940ca520576d1544744732b81.tar.gz linux-46f5182dd792c55940ca520576d1544744732b81.tar.bz2 linux-46f5182dd792c55940ca520576d1544744732b81.zip |
ipv6: make in6_dump_addrs() lockless
in6_dump_addrs() is called with RCU protection.
There is no need holding idev->lock to iterate through unicast addresses.
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv6')
-rw-r--r-- | net/ipv6/addrconf.c | 14 |
1 files changed, 5 insertions, 9 deletions
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 5864a1fc6850..c662972d9206 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -5271,23 +5271,22 @@ static int inet6_fill_ifacaddr(struct sk_buff *skb, } /* called with rcu_read_lock() */ -static int in6_dump_addrs(struct inet6_dev *idev, struct sk_buff *skb, +static int in6_dump_addrs(const struct inet6_dev *idev, struct sk_buff *skb, struct netlink_callback *cb, int s_ip_idx, struct inet6_fill_args *fillargs) { - struct ifmcaddr6 *ifmca; - struct ifacaddr6 *ifaca; + const struct ifmcaddr6 *ifmca; + const struct ifacaddr6 *ifaca; int ip_idx = 0; int err = 1; - read_lock_bh(&idev->lock); switch (fillargs->type) { case UNICAST_ADDR: { - struct inet6_ifaddr *ifa; + const struct inet6_ifaddr *ifa; fillargs->event = RTM_NEWADDR; /* unicast address incl. temp addr */ - list_for_each_entry(ifa, &idev->addr_list, if_list) { + list_for_each_entry_rcu(ifa, &idev->addr_list, if_list) { if (ip_idx < s_ip_idx) goto next; err = inet6_fill_ifaddr(skb, ifa, fillargs); @@ -5300,7 +5299,6 @@ next: break; } case MULTICAST_ADDR: - read_unlock_bh(&idev->lock); fillargs->event = RTM_GETMULTICAST; /* multicast address */ @@ -5313,7 +5311,6 @@ next: if (err < 0) break; } - read_lock_bh(&idev->lock); break; case ANYCAST_ADDR: fillargs->event = RTM_GETANYCAST; @@ -5330,7 +5327,6 @@ next: default: break; } - read_unlock_bh(&idev->lock); cb->args[2] = ip_idx; return err; } |