Skip to content

Commit 53cd014

Browse files
author
Hangbin Liu
committed
dev: Pass netdevice_tracker to dev_get_by_flags_rcu().
JIRA: https://issues.redhat.com/browse/RHEL-115325 Upstream Status: net.git commit 2a683d0 commit 2a683d0 Author: Kuniyuki Iwashima <kuniyu@google.com> Date: Fri Jul 11 05:10:59 2025 +0000 dev: Pass netdevice_tracker to dev_get_by_flags_rcu(). This is a follow-up for commit eb1ac9f ("ipv6: anycast: Don't hold RTNL for IPV6_JOIN_ANYCAST."). We should not add a new device lookup API without netdevice_tracker. Let's pass netdevice_tracker to dev_get_by_flags_rcu() and rename it with netdev_ prefix to match other newer APIs. Note that we always use GFP_ATOMIC for netdev_hold() as it's expected to be called under RCU. Suggested-by: Jakub Kicinski <kuba@kernel.org> Link: https://lore.kernel.org/netdev/20250708184053.102109f6@kernel.org/ Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com> Reviewed-by: Simon Horman <horms@kernel.org> Link: https://patch.msgid.link/20250711051120.2866855-1-kuniyu@google.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Hangbin Liu <haliu@redhat.com>
1 parent 4050137 commit 53cd014

File tree

3 files changed

+14
-12
lines changed

3 files changed

+14
-12
lines changed

include/linux/netdevice.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3160,8 +3160,6 @@ int dev_get_iflink(const struct net_device *dev);
31603160
int dev_fill_metadata_dst(struct net_device *dev, struct sk_buff *skb);
31613161
int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
31623162
struct net_device_path_stack *stack);
3163-
struct net_device *dev_get_by_flags_rcu(struct net *net, unsigned short flags,
3164-
unsigned short mask);
31653163
struct net_device *dev_get_by_name(struct net *net, const char *name);
31663164
struct net_device *dev_get_by_name_rcu(struct net *net, const char *name);
31673165
struct net_device *__dev_get_by_name(struct net *net, const char *name);
@@ -3222,6 +3220,8 @@ struct net_device *netdev_get_by_index(struct net *net, int ifindex,
32223220
netdevice_tracker *tracker, gfp_t gfp);
32233221
struct net_device *netdev_get_by_name(struct net *net, const char *name,
32243222
netdevice_tracker *tracker, gfp_t gfp);
3223+
struct net_device *netdev_get_by_flags_rcu(struct net *net, netdevice_tracker *tracker,
3224+
unsigned short flags, unsigned short mask);
32253225
struct net_device *dev_get_by_index_rcu(struct net *net, int ifindex);
32263226
void netdev_copy_name(struct net_device *dev, char *name);
32273227

net/core/dev.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,8 +1102,9 @@ struct net_device *dev_getfirstbyhwtype(struct net *net, unsigned short type)
11021102
EXPORT_SYMBOL(dev_getfirstbyhwtype);
11031103

11041104
/**
1105-
* dev_get_by_flags_rcu - find any device with given flags
1105+
* netdev_get_by_flags_rcu - find any device with given flags
11061106
* @net: the applicable net namespace
1107+
* @tracker: tracking object for the acquired reference
11071108
* @if_flags: IFF_* values
11081109
* @mask: bitmask of bits in if_flags to check
11091110
*
@@ -1112,21 +1113,21 @@ EXPORT_SYMBOL(dev_getfirstbyhwtype);
11121113
* Context: rcu_read_lock() must be held.
11131114
* Returns: NULL if a device is not found or a pointer to the device.
11141115
*/
1115-
struct net_device *dev_get_by_flags_rcu(struct net *net, unsigned short if_flags,
1116-
unsigned short mask)
1116+
struct net_device *netdev_get_by_flags_rcu(struct net *net, netdevice_tracker *tracker,
1117+
unsigned short if_flags, unsigned short mask)
11171118
{
11181119
struct net_device *dev;
11191120

11201121
for_each_netdev_rcu(net, dev) {
11211122
if (((READ_ONCE(dev->flags) ^ if_flags) & mask) == 0) {
1122-
dev_hold(dev);
1123+
netdev_hold(dev, tracker, GFP_ATOMIC);
11231124
return dev;
11241125
}
11251126
}
11261127

11271128
return NULL;
11281129
}
1129-
EXPORT_IPV6_MOD(dev_get_by_flags_rcu);
1130+
EXPORT_IPV6_MOD(netdev_get_by_flags_rcu);
11301131

11311132
/**
11321133
* dev_valid_name - check if name is okay for network device

net/ipv6/anycast.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
6969
struct ipv6_pinfo *np = inet6_sk(sk);
7070
struct ipv6_ac_socklist *pac = NULL;
7171
struct net *net = sock_net(sk);
72+
netdevice_tracker dev_tracker;
7273
struct net_device *dev = NULL;
7374
struct inet6_dev *idev;
7475
int err = 0, ishost;
@@ -79,7 +80,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
7980
return -EINVAL;
8081

8182
if (ifindex)
82-
dev = dev_get_by_index(net, ifindex);
83+
dev = netdev_get_by_index(net, ifindex, &dev_tracker, GFP_KERNEL);
8384

8485
if (ipv6_chk_addr_and_flags(net, addr, dev, true, 0, IFA_F_TENTATIVE)) {
8586
err = -EINVAL;
@@ -104,16 +105,16 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
104105
rt = rt6_lookup(net, addr, NULL, 0, NULL, 0);
105106
if (rt) {
106107
dev = dst_dev(&rt->dst);
107-
dev_hold(dev);
108+
netdev_hold(dev, &dev_tracker, GFP_ATOMIC);
108109
ip6_rt_put(rt);
109110
} else if (ishost) {
110111
rcu_read_unlock();
111112
err = -EADDRNOTAVAIL;
112113
goto error;
113114
} else {
114115
/* router, no matching interface: just pick one */
115-
dev = dev_get_by_flags_rcu(net, IFF_UP,
116-
IFF_UP | IFF_LOOPBACK);
116+
dev = netdev_get_by_flags_rcu(net, &dev_tracker, IFF_UP,
117+
IFF_UP | IFF_LOOPBACK);
117118
}
118119
rcu_read_unlock();
119120
}
@@ -159,7 +160,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)
159160
error_idev:
160161
in6_dev_put(idev);
161162
error:
162-
dev_put(dev);
163+
netdev_put(dev, &dev_tracker);
163164

164165
if (pac)
165166
sock_kfree_s(sk, pac, sizeof(*pac));

0 commit comments

Comments
 (0)