Commit 395059c5 authored by David S. Miller's avatar David S. Miller

Merge branch 'rtnetlink-rtnl_lock'

Jakub Kicinski says:

====================
rtnetlink: move rtnl_lock handling out of af_netlink

With the changes done in commit 5b4b62a1 ("rtnetlink: make
the "split" NLM_DONE handling generic") we can also move the
rtnl locking out of af_netlink.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents c917b26e 5fbf57a9
...@@ -47,7 +47,6 @@ struct netlink_kernel_cfg { ...@@ -47,7 +47,6 @@ struct netlink_kernel_cfg {
unsigned int groups; unsigned int groups;
unsigned int flags; unsigned int flags;
void (*input)(struct sk_buff *skb); void (*input)(struct sk_buff *skb);
struct mutex *cb_mutex;
int (*bind)(struct net *net, int group); int (*bind)(struct net *net, int group);
void (*unbind)(struct net *net, int group); void (*unbind)(struct net *net, int group);
void (*release) (struct sock *sk, unsigned long *groups); void (*release) (struct sock *sk, unsigned long *groups);
......
...@@ -6486,6 +6486,7 @@ static int rtnl_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh, ...@@ -6486,6 +6486,7 @@ static int rtnl_mdb_del(struct sk_buff *skb, struct nlmsghdr *nlh,
static int rtnl_dumpit(struct sk_buff *skb, struct netlink_callback *cb) static int rtnl_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
{ {
const bool needs_lock = !(cb->flags & RTNL_FLAG_DUMP_UNLOCKED);
rtnl_dumpit_func dumpit = cb->data; rtnl_dumpit_func dumpit = cb->data;
int err; int err;
...@@ -6495,7 +6496,11 @@ static int rtnl_dumpit(struct sk_buff *skb, struct netlink_callback *cb) ...@@ -6495,7 +6496,11 @@ static int rtnl_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
if (!dumpit) if (!dumpit)
return 0; return 0;
if (needs_lock)
rtnl_lock();
err = dumpit(skb, cb); err = dumpit(skb, cb);
if (needs_lock)
rtnl_unlock();
/* Old dump handlers used to send NLM_DONE as in a separate recvmsg(). /* Old dump handlers used to send NLM_DONE as in a separate recvmsg().
* Some applications which parse netlink manually depend on this. * Some applications which parse netlink manually depend on this.
...@@ -6515,7 +6520,8 @@ static int rtnetlink_dump_start(struct sock *ssk, struct sk_buff *skb, ...@@ -6515,7 +6520,8 @@ static int rtnetlink_dump_start(struct sock *ssk, struct sk_buff *skb,
const struct nlmsghdr *nlh, const struct nlmsghdr *nlh,
struct netlink_dump_control *control) struct netlink_dump_control *control)
{ {
if (control->flags & RTNL_FLAG_DUMP_SPLIT_NLM_DONE) { if (control->flags & RTNL_FLAG_DUMP_SPLIT_NLM_DONE ||
!(control->flags & RTNL_FLAG_DUMP_UNLOCKED)) {
WARN_ON(control->data); WARN_ON(control->data);
control->data = control->dump; control->data = control->dump;
control->dump = rtnl_dumpit; control->dump = rtnl_dumpit;
...@@ -6703,7 +6709,6 @@ static int __net_init rtnetlink_net_init(struct net *net) ...@@ -6703,7 +6709,6 @@ static int __net_init rtnetlink_net_init(struct net *net)
struct netlink_kernel_cfg cfg = { struct netlink_kernel_cfg cfg = {
.groups = RTNLGRP_MAX, .groups = RTNLGRP_MAX,
.input = rtnetlink_rcv, .input = rtnetlink_rcv,
.cb_mutex = &rtnl_mutex,
.flags = NL_CFG_F_NONROOT_RECV, .flags = NL_CFG_F_NONROOT_RECV,
.bind = rtnetlink_bind, .bind = rtnetlink_bind,
}; };
......
...@@ -636,8 +636,7 @@ static struct proto netlink_proto = { ...@@ -636,8 +636,7 @@ static struct proto netlink_proto = {
}; };
static int __netlink_create(struct net *net, struct socket *sock, static int __netlink_create(struct net *net, struct socket *sock,
struct mutex *dump_cb_mutex, int protocol, int protocol, int kern)
int kern)
{ {
struct sock *sk; struct sock *sk;
struct netlink_sock *nlk; struct netlink_sock *nlk;
...@@ -655,7 +654,6 @@ static int __netlink_create(struct net *net, struct socket *sock, ...@@ -655,7 +654,6 @@ static int __netlink_create(struct net *net, struct socket *sock,
lockdep_set_class_and_name(&nlk->nl_cb_mutex, lockdep_set_class_and_name(&nlk->nl_cb_mutex,
nlk_cb_mutex_keys + protocol, nlk_cb_mutex_keys + protocol,
nlk_cb_mutex_key_strings[protocol]); nlk_cb_mutex_key_strings[protocol]);
nlk->dump_cb_mutex = dump_cb_mutex;
init_waitqueue_head(&nlk->wait); init_waitqueue_head(&nlk->wait);
sk->sk_destruct = netlink_sock_destruct; sk->sk_destruct = netlink_sock_destruct;
...@@ -667,7 +665,6 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol, ...@@ -667,7 +665,6 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol,
int kern) int kern)
{ {
struct module *module = NULL; struct module *module = NULL;
struct mutex *cb_mutex;
struct netlink_sock *nlk; struct netlink_sock *nlk;
int (*bind)(struct net *net, int group); int (*bind)(struct net *net, int group);
void (*unbind)(struct net *net, int group); void (*unbind)(struct net *net, int group);
...@@ -696,7 +693,6 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol, ...@@ -696,7 +693,6 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol,
module = nl_table[protocol].module; module = nl_table[protocol].module;
else else
err = -EPROTONOSUPPORT; err = -EPROTONOSUPPORT;
cb_mutex = nl_table[protocol].cb_mutex;
bind = nl_table[protocol].bind; bind = nl_table[protocol].bind;
unbind = nl_table[protocol].unbind; unbind = nl_table[protocol].unbind;
release = nl_table[protocol].release; release = nl_table[protocol].release;
...@@ -705,7 +701,7 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol, ...@@ -705,7 +701,7 @@ static int netlink_create(struct net *net, struct socket *sock, int protocol,
if (err < 0) if (err < 0)
goto out; goto out;
err = __netlink_create(net, sock, cb_mutex, protocol, kern); err = __netlink_create(net, sock, protocol, kern);
if (err < 0) if (err < 0)
goto out_module; goto out_module;
...@@ -2016,7 +2012,6 @@ __netlink_kernel_create(struct net *net, int unit, struct module *module, ...@@ -2016,7 +2012,6 @@ __netlink_kernel_create(struct net *net, int unit, struct module *module,
struct sock *sk; struct sock *sk;
struct netlink_sock *nlk; struct netlink_sock *nlk;
struct listeners *listeners = NULL; struct listeners *listeners = NULL;
struct mutex *cb_mutex = cfg ? cfg->cb_mutex : NULL;
unsigned int groups; unsigned int groups;
BUG_ON(!nl_table); BUG_ON(!nl_table);
...@@ -2027,7 +2022,7 @@ __netlink_kernel_create(struct net *net, int unit, struct module *module, ...@@ -2027,7 +2022,7 @@ __netlink_kernel_create(struct net *net, int unit, struct module *module,
if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock)) if (sock_create_lite(PF_NETLINK, SOCK_DGRAM, unit, &sock))
return NULL; return NULL;
if (__netlink_create(net, sock, cb_mutex, unit, 1) < 0) if (__netlink_create(net, sock, unit, 1) < 0)
goto out_sock_release_nosk; goto out_sock_release_nosk;
sk = sock->sk; sk = sock->sk;
...@@ -2055,7 +2050,6 @@ __netlink_kernel_create(struct net *net, int unit, struct module *module, ...@@ -2055,7 +2050,6 @@ __netlink_kernel_create(struct net *net, int unit, struct module *module,
if (!nl_table[unit].registered) { if (!nl_table[unit].registered) {
nl_table[unit].groups = groups; nl_table[unit].groups = groups;
rcu_assign_pointer(nl_table[unit].listeners, listeners); rcu_assign_pointer(nl_table[unit].listeners, listeners);
nl_table[unit].cb_mutex = cb_mutex;
nl_table[unit].module = module; nl_table[unit].module = module;
if (cfg) { if (cfg) {
nl_table[unit].bind = cfg->bind; nl_table[unit].bind = cfg->bind;
...@@ -2326,17 +2320,9 @@ static int netlink_dump(struct sock *sk, bool lock_taken) ...@@ -2326,17 +2320,9 @@ static int netlink_dump(struct sock *sk, bool lock_taken)
netlink_skb_set_owner_r(skb, sk); netlink_skb_set_owner_r(skb, sk);
if (nlk->dump_done_errno > 0) { if (nlk->dump_done_errno > 0) {
struct mutex *extra_mutex = nlk->dump_cb_mutex;
cb->extack = &extack; cb->extack = &extack;
if (cb->flags & RTNL_FLAG_DUMP_UNLOCKED)
extra_mutex = NULL;
if (extra_mutex)
mutex_lock(extra_mutex);
nlk->dump_done_errno = cb->dump(skb, cb); nlk->dump_done_errno = cb->dump(skb, cb);
if (extra_mutex)
mutex_unlock(extra_mutex);
/* EMSGSIZE plus something already in the skb means /* EMSGSIZE plus something already in the skb means
* that there's more to dump but current skb has filled up. * that there's more to dump but current skb has filled up.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment