From: Florian Westphal Date: Wed, 9 Aug 2017 18:41:50 +0000 (+0200) Subject: rtnetlink: small rtnl lock pushdown X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=0cc09020aefe832db23d63cd3a6c889ab7645eec;p=openwrt%2Fstaging%2Fblogic.git 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 --- 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)