From 0cc09020aefe832db23d63cd3a6c889ab7645eec Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Wed, 9 Aug 2017 20:41:50 +0200 Subject: [PATCH] rtnetlink: small rtnl lock pushdown instead of rtnl lock/unload at the top level, push it down to the called function. This is just an intermediate step, next commit switches protection of the rtnl_link ops table to rcu, in which case (for dumps) the rtnl lock is acquired only by the netlink dumper infrastructure (current lock/unlock/dump/lock/unlock rtnl sequence becomes rcu lock/rcu unlock/dump). Signed-off-by: Florian Westphal Reviewed-by: Hannes Frederic Sowa Signed-off-by: David S. Miller --- net/core/rtnetlink.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index c45a7c5e3232..be01d8e48661 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -4178,9 +4178,11 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, rtnl_dumpit_func dumpit; u16 min_dump_alloc = 0; + rtnl_lock(); + dumpit = rtnl_get_dumpit(family, type); if (dumpit == NULL) - return -EOPNOTSUPP; + goto err_unlock; refcount_inc(&rtnl_msg_handlers_ref[family]); @@ -4196,23 +4198,28 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, }; err = netlink_dump_start(rtnl, skb, nlh, &c); } - rtnl_lock(); refcount_dec(&rtnl_msg_handlers_ref[family]); return err; } + rtnl_lock(); doit = rtnl_get_doit(family, type); if (doit == NULL) - return -EOPNOTSUPP; + goto err_unlock; - return doit(skb, nlh, extack); + err = doit(skb, nlh, extack); + rtnl_unlock(); + + return err; + +err_unlock: + rtnl_unlock(); + return -EOPNOTSUPP; } static void rtnetlink_rcv(struct sk_buff *skb) { - rtnl_lock(); netlink_rcv_skb(skb, &rtnetlink_rcv_msg); - rtnl_unlock(); } static int rtnetlink_bind(struct net *net, int group) -- 2.20.1