]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: dst: introduce dst->dev_rcu
authorEric Dumazet <edumazet@google.com>
Mon, 15 Dec 2025 21:51:18 +0000 (21:51 +0000)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 18 Dec 2025 12:55:22 +0000 (13:55 +0100)
[ Upstream commit caedcc5b6df1b2e2b5f39079e3369c1d4d5c5f50 ]

Followup of commit 88fe14253e1818 ("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()")
Cc: stable@vger.kernel.org
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>
Stable-dep-of: 50c127a69cd62 ("Replace three dst_dev() with a lockdep enabled helper.")
Signed-off-by: Gyokhan Kochmarla <gyokhan@amazon.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
include/net/dst.h
net/core/dst.c
net/ipv4/route.c

index e5c9ea18838381af79df0ab3189bd4845a5fb2d1..e7c1eb69570ec205bf43cb604dda562453ec3c82 100644 (file)
 struct sk_buff;
 
 struct dst_entry {
-       struct net_device       *dev;
+       union {
+               struct net_device       *dev;
+               struct net_device __rcu *dev_rcu;
+       };
        struct  dst_ops         *ops;
        unsigned long           _metrics;
        unsigned long           expires;
@@ -568,9 +571,12 @@ static inline struct net_device *dst_dev(const struct dst_entry *dst)
 
 static inline struct net_device *dst_dev_rcu(const struct dst_entry *dst)
 {
-       /* In the future, use rcu_dereference(dst->dev) */
-       WARN_ON_ONCE(!rcu_read_lock_held());
-       return READ_ONCE(dst->dev);
+       return rcu_dereference(dst->dev_rcu);
+}
+
+static inline struct net *dst_dev_net_rcu(const struct dst_entry *dst)
+{
+       return dev_net_rcu(dst_dev_rcu(dst));
 }
 
 static inline struct net_device *skb_dst_dev(const struct sk_buff *skb)
@@ -590,7 +596,7 @@ static inline struct net *skb_dst_dev_net(const struct sk_buff *skb)
 
 static inline struct net *skb_dst_dev_net_rcu(const struct sk_buff *skb)
 {
-       return dev_net_rcu(skb_dst_dev(skb));
+       return dev_net_rcu(skb_dst_dev_rcu(skb));
 }
 
 struct dst_entry *dst_blackhole_check(struct dst_entry *dst, u32 cookie);
index 9a0ddef8bee43042bfcdb40b72602ae69521a6dd..8dbb54148c038d8ac1aabf8deef772eb6c19eb92 100644 (file)
@@ -150,7 +150,7 @@ void dst_dev_put(struct dst_entry *dst)
                dst->ops->ifdown(dst, dev);
        WRITE_ONCE(dst->input, dst_discard);
        WRITE_ONCE(dst->output, dst_discard_out);
-       WRITE_ONCE(dst->dev, blackhole_netdev);
+       rcu_assign_pointer(dst->dev_rcu, blackhole_netdev);
        netdev_ref_replace(dev, blackhole_netdev, &dst->dev_tracker,
                           GFP_ATOMIC);
 }
index e219bb423c3af7b193a3cd95d26eb4a472b7ef31..7579001d5b29897e48d8990d0ffad327cf71e045 100644 (file)
@@ -1030,7 +1030,7 @@ static void __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
                return;
 
        rcu_read_lock();
-       net = dev_net_rcu(dst_dev(dst));
+       net = dst_dev_net_rcu(dst);
        if (mtu < net->ipv4.ip_rt_min_pmtu) {
                lock = true;
                mtu = min(old_mtu, net->ipv4.ip_rt_min_pmtu);
@@ -1328,7 +1328,7 @@ static unsigned int ipv4_default_advmss(const struct dst_entry *dst)
        struct net *net;
 
        rcu_read_lock();
-       net = dev_net_rcu(dst_dev(dst));
+       net = dst_dev_net_rcu(dst);
        advmss = max_t(unsigned int, ipv4_mtu(dst) - header_size,
                                   net->ipv4.ip_rt_min_advmss);
        rcu_read_unlock();