Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: dst: introduce dst->dev_rcu

Followup of commit 88fe14253e18 ("net: dst: add four helpers
to annotate data-races around dst->dev").

We want to gradually add explicit RCU protection to dst->dev,
including lockdep support.

Add an union to alias dst->dev_rcu and dst->dev.

Add dst_dev_net_rcu() helper.

Fixes: 4a6ce2b6f2ec ("net: introduce a new function dst_dev_put()")
Signed-off-by: Eric Dumazet <edumazet@google.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://patch.msgid.link/20250828195823.3958522-2-edumazet@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Eric Dumazet and committed by
Jakub Kicinski
caedcc5b e71aa5a9

+14 -8
+11 -5
include/net/dst.h
··· 24 24 struct sk_buff; 25 25 26 26 struct dst_entry { 27 - struct net_device *dev; 27 + union { 28 + struct net_device *dev; 29 + struct net_device __rcu *dev_rcu; 30 + }; 28 31 struct dst_ops *ops; 29 32 unsigned long _metrics; 30 33 unsigned long expires; ··· 573 570 574 571 static inline struct net_device *dst_dev_rcu(const struct dst_entry *dst) 575 572 { 576 - /* In the future, use rcu_dereference(dst->dev) */ 577 - WARN_ON_ONCE(!rcu_read_lock_held()); 578 - return READ_ONCE(dst->dev); 573 + return rcu_dereference(dst->dev_rcu); 574 + } 575 + 576 + static inline struct net *dst_dev_net_rcu(const struct dst_entry *dst) 577 + { 578 + return dev_net_rcu(dst_dev_rcu(dst)); 579 579 } 580 580 581 581 static inline struct net_device *skb_dst_dev(const struct sk_buff *skb) ··· 598 592 599 593 static inline struct net *skb_dst_dev_net_rcu(const struct sk_buff *skb) 600 594 { 601 - return dev_net_rcu(skb_dst_dev(skb)); 595 + return dev_net_rcu(skb_dst_dev_rcu(skb)); 602 596 } 603 597 604 598 struct dst_entry *dst_blackhole_check(struct dst_entry *dst, u32 cookie);
+1 -1
net/core/dst.c
··· 150 150 dst->ops->ifdown(dst, dev); 151 151 WRITE_ONCE(dst->input, dst_discard); 152 152 WRITE_ONCE(dst->output, dst_discard_out); 153 - WRITE_ONCE(dst->dev, blackhole_netdev); 153 + rcu_assign_pointer(dst->dev_rcu, blackhole_netdev); 154 154 netdev_ref_replace(dev, blackhole_netdev, &dst->dev_tracker, 155 155 GFP_ATOMIC); 156 156 }
+2 -2
net/ipv4/route.c
··· 1027 1027 return; 1028 1028 1029 1029 rcu_read_lock(); 1030 - net = dev_net_rcu(dst_dev(dst)); 1030 + net = dst_dev_net_rcu(dst); 1031 1031 if (mtu < net->ipv4.ip_rt_min_pmtu) { 1032 1032 lock = true; 1033 1033 mtu = min(old_mtu, net->ipv4.ip_rt_min_pmtu); ··· 1327 1327 struct net *net; 1328 1328 1329 1329 rcu_read_lock(); 1330 - net = dev_net_rcu(dst_dev(dst)); 1330 + net = dst_dev_net_rcu(dst); 1331 1331 advmss = max_t(unsigned int, ipv4_mtu(dst) - header_size, 1332 1332 net->ipv4.ip_rt_min_advmss); 1333 1333 rcu_read_unlock();