Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net

Conflicts:
	arch/arm/boot/dts/imx6sx-sdb.dts
	net/sched/cls_bpf.c

Two simple sets of overlapping changes.

Signed-off-by: David S. Miller <[email protected]>
This commit is contained in:
David S. Miller 2015-01-27 16:59:56 -08:00
commit 95f873f2ff
457 changed files with 4418 additions and 3193 deletions

View file

@ -61,6 +61,7 @@
#include <linux/rhashtable.h>
#include <asm/cacheflush.h>
#include <linux/hash.h>
#include <linux/genetlink.h>
#include <net/net_namespace.h>
#include <net/sock.h>
@ -1091,6 +1092,8 @@ static void netlink_remove(struct sock *sk)
__sk_del_bind_node(sk);
netlink_update_listeners(sk);
}
if (sk->sk_protocol == NETLINK_GENERIC)
atomic_inc(&genl_sk_destructing_cnt);
netlink_table_ungrab();
}
@ -1214,6 +1217,20 @@ static int netlink_release(struct socket *sock)
* will be purged.
*/
/* must not acquire netlink_table_lock in any way again before unbind
* and notifying genetlink is done as otherwise it might deadlock
*/
if (nlk->netlink_unbind) {
int i;
for (i = 0; i < nlk->ngroups; i++)
if (test_bit(i, nlk->groups))
nlk->netlink_unbind(sock_net(sk), i + 1);
}
if (sk->sk_protocol == NETLINK_GENERIC &&
atomic_dec_return(&genl_sk_destructing_cnt) == 0)
wake_up(&genl_sk_destructing_waitq);
sock->sk = NULL;
wake_up_interruptible_all(&nlk->wait);
@ -1249,13 +1266,6 @@ static int netlink_release(struct socket *sock)
netlink_table_ungrab();
}
if (nlk->netlink_unbind) {
int i;
for (i = 0; i < nlk->ngroups; i++)
if (test_bit(i, nlk->groups))
nlk->netlink_unbind(sock_net(sk), i + 1);
}
kfree(nlk->groups);
nlk->groups = NULL;

View file

@ -2,6 +2,7 @@
#define _AF_NETLINK_H
#include <linux/rhashtable.h>
#include <linux/atomic.h>
#include <net/sock.h>
#define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8)

View file

@ -23,6 +23,9 @@
static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */
static DECLARE_RWSEM(cb_lock);
atomic_t genl_sk_destructing_cnt = ATOMIC_INIT(0);
DECLARE_WAIT_QUEUE_HEAD(genl_sk_destructing_waitq);
void genl_lock(void)
{
mutex_lock(&genl_mutex);
@ -435,15 +438,18 @@ int genl_unregister_family(struct genl_family *family)
genl_lock_all();
genl_unregister_mc_groups(family);
list_for_each_entry(rc, genl_family_chain(family->id), family_list) {
if (family->id != rc->id || strcmp(rc->name, family->name))
continue;
genl_unregister_mc_groups(family);
list_del(&rc->family_list);
family->n_ops = 0;
genl_unlock_all();
up_write(&cb_lock);
wait_event(genl_sk_destructing_waitq,
atomic_read(&genl_sk_destructing_cnt) == 0);
genl_unlock();
kfree(family->attrbuf);
genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0);
@ -987,7 +993,7 @@ static struct genl_multicast_group genl_ctrl_groups[] = {
static int genl_bind(struct net *net, int group)
{
int i, err = 0;
int i, err = -ENOENT;
down_read(&cb_lock);
for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {
@ -1016,7 +1022,6 @@ static int genl_bind(struct net *net, int group)
static void genl_unbind(struct net *net, int group)
{
int i;
bool found = false;
down_read(&cb_lock);
for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {
@ -1029,14 +1034,11 @@ static void genl_unbind(struct net *net, int group)
if (f->mcast_unbind)
f->mcast_unbind(net, fam_grp);
found = true;
break;
}
}
}
up_read(&cb_lock);
WARN_ON(!found);
}
static int __net_init genl_pernet_init(struct net *net)