rtnetlink: change nlk->cb_mutex role
[ Upstream commit e39951d965bf58b5aba7f61dc1140dcb8271af22 ]
In commit af65bdfce9
("[NETLINK]: Switch cb_lock spinlock
to mutex and allow to override it"), Patrick McHardy used
a common mutex to protect both nlk->cb and the dump() operations.
The override is used for rtnl dumps, registered with
rntl_register() and rntl_register_module().
We want to be able to opt-out some dump() operations
to not acquire RTNL, so we need to protect nlk->cb
with a per socket mutex.
This patch renames nlk->cb_def_mutex to nlk->nl_cb_mutex
The optional pointer to the mutex used to protect dump()
call is stored in nlk->dump_cb_mutex
Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Stable-dep-of: 5be2062e3080 ("mpls: Handle error of rtnl_register_module().")
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
f4df31a051
commit
c8c76f1550
|
@ -636,7 +636,7 @@ static struct proto netlink_proto = {
|
|||
};
|
||||
|
||||
static int __netlink_create(struct net *net, struct socket *sock,
|
||||
struct mutex *cb_mutex, int protocol,
|
||||
struct mutex *dump_cb_mutex, int protocol,
|
||||
int kern)
|
||||
{
|
||||
struct sock *sk;
|
||||
|
@ -651,15 +651,11 @@ static int __netlink_create(struct net *net, struct socket *sock,
|
|||
sock_init_data(sock, sk);
|
||||
|
||||
nlk = nlk_sk(sk);
|
||||
if (cb_mutex) {
|
||||
nlk->cb_mutex = cb_mutex;
|
||||
} else {
|
||||
nlk->cb_mutex = &nlk->cb_def_mutex;
|
||||
mutex_init(nlk->cb_mutex);
|
||||
lockdep_set_class_and_name(nlk->cb_mutex,
|
||||
mutex_init(&nlk->nl_cb_mutex);
|
||||
lockdep_set_class_and_name(&nlk->nl_cb_mutex,
|
||||
nlk_cb_mutex_keys + protocol,
|
||||
nlk_cb_mutex_key_strings[protocol]);
|
||||
}
|
||||
nlk->dump_cb_mutex = dump_cb_mutex;
|
||||
init_waitqueue_head(&nlk->wait);
|
||||
|
||||
sk->sk_destruct = netlink_sock_destruct;
|
||||
|
@ -2211,7 +2207,7 @@ static int netlink_dump(struct sock *sk, bool lock_taken)
|
|||
int alloc_size;
|
||||
|
||||
if (!lock_taken)
|
||||
mutex_lock(nlk->cb_mutex);
|
||||
mutex_lock(&nlk->nl_cb_mutex);
|
||||
if (!nlk->cb_running) {
|
||||
err = -EINVAL;
|
||||
goto errout_skb;
|
||||
|
@ -2263,14 +2259,22 @@ static int netlink_dump(struct sock *sk, bool lock_taken)
|
|||
netlink_skb_set_owner_r(skb, sk);
|
||||
|
||||
if (nlk->dump_done_errno > 0) {
|
||||
struct mutex *extra_mutex = nlk->dump_cb_mutex;
|
||||
|
||||
cb->extack = &extack;
|
||||
|
||||
if (extra_mutex)
|
||||
mutex_lock(extra_mutex);
|
||||
nlk->dump_done_errno = cb->dump(skb, cb);
|
||||
if (extra_mutex)
|
||||
mutex_unlock(extra_mutex);
|
||||
|
||||
cb->extack = NULL;
|
||||
}
|
||||
|
||||
if (nlk->dump_done_errno > 0 ||
|
||||
skb_tailroom(skb) < nlmsg_total_size(sizeof(nlk->dump_done_errno))) {
|
||||
mutex_unlock(nlk->cb_mutex);
|
||||
mutex_unlock(&nlk->nl_cb_mutex);
|
||||
|
||||
if (sk_filter(sk, skb))
|
||||
kfree_skb(skb);
|
||||
|
@ -2304,13 +2308,13 @@ static int netlink_dump(struct sock *sk, bool lock_taken)
|
|||
WRITE_ONCE(nlk->cb_running, false);
|
||||
module = cb->module;
|
||||
skb = cb->skb;
|
||||
mutex_unlock(nlk->cb_mutex);
|
||||
mutex_unlock(&nlk->nl_cb_mutex);
|
||||
module_put(module);
|
||||
consume_skb(skb);
|
||||
return 0;
|
||||
|
||||
errout_skb:
|
||||
mutex_unlock(nlk->cb_mutex);
|
||||
mutex_unlock(&nlk->nl_cb_mutex);
|
||||
kfree_skb(skb);
|
||||
return err;
|
||||
}
|
||||
|
@ -2333,7 +2337,7 @@ int __netlink_dump_start(struct sock *ssk, struct sk_buff *skb,
|
|||
}
|
||||
|
||||
nlk = nlk_sk(sk);
|
||||
mutex_lock(nlk->cb_mutex);
|
||||
mutex_lock(&nlk->nl_cb_mutex);
|
||||
/* A dump is in progress... */
|
||||
if (nlk->cb_running) {
|
||||
ret = -EBUSY;
|
||||
|
@ -2384,7 +2388,7 @@ error_put:
|
|||
module_put(control->module);
|
||||
error_unlock:
|
||||
sock_put(sk);
|
||||
mutex_unlock(nlk->cb_mutex);
|
||||
mutex_unlock(&nlk->nl_cb_mutex);
|
||||
error_free:
|
||||
kfree_skb(skb);
|
||||
return ret;
|
||||
|
|
|
@ -39,8 +39,9 @@ struct netlink_sock {
|
|||
bool cb_running;
|
||||
int dump_done_errno;
|
||||
struct netlink_callback cb;
|
||||
struct mutex *cb_mutex;
|
||||
struct mutex cb_def_mutex;
|
||||
struct mutex nl_cb_mutex;
|
||||
|
||||
struct mutex *dump_cb_mutex;
|
||||
void (*netlink_rcv)(struct sk_buff *skb);
|
||||
int (*netlink_bind)(struct net *net, int group);
|
||||
void (*netlink_unbind)(struct net *net, int group);
|
||||
|
|
Loading…
Reference in New Issue