mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-07 22:08:33 -04:00
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>
This commit is contained in:
committed by
Paolo Abeni
parent
e6f497955f
commit
c9cabe05e4
@@ -3734,24 +3734,11 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
|
||||
{
|
||||
struct net *net = cfg->fc_nlinfo.nl_net;
|
||||
struct fib6_info *rt = NULL;
|
||||
struct nexthop *nh = NULL;
|
||||
struct fib6_table *table;
|
||||
struct fib6_nh *fib6_nh;
|
||||
int err = -EINVAL;
|
||||
int err = -ENOBUFS;
|
||||
int addr_type;
|
||||
|
||||
if (cfg->fc_nh_id) {
|
||||
nh = nexthop_find_by_id(net, cfg->fc_nh_id);
|
||||
if (!nh) {
|
||||
NL_SET_ERR_MSG(extack, "Nexthop id does not exist");
|
||||
goto out;
|
||||
}
|
||||
err = fib6_check_nexthop(nh, cfg, extack);
|
||||
if (err)
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = -ENOBUFS;
|
||||
if (cfg->fc_nlinfo.nlh &&
|
||||
!(cfg->fc_nlinfo.nlh->nlmsg_flags & NLM_F_CREATE)) {
|
||||
table = fib6_get_table(net, cfg->fc_table);
|
||||
@@ -3767,7 +3754,7 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
|
||||
goto out;
|
||||
|
||||
err = -ENOMEM;
|
||||
rt = fib6_info_alloc(gfp_flags, !nh);
|
||||
rt = fib6_info_alloc(gfp_flags, !cfg->fc_nh_id);
|
||||
if (!rt)
|
||||
goto out;
|
||||
|
||||
@@ -3803,12 +3790,27 @@ static struct fib6_info *ip6_route_info_create(struct fib6_config *cfg,
|
||||
ipv6_addr_prefix(&rt->fib6_src.addr, &cfg->fc_src, cfg->fc_src_len);
|
||||
rt->fib6_src.plen = cfg->fc_src_len;
|
||||
#endif
|
||||
if (nh) {
|
||||
|
||||
if (cfg->fc_nh_id) {
|
||||
struct nexthop *nh;
|
||||
|
||||
nh = nexthop_find_by_id(net, cfg->fc_nh_id);
|
||||
if (!nh) {
|
||||
err = -EINVAL;
|
||||
NL_SET_ERR_MSG(extack, "Nexthop id does not exist");
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
err = fib6_check_nexthop(nh, cfg, extack);
|
||||
if (err)
|
||||
goto out_free;
|
||||
|
||||
if (!nexthop_get(nh)) {
|
||||
NL_SET_ERR_MSG(extack, "Nexthop has been deleted");
|
||||
err = -ENOENT;
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
rt->nh = nh;
|
||||
fib6_nh = nexthop_fib6_nh(rt->nh);
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user