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

Configure Feed

Select the types of activity you want to include in your feed.

ipv6: Move nexthop_find_by_id() after fib6_info_alloc().

We will get rid of RTNL from RTM_NEWROUTE and SIOCADDRT.

Then, we must perform two lookups for nexthop and dev under RCU
to guarantee their lifetime.

ip6_route_info_create() calls nexthop_find_by_id() first if
RTA_NH_ID is specified, and then allocates struct fib6_info.

nexthop_find_by_id() must be called under RCU, but we do not want
to use GFP_ATOMIC for memory allocation here, which will be likely
to fail in ip6_route_multipath_add().

Let's move nexthop_find_by_id() after the memory allocation so
that we can later split ip6_route_info_create() into two parts:
the sleepable part and the RCU part.

Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com>
Acked-by: Paolo Abeni <pabeni@redhat.com>
Link: https://patch.msgid.link/20250418000443.43734-6-kuniyu@amazon.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

authored by

Kuniyuki Iwashima and committed by
Paolo Abeni
c9cabe05 e6f49795

+18 -16
+18 -16
net/ipv6/route.c
··· 3734 3734 { 3735 3735 struct net *net = cfg->fc_nlinfo.nl_net; 3736 3736 struct fib6_info *rt = NULL; 3737 - struct nexthop *nh = NULL; 3738 3737 struct fib6_table *table; 3739 3738 struct fib6_nh *fib6_nh; 3740 - int err = -EINVAL; 3739 + int err = -ENOBUFS; 3741 3740 int addr_type; 3742 3741 3743 - if (cfg->fc_nh_id) { 3744 - nh = nexthop_find_by_id(net, cfg->fc_nh_id); 3745 - if (!nh) { 3746 - NL_SET_ERR_MSG(extack, "Nexthop id does not exist"); 3747 - goto out; 3748 - } 3749 - err = fib6_check_nexthop(nh, cfg, extack); 3750 - if (err) 3751 - goto out; 3752 - } 3753 - 3754 - err = -ENOBUFS; 3755 3742 if (cfg->fc_nlinfo.nlh && 3756 3743 !(cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_CREATE)) { 3757 3744 table = fib6_get_table(net, cfg->fc_table); ··· 3754 3767 goto out; 3755 3768 3756 3769 err = -ENOMEM; 3757 - rt = fib6_info_alloc(gfp_flags, !nh); 3770 + rt = fib6_info_alloc(gfp_flags, !cfg->fc_nh_id); 3758 3771 if (!rt) 3759 3772 goto out; 3760 3773 ··· 3790 3803 ipv6_addr_prefix(&rt->fib6_src.addr, &cfg->fc_src, cfg->fc_src_len); 3791 3804 rt->fib6_src.plen = cfg->fc_src_len; 3792 3805 #endif 3793 - if (nh) { 3806 + 3807 + if (cfg->fc_nh_id) { 3808 + struct nexthop *nh; 3809 + 3810 + nh = nexthop_find_by_id(net, cfg->fc_nh_id); 3811 + if (!nh) { 3812 + err = -EINVAL; 3813 + NL_SET_ERR_MSG(extack, "Nexthop id does not exist"); 3814 + goto out_free; 3815 + } 3816 + 3817 + err = fib6_check_nexthop(nh, cfg, extack); 3818 + if (err) 3819 + goto out_free; 3820 + 3794 3821 if (!nexthop_get(nh)) { 3795 3822 NL_SET_ERR_MSG(extack, "Nexthop has been deleted"); 3796 3823 err = -ENOENT; 3797 3824 goto out_free; 3798 3825 } 3826 + 3799 3827 rt->nh = nh; 3800 3828 fib6_nh = nexthop_fib6_nh(rt->nh); 3801 3829 } else {