Message ID | 20241106022432.13065-7-kuniyu@amazon.com (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | Netdev Maintainers |
Headers | show |
Series | rtnetlink: Convert rtnl_newlink() to per-netns RTNL. | expand |
On 11/6/24 03:24, Kuniyuki Iwashima wrote: > @@ -7001,7 +7021,8 @@ static struct pernet_operations rtnetlink_net_ops = { > }; > > static const struct rtnl_msg_handler rtnetlink_rtnl_msg_handlers[] __initconst = { > - {.msgtype = RTM_NEWLINK, .doit = rtnl_newlink}, > + {.msgtype = RTM_NEWLINK, .doit = rtnl_newlink, > + .flags = RTNL_FLAG_DOIT_PERNET}, > {.msgtype = RTM_DELLINK, .doit = rtnl_dellink}, > {.msgtype = RTM_GETLINK, .doit = rtnl_getlink, > .dumpit = rtnl_dump_ifinfo, .flags = RTNL_FLAG_DUMP_SPLIT_NLM_DONE}, It looks like this still causes look problems - srcu/rtnl acquired in both orders: https://netdev-3.bots.linux.dev/vmksft-net-dbg/results/847881/12-rtnetlink-sh/stderr It looks like __rtnl_link_unregister() should release the rtnl lock around synchronize_srcu(). I'm unsure if would cause other problems, too. Please have a self-tests run with lockdep enabled before the next iteration: https://github.com/linux-netdev/nipa/wiki/How-to-run-netdev-selftests-CI-style The whole test suite could be quite cumbersome, but the rtnetlink.sh test should give a good coverage. Thanks. Paolo p.s. kudos to Jakub for the extra miles to create and maintain the CI infra: it's really catching up non trivial things.
On Tue, Nov 05, 2024 at 06:24:31PM -0800, Kuniyuki Iwashima wrote: > Now, we are ready to convert rtnl_newlink() to per-netns RTNL; > rtnl_link_ops is protected by SRCU and netns is prefetched in > rtnl_newlink(). > > Let's register rtnl_newlink() with RTNL_FLAG_DOIT_PERNET and > push RTNL down as rtnl_nets_lock(). > > Signed-off-by: Kuniyuki Iwashima <kuniyu@amazon.com> > Reviewed-by: Eric Dumazet <edumazet@google.com> > --- > v2: Remove __rtnl_unlock() dance in rtnl_newlink(). > --- > net/core/rtnetlink.c | 27 ++++++++++++++++++++++++--- > 1 file changed, 24 insertions(+), 3 deletions(-) > Reviewed-by: Nikolay Aleksandrov <razor@blackwall.org>
From: Paolo Abeni <pabeni@redhat.com> Date: Wed, 6 Nov 2024 10:00:26 +0100 > On 11/6/24 03:24, Kuniyuki Iwashima wrote: > > @@ -7001,7 +7021,8 @@ static struct pernet_operations rtnetlink_net_ops = { > > }; > > > > static const struct rtnl_msg_handler rtnetlink_rtnl_msg_handlers[] __initconst = { > > - {.msgtype = RTM_NEWLINK, .doit = rtnl_newlink}, > > + {.msgtype = RTM_NEWLINK, .doit = rtnl_newlink, > > + .flags = RTNL_FLAG_DOIT_PERNET}, > > {.msgtype = RTM_DELLINK, .doit = rtnl_dellink}, > > {.msgtype = RTM_GETLINK, .doit = rtnl_getlink, > > .dumpit = rtnl_dump_ifinfo, .flags = RTNL_FLAG_DUMP_SPLIT_NLM_DONE}, > > It looks like this still causes look problems - srcu/rtnl acquired in > both orders: > > https://netdev-3.bots.linux.dev/vmksft-net-dbg/results/847881/12-rtnetlink-sh/stderr > > It looks like __rtnl_link_unregister() should release the rtnl lock > around synchronize_srcu(). I'm unsure if would cause other problems, too. It seems I need to unexport __rtnl_link_unregister(), add mutex for rtnl_link_ops, and move ops deletion before down_write(&pernet_ops_rwsem) in rtnl_link_unregister(). It would be better than releasing RTNL after rtnl_lock_unregistering_all(). > > Please have a self-tests run with lockdep enabled before the next iteration: > > https://github.com/linux-netdev/nipa/wiki/How-to-run-netdev-selftests-CI-style > > The whole test suite could be quite cumbersome, but the rtnetlink.sh > test should give a good coverage. Sure, sorry for the churn for other patches.. I noticed rmmod wasn't tested on my QEMU because I enabled drivers as =y so that I need not copy .ko. I'll run test with netdevsim as =m at least. > > Thanks. > > Paolo > > p.s. kudos to Jakub for the extra miles to create and maintain the CI > infra: it's really catching up non trivial things. +100 Thank you!
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index d5557a621099..1b58a7c4c912 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -319,6 +319,26 @@ static void rtnl_nets_add(struct rtnl_nets *rtnl_nets, struct net *net) rtnl_nets->len++; } +static void rtnl_nets_lock(struct rtnl_nets *rtnl_nets) +{ + int i; + + rtnl_lock(); + + for (i = 0; i < rtnl_nets->len; i++) + __rtnl_net_lock(rtnl_nets->net[i]); +} + +static void rtnl_nets_unlock(struct rtnl_nets *rtnl_nets) +{ + int i; + + for (i = 0; i < rtnl_nets->len; i++) + __rtnl_net_unlock(rtnl_nets->net[i]); + + rtnl_unlock(); +} + static struct rtnl_link __rcu *__rcu *rtnl_msg_handlers[RTNL_FAMILY_MAX + 1]; static inline int rtm_msgindex(int msgtype) @@ -3932,9 +3952,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, ops = rtnl_link_ops_get(kind, &ops_srcu_index); #ifdef CONFIG_MODULES if (!ops) { - __rtnl_unlock(); request_module("rtnl-link-%s", kind); - rtnl_lock(); ops = rtnl_link_ops_get(kind, &ops_srcu_index); } #endif @@ -3997,7 +4015,9 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh, } } + rtnl_nets_lock(&rtnl_nets); ret = __rtnl_newlink(skb, nlh, ops, tgt_net, link_net, tbs, data, extack); + rtnl_nets_unlock(&rtnl_nets); put_net: rtnl_nets_destroy(&rtnl_nets); @@ -7001,7 +7021,8 @@ static struct pernet_operations rtnetlink_net_ops = { }; static const struct rtnl_msg_handler rtnetlink_rtnl_msg_handlers[] __initconst = { - {.msgtype = RTM_NEWLINK, .doit = rtnl_newlink}, + {.msgtype = RTM_NEWLINK, .doit = rtnl_newlink, + .flags = RTNL_FLAG_DOIT_PERNET}, {.msgtype = RTM_DELLINK, .doit = rtnl_dellink}, {.msgtype = RTM_GETLINK, .doit = rtnl_getlink, .dumpit = rtnl_dump_ifinfo, .flags = RTNL_FLAG_DUMP_SPLIT_NLM_DONE},