FAILED: patch "[PATCH] ipv6: start using dst_dev_rcu()" failed to apply to 6.12-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 6.12-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.12.y
git checkout FETCH_HEAD
git cherry-pick -x b775ecf1655cedbc465fd6699ab18a2bc4e7a352
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2026091758-subsector-deity-17bd@gregkh' --subject-prefix 'PATCH 6.12.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From b775ecf1655cedbc465fd6699ab18a2bc4e7a352 Mon Sep 17 00:00:00 2001
From: Eric Dumazet <[email protected]>
Date: Thu, 28 Aug 2025 19:58:17 +0000
Subject: [PATCH] ipv6: start using dst_dev_rcu()
Refactor icmpv6_xrlim_allow() and ip6_dst_hoplimit() so that we acquire rcu_read_lock() a bit longer to be able to use dst_dev_rcu() instead of dst_dev().
__ip6_rt_update_pmtu() and rt6_do_redirect can directly use dst_dev_rcu() in sections already holding rcu_read_lock().
Small changes to use dst_dev_net_rcu() inip6_default_advmss(), ipv6_sock_ac_join(),ip6_mc_find_dev() and ndisc_send_skb().
net/ipv6/anycast.c +1 -1
@@ -104,7 +104,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)rcu_read_lock (); rt =rt6_lookup (net, addr,NULL ,0 ,NULL ,0 );if (rt) { - dev =dst_dev (&rt->dst); + dev =dst_dev_rcu (&rt->dst);netdev_hold (dev, &dev_tracker,GFP_ATOMIC );ip6_rt_put (rt); }else if (ishost) {
net/ipv6/icmp.c +3 -3
@@ -209,7 +209,8 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,* this lookup should be more aggressive (not longer than timeout). */ dst =ip6_route_output (net, sk, fl6); - dev =dst_dev (dst); +rcu_read_lock (); + dev =dst_dev_rcu (dst);if (dst->error) {IP6_INC_STATS (net,ip6_dst_idev (dst),IPSTATS_MIB_OUTNOROUTES );
@@ -224,11 +225,10 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,if (rt->rt6i_dst.plen <128 ) tmo >>= ((128 - rt->rt6i_dst.plen)>>5 ); -rcu_read_lock (); peer =inet_getpeer_v6 (net->ipv6.peers, &fl6->daddr); res =inet_peer_xrlim_allow (peer, tmo); -rcu_read_unlock (); } +rcu_read_unlock ();if (!res)__ICMP6_INC_STATS (net,ip6_dst_idev (dst),ICMP6_MIB_RATELIMITHOST );
net/ipv6/mcast.c +1 -1
@@ -180,7 +180,7 @@ static struct net_device *ip6_mc_find_dev(struct net *net,rcu_read_lock (); rt =rt6_lookup (net, group,NULL ,0 ,NULL ,0 );if (rt) { - dev =dst_dev (&rt->dst); + dev =dst_dev_rcu (&rt->dst);dev_hold (dev);ip6_rt_put (rt); }
net/ipv6/ndisc.c +1 -1
@@ -505,7 +505,7 @@ void ndisc_send_skb(struct sk_buff *skb, const struct in6_addr *daddr,ip6_nd_hdr (skb, saddr, daddr,READ_ONCE (inet6_sk (sk)->hop_limit), skb->len); - dev =dst_dev (dst); + dev =dst_dev_rcu (dst); idev =__in6_dev_get (dev);IP6_INC_STATS (net, idev,IPSTATS_MIB_OUTREQUESTS );
net/ipv6/output_core.c +5 -3
@@ -104,18 +104,20 @@ EXPORT_SYMBOL(ip6_find_1stfragopt);int ip6_dst_hoplimit (struct dst_entry *dst) {int hoplimit =dst_metric_raw (dst,RTAX_HOPLIMIT ); + +rcu_read_lock ();if (hoplimit ==0 ) { -struct net_device *dev =dst_dev (dst); +struct net_device *dev =dst_dev_rcu (dst);struct inet6_dev *idev; -rcu_read_lock (); idev =__in6_dev_get (dev);if (idev) hoplimit =READ_ONCE (idev->cnf.hop_limit);else hoplimit =READ_ONCE (dev_net (dev)->ipv6.devconf_all->hop_limit); -rcu_read_unlock (); } +rcu_read_unlock (); +return hoplimit; }EXPORT_SYMBOL (ip6_dst_hoplimit);
net/ipv6/route.c +3 -4
@@ -2943,7 +2943,7 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,if (res.f6i->nh) {struct fib6_nh_match_arg arg = { - .dev =dst_dev (dst), + .dev =dst_dev_rcu (dst), .gw = &rt6->rt6i_gateway, };
@@ -3238,7 +3238,6 @@ EXPORT_SYMBOL_GPL(ip6_sk_redirect);static unsigned int ip6_default_advmss (const struct dst_entry *dst) { -struct net_device *dev =dst_dev (dst);unsigned int mtu =dst_mtu (dst);struct net *net;
@@ -3246,7 +3245,7 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst)rcu_read_lock (); - net =dev_net_rcu (dev); + net =dst_dev_net_rcu (dst);if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss) mtu = net->ipv6.sysctl.ip6_rt_min_advmss;
@@ -4301,7 +4300,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buif (res.f6i->nh) {struct fib6_nh_match_arg arg = { - .dev =dst_dev (dst), + .dev =dst_dev_rcu (dst), .gw = &rt->rt6i_gateway, };
Sasha Levin
maintainerPATCH 1/2 ipv6: mcast: Don't hold RTNL for MCAST_ socket options.
From: Kuniyuki Iwashima <[email protected]>
[ Upstream commit e6e14d582dd2cbee362c48a1865f8d03ca0a5611 ]
In ip6_mc_source() and ip6_mc_msfilter(), per-socket mld data is protected by lock_sock() and inet6_dev->mc_lock is also held for some per-interface functions.
ip6_mc_find_dev_rtnl() only depends on RTNL. If we want to remove it, we need to check inet6_dev->dead under mc_lock to close the race with addrconf_ifdown(), as mentioned earlier.
Let's do that and drop RTNL for the rest of MCAST_ socket options.
Note that ip6_mc_msfilter() has unnecessary lock dances and they are integrated into one to avoid the last-minute error and simplify the error handling.
Backport adaptation for Linux 6.12:
Keep setsockopt_needs_rtnl() unchanged. The stable multicast join and drop paths still require RTNL, including source-group joins and the leave-group cases in ip6_mc_source() and ip6_mc_msfilter(). The stable addrconf_ifdown() also still publishes idev->dead outside mc_lock. Retaining RTNL avoids depending on the missing multicast lock-removal predecessors while keeping the referenced lookup and filter locking changes needed by the target.
Move the existing multicast lookup before __ipv6_sock_mc_join(), matching the location used by the target's parent. A plain patch check succeeds without this move, but a three-way cherry-pick otherwise sees the target as modifying a deleted helper and conflicts. Keep the helper's inet6_dev return type and existing callers; no additional helper is introduced.
Prepare the existing ipv6_sock_ac_join() lookup for target commit b775ecf1655cedbc465fd6699ab18a2bc4e7a352 as well: use dst_dev() under RCU, take a tracked device reference before releasing the route, and balance the references for the explicit-interface and fallback-device paths at the common exit. Keep its RTNL requirement and the existing device lookup APIs. This supplies the target's anycast context without adding functions or importing the unrelated anycast lock-removal series.
[ sashal: Reduced backport -- upstream e6e14d582dd2c touches 2 file(s), this
backport carries 2. Not backported here:
net/ipv6/ipv6_sockglue.c
This note is generated from the file lists only; see the resolution record for the reasoning. ]
Stable-dep-of: b775ecf1655c ("ipv6: start using dst_dev_rcu()")
--- net/ipv6/anycast.c | 25 ++++++++--- net/ipv6/mcast.c | 108 ++++++++++++++++++++++++++------------------- 2 files changed, 80 insertions(+), 53 deletions(-)
net/ipv6/anycast.c +18 -7
@@ -65,8 +65,9 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)struct ipv6_pinfo *np =inet6_sk (sk);struct net_device *dev =NULL ;struct inet6_dev *idev; -struct ipv6_ac_socklist *pac; +struct ipv6_ac_socklist *pac =NULL ;struct net *net =sock_net (sk); +netdevice_tracker dev_tracker;int ishost = !net->ipv6.devconf_all->forwarding;int err =0 ;
@@ -78,32 +79,41 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)return -EINVAL ;if (ifindex) - dev =__dev_get_by_index (net, ifindex); + dev =netdev_get_by_index (net, ifindex, &dev_tracker,GFP_KERNEL ); -if (ipv6_chk_addr_and_flags (net, addr, dev, true,0 ,IFA_F_TENTATIVE )) -return -EINVAL ; +if (ipv6_chk_addr_and_flags (net, addr, dev, true,0 ,IFA_F_TENTATIVE )) { + err = -EINVAL ; + goto error; + } pac =sock_kmalloc (sk,sizeof (struct ipv6_ac_socklist ),GFP_KERNEL ); -if (!pac) -return -ENOMEM ; +if (!pac) { + err = -ENOMEM ; + goto error; + } pac->acl_next =NULL ; pac->acl_addr = *addr;if (ifindex ==0 ) {struct rt6_info *rt; +rcu_read_lock (); rt =rt6_lookup (net, addr,NULL ,0 ,NULL ,0 );if (rt) { - dev = rt->dst.dev; + dev =dst_dev (&rt->dst); +netdev_hold (dev, &dev_tracker,GFP_ATOMIC );ip6_rt_put (rt); }else if (ishost) { +rcu_read_unlock (); err = -EADDRNOTAVAIL ; goto error; }else {/* router, no matching interface: just pick one */ dev =__dev_get_by_flags (net,IFF_UP ,IFF_UP |IFF_LOOPBACK ); +netdev_hold (dev, &dev_tracker,GFP_ATOMIC ); } +rcu_read_unlock (); }if (!dev) {
@@ -144,6 +154,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr) } error: +netdev_put (dev, &dev_tracker);if (pac)sock_kfree_s (sk, pac,sizeof (*pac));return err;
net/ipv6/mcast.c +62 -46
195 lines not on this page · raw message
Signature · 1 line
2.53.0
Sasha Levin
maintainerPATCH 2/2 ipv6: start using dst_dev_rcu()
From: Eric Dumazet <[email protected]>
[ Upstream commit b775ecf1655cedbc465fd6699ab18a2bc4e7a352 ]
Refactor icmpv6_xrlim_allow() and ip6_dst_hoplimit() so that we acquire rcu_read_lock() a bit longer to be able to use dst_dev_rcu() instead of dst_dev().
__ip6_rt_update_pmtu() and rt6_do_redirect can directly use dst_dev_rcu() in sections already holding rcu_read_lock().
Small changes to use dst_dev_net_rcu() inip6_default_advmss(), ipv6_sock_ac_join(),ip6_mc_find_dev() and ndisc_send_skb().
--- net/ipv6/anycast.c | 2 +- net/ipv6/icmp.c | 6 +++--- net/ipv6/mcast.c | 2 +- net/ipv6/ndisc.c | 2 +- net/ipv6/output_core.c | 8 +++++--- net/ipv6/route.c | 7 +++---- 6 files changed, 14 insertions(+), 13 deletions(-)
net/ipv6/anycast.c +1 -1
@@ -100,7 +100,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)rcu_read_lock (); rt =rt6_lookup (net, addr,NULL ,0 ,NULL ,0 );if (rt) { - dev =dst_dev (&rt->dst); + dev =dst_dev_rcu (&rt->dst);netdev_hold (dev, &dev_tracker,GFP_ATOMIC );ip6_rt_put (rt); }else if (ishost) {
net/ipv6/icmp.c +3 -3
@@ -209,7 +209,8 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,* this lookup should be more aggressive (not longer than timeout). */ dst =ip6_route_output (net, sk, fl6); - dev =dst_dev (dst); +rcu_read_lock (); + dev =dst_dev_rcu (dst);if (dst->error) {IP6_INC_STATS (net,ip6_dst_idev (dst),IPSTATS_MIB_OUTNOROUTES );
@@ -224,11 +225,10 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,if (rt->rt6i_dst.plen <128 ) tmo >>= ((128 - rt->rt6i_dst.plen)>>5 ); -rcu_read_lock (); peer =inet_getpeer_v6 (net->ipv6.peers, &fl6->daddr); res =inet_peer_xrlim_allow (peer, tmo); -rcu_read_unlock (); } +rcu_read_unlock ();if (!res)__ICMP6_INC_STATS (net,ip6_dst_idev (dst),ICMP6_MIB_RATELIMITHOST );
net/ipv6/mcast.c +1 -1
@@ -179,7 +179,7 @@ static struct inet6_dev *ip6_mc_find_dev(struct net *net,rcu_read_lock (); rt =rt6_lookup (net, group,NULL ,0 ,NULL ,0 );if (rt) { - dev =dst_dev (&rt->dst); + dev =dst_dev_rcu (&rt->dst);dev_hold (dev);ip6_rt_put (rt); }
net/ipv6/ndisc.c +1 -1
@@ -508,7 +508,7 @@ void ndisc_send_skb(struct sk_buff *skb, const struct in6_addr *daddr,ip6_nd_hdr (skb, saddr, daddr,READ_ONCE (inet6_sk (sk)->hop_limit), skb->len); - dev =dst_dev (dst); + dev =dst_dev_rcu (dst); idev =__in6_dev_get (dev);IP6_INC_STATS (net, idev,IPSTATS_MIB_OUTREQUESTS );
net/ipv6/output_core.c +5 -3
@@ -104,18 +104,20 @@ EXPORT_SYMBOL(ip6_find_1stfragopt);int ip6_dst_hoplimit (struct dst_entry *dst) {int hoplimit =dst_metric_raw (dst,RTAX_HOPLIMIT ); + +rcu_read_lock ();if (hoplimit ==0 ) { -struct net_device *dev =dst_dev (dst); +struct net_device *dev =dst_dev_rcu (dst);struct inet6_dev *idev; -rcu_read_lock (); idev =__in6_dev_get (dev);if (idev) hoplimit =READ_ONCE (idev->cnf.hop_limit);else hoplimit =READ_ONCE (dev_net (dev)->ipv6.devconf_all->hop_limit); -rcu_read_unlock (); } +rcu_read_unlock (); +return hoplimit; }EXPORT_SYMBOL (ip6_dst_hoplimit);
net/ipv6/route.c +3 -4
@@ -2949,7 +2949,7 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,if (res.f6i->nh) {struct fib6_nh_match_arg arg = { - .dev =dst_dev (dst), + .dev =dst_dev_rcu (dst), .gw = &rt6->rt6i_gateway, };
@@ -3244,7 +3244,6 @@ EXPORT_SYMBOL_GPL(ip6_sk_redirect);static unsigned int ip6_default_advmss (const struct dst_entry *dst) { -struct net_device *dev =dst_dev (dst);unsigned int mtu =dst_mtu (dst);struct net *net;
@@ -3252,7 +3251,7 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst)rcu_read_lock (); - net =dev_net_rcu (dev); + net =dst_dev_net_rcu (dst);if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss) mtu = net->ipv6.sysctl.ip6_rt_min_advmss;
@@ -4266,7 +4265,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buif (res.f6i->nh) {struct fib6_nh_match_arg arg = { - .dev =dst_dev (dst), + .dev =dst_dev_rcu (dst), .gw = &rt->rt6i_gateway, };
Signature · 1 line
2.53.0
Re: [PATCH 6.12.y 2/2] ipv6: start using dst_dev_rcu()
Quoted 167 lines · Sasha Levin
From: Eric Dumazet <[email protected]>
[ Upstream commit
b775ecf1655cedbc465fd6699ab18a2bc4e7a352]Refactor
icmpv6_xrlim_allow()andip6_dst_hoplimit()so that we acquirercu_read_lock()a bit longer to be able to usedst_dev_rcu()instead ofdst_dev().
__ip6_rt_update_pmtu()andrt6_do_redirectcan directly usedst_dev_rcu()in sections already holdingrcu_read_lock().Small changes to use
dst_dev_net_rcu()inip6_default_advmss(),ipv6_sock_ac_join(),ip6_mc_find_dev()andndisc_send_skb().Fixes 4a6ce2b6f2ec ("net: introduce a new function dst_dev_put()")Signed-off-by Eric Dumazet <[email protected]>Reviewed-by David Ahern <[email protected]>Signed-off-by Jakub Kicinski <[email protected]>Signed-off-by Sasha Levin <[email protected]>--- net/ipv6/anycast.c | 2 +- net/ipv6/icmp.c | 6 +++--- net/ipv6/mcast.c | 2 +- net/ipv6/ndisc.c | 2 +- net/ipv6/output_core.c | 8 +++++--- net/ipv6/route.c | 7 +++---- 6 files changed, 14 insertions(+), 13 deletions(-)net/ipv6/anycast.c +1
-1@@ -100,7 +100,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr)rcu_read_lock (); rt =rt6_lookup (net, addr,NULL ,0 ,NULL ,0 );if (rt) { - dev =dst_dev (&rt->dst); + dev =dst_dev_rcu (&rt->dst);netdev_hold (dev, &dev_tracker,GFP_ATOMIC );ip6_rt_put (rt); }else if (ishost) {net/ipv6/icmp.c +3
-3@@ -209,7 +209,8 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,* this lookup should be more aggressive (not longer than timeout). */ dst =ip6_route_output (net, sk, fl6); - dev =dst_dev (dst); +rcu_read_lock (); + dev =dst_dev_rcu (dst);if (dst->error) {IP6_INC_STATS (net,ip6_dst_idev (dst),IPSTATS_MIB_OUTNOROUTES );@@ -224,11 +225,10 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,if (rt->rt6i_dst.plen <128 ) tmo >>= ((128 - rt->rt6i_dst.plen)>>5 ); -rcu_read_lock (); peer =inet_getpeer_v6 (net->ipv6.peers, &fl6->daddr); res =inet_peer_xrlim_allow (peer, tmo); -rcu_read_unlock (); } +rcu_read_unlock ();if (!res)__ICMP6_INC_STATS (net,ip6_dst_idev (dst),ICMP6_MIB_RATELIMITHOST );net/ipv6/mcast.c +1
-1@@ -179,7 +179,7 @@ static struct inet6_dev *ip6_mc_find_dev(struct net *net,rcu_read_lock (); rt =rt6_lookup (net, group,NULL ,0 ,NULL ,0 );if (rt) { - dev =dst_dev (&rt->dst); + dev =dst_dev_rcu (&rt->dst);dev_hold (dev);ip6_rt_put (rt); }net/ipv6/ndisc.c +1
-1@@ -508,7 +508,7 @@ void ndisc_send_skb(struct sk_buff *skb, const struct in6_addr *daddr,ip6_nd_hdr (skb, saddr, daddr,READ_ONCE (inet6_sk (sk)->hop_limit), skb->len); - dev =dst_dev (dst); + dev =dst_dev_rcu (dst); idev =__in6_dev_get (dev);IP6_INC_STATS (net, idev,IPSTATS_MIB_OUTREQUESTS );net/ipv6/output_core.c +5
-3@@ -104,18 +104,20 @@ EXPORT_SYMBOL(ip6_find_1stfragopt);int ip6_dst_hoplimit (struct dst_entry *dst) {int hoplimit =dst_metric_raw (dst,RTAX_HOPLIMIT ); + +rcu_read_lock ();if (hoplimit ==0 ) { -struct net_device *dev =dst_dev (dst); +struct net_device *dev =dst_dev_rcu (dst);struct inet6_dev *idev; -rcu_read_lock (); idev =__in6_dev_get (dev);if (idev) hoplimit =READ_ONCE (idev->cnf.hop_limit);else hoplimit =READ_ONCE (dev_net (dev)->ipv6.devconf_all->hop_limit); -rcu_read_unlock (); } +rcu_read_unlock (); +return hoplimit; }EXPORT_SYMBOL (ip6_dst_hoplimit);net/ipv6/route.c +3
-4@@ -2949,7 +2949,7 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,if (res.f6i->nh) {struct fib6_nh_match_arg arg = { - .dev =dst_dev (dst), + .dev =dst_dev_rcu (dst), .gw = &rt6->rt6i_gateway, };@@ -3244,7 +3244,6 @@ EXPORT_SYMBOL_GPL(ip6_sk_redirect);static unsigned int ip6_default_advmss (const struct dst_entry *dst) { -struct net_device *dev =dst_dev (dst);unsigned int mtu =dst_mtu (dst);struct net *net;@@ -3252,7 +3251,7 @@ static unsigned int ip6_default_advmss(const struct dst_entry *dst)rcu_read_lock (); - net =dev_net_rcu (dev); + net =dst_dev_net_rcu (dst);if (mtu < net->ipv6.sysctl.ip6_rt_min_advmss) mtu = net->ipv6.sysctl.ip6_rt_min_advmss;@@ -4266,7 +4265,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_buif (res.f6i->nh) {struct fib6_nh_match_arg arg = { - .dev =dst_dev (dst), + .dev =dst_dev_rcu (dst), .gw = &rt->rt6i_gateway, };Signature · 1 line
2.53.0
did not apply