diff options
| author | Florian Westphal <fw@strlen.de> | 2017-08-09 14:41:50 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2017-08-09 19:57:38 -0400 |
| commit | 0cc09020aefe832db23d63cd3a6c889ab7645eec (patch) | |
| tree | 5458da1272db981d04048d558e64baa5bdcdabbf /net | |
| parent | 019a316992ee0d9832b1c480c899d6bdf2a0a77e (diff) | |
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 <fw@strlen.de>
Reviewed-by: Hannes Frederic Sowa <hannes@stressinduktion.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net')
| -rw-r--r-- | net/core/rtnetlink.c | 19 |
1 files 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, | |||
| 4178 | rtnl_dumpit_func dumpit; | 4178 | rtnl_dumpit_func dumpit; |
| 4179 | u16 min_dump_alloc = 0; | 4179 | u16 min_dump_alloc = 0; |
| 4180 | 4180 | ||
| 4181 | rtnl_lock(); | ||
| 4182 | |||
| 4181 | dumpit = rtnl_get_dumpit(family, type); | 4183 | dumpit = rtnl_get_dumpit(family, type); |
| 4182 | if (dumpit == NULL) | 4184 | if (dumpit == NULL) |
| 4183 | return -EOPNOTSUPP; | 4185 | goto err_unlock; |
| 4184 | 4186 | ||
| 4185 | refcount_inc(&rtnl_msg_handlers_ref[family]); | 4187 | refcount_inc(&rtnl_msg_handlers_ref[family]); |
| 4186 | 4188 | ||
| @@ -4196,23 +4198,28 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
| 4196 | }; | 4198 | }; |
| 4197 | err = netlink_dump_start(rtnl, skb, nlh, &c); | 4199 | err = netlink_dump_start(rtnl, skb, nlh, &c); |
| 4198 | } | 4200 | } |
| 4199 | rtnl_lock(); | ||
| 4200 | refcount_dec(&rtnl_msg_handlers_ref[family]); | 4201 | refcount_dec(&rtnl_msg_handlers_ref[family]); |
| 4201 | return err; | 4202 | return err; |
| 4202 | } | 4203 | } |
| 4203 | 4204 | ||
| 4205 | rtnl_lock(); | ||
| 4204 | doit = rtnl_get_doit(family, type); | 4206 | doit = rtnl_get_doit(family, type); |
| 4205 | if (doit == NULL) | 4207 | if (doit == NULL) |
| 4206 | return -EOPNOTSUPP; | 4208 | goto err_unlock; |
| 4207 | 4209 | ||
| 4208 | return doit(skb, nlh, extack); | 4210 | err = doit(skb, nlh, extack); |
| 4211 | rtnl_unlock(); | ||
| 4212 | |||
| 4213 | return err; | ||
| 4214 | |||
| 4215 | err_unlock: | ||
| 4216 | rtnl_unlock(); | ||
| 4217 | return -EOPNOTSUPP; | ||
| 4209 | } | 4218 | } |
| 4210 | 4219 | ||
| 4211 | static void rtnetlink_rcv(struct sk_buff *skb) | 4220 | static void rtnetlink_rcv(struct sk_buff *skb) |
| 4212 | { | 4221 | { |
| 4213 | rtnl_lock(); | ||
| 4214 | netlink_rcv_skb(skb, &rtnetlink_rcv_msg); | 4222 | netlink_rcv_skb(skb, &rtnetlink_rcv_msg); |
| 4215 | rtnl_unlock(); | ||
| 4216 | } | 4223 | } |
| 4217 | 4224 | ||
| 4218 | static int rtnetlink_bind(struct net *net, int group) | 4225 | static int rtnetlink_bind(struct net *net, int group) |
