aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2015-01-27 19:59:56 -0500
committerDavid S. Miller <davem@davemloft.net>2015-01-27 19:59:56 -0500
commit95f873f2fff96c592c5d863e2a39825bd8bf0500 (patch)
tree0d2dd664964ba2c701aefea5b4d1e85b481045e1 /net/netlink
parent8ea65f4a2dfaaf494ef42a16cbf2fea39b07450f (diff)
parent59343cd7c4809cf7598789e1cd14563780ae4239 (diff)
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 <davem@davemloft.net>
Diffstat (limited to 'net/netlink')
-rw-r--r--net/netlink/af_netlink.c24
-rw-r--r--net/netlink/af_netlink.h1
-rw-r--r--net/netlink/genetlink.c18
3 files changed, 28 insertions, 15 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index d77b3467b1d4..2197af00673a 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -61,6 +61,7 @@
61#include <linux/rhashtable.h> 61#include <linux/rhashtable.h>
62#include <asm/cacheflush.h> 62#include <asm/cacheflush.h>
63#include <linux/hash.h> 63#include <linux/hash.h>
64#include <linux/genetlink.h>
64 65
65#include <net/net_namespace.h> 66#include <net/net_namespace.h>
66#include <net/sock.h> 67#include <net/sock.h>
@@ -1091,6 +1092,8 @@ static void netlink_remove(struct sock *sk)
1091 __sk_del_bind_node(sk); 1092 __sk_del_bind_node(sk);
1092 netlink_update_listeners(sk); 1093 netlink_update_listeners(sk);
1093 } 1094 }
1095 if (sk->sk_protocol == NETLINK_GENERIC)
1096 atomic_inc(&genl_sk_destructing_cnt);
1094 netlink_table_ungrab(); 1097 netlink_table_ungrab();
1095} 1098}
1096 1099
@@ -1214,6 +1217,20 @@ static int netlink_release(struct socket *sock)
1214 * will be purged. 1217 * will be purged.
1215 */ 1218 */
1216 1219
1220 /* must not acquire netlink_table_lock in any way again before unbind
1221 * and notifying genetlink is done as otherwise it might deadlock
1222 */
1223 if (nlk->netlink_unbind) {
1224 int i;
1225
1226 for (i = 0; i < nlk->ngroups; i++)
1227 if (test_bit(i, nlk->groups))
1228 nlk->netlink_unbind(sock_net(sk), i + 1);
1229 }
1230 if (sk->sk_protocol == NETLINK_GENERIC &&
1231 atomic_dec_return(&genl_sk_destructing_cnt) == 0)
1232 wake_up(&genl_sk_destructing_waitq);
1233
1217 sock->sk = NULL; 1234 sock->sk = NULL;
1218 wake_up_interruptible_all(&nlk->wait); 1235 wake_up_interruptible_all(&nlk->wait);
1219 1236
@@ -1249,13 +1266,6 @@ static int netlink_release(struct socket *sock)
1249 netlink_table_ungrab(); 1266 netlink_table_ungrab();
1250 } 1267 }
1251 1268
1252 if (nlk->netlink_unbind) {
1253 int i;
1254
1255 for (i = 0; i < nlk->ngroups; i++)
1256 if (test_bit(i, nlk->groups))
1257 nlk->netlink_unbind(sock_net(sk), i + 1);
1258 }
1259 kfree(nlk->groups); 1269 kfree(nlk->groups);
1260 nlk->groups = NULL; 1270 nlk->groups = NULL;
1261 1271
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h
index 7518375782f5..89008405d6b4 100644
--- a/net/netlink/af_netlink.h
+++ b/net/netlink/af_netlink.h
@@ -2,6 +2,7 @@
2#define _AF_NETLINK_H 2#define _AF_NETLINK_H
3 3
4#include <linux/rhashtable.h> 4#include <linux/rhashtable.h>
5#include <linux/atomic.h>
5#include <net/sock.h> 6#include <net/sock.h>
6 7
7#define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) 8#define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8)
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index f52a7d5734cd..2ed5f964772e 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -23,6 +23,9 @@
23static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */ 23static DEFINE_MUTEX(genl_mutex); /* serialization of message processing */
24static DECLARE_RWSEM(cb_lock); 24static DECLARE_RWSEM(cb_lock);
25 25
26atomic_t genl_sk_destructing_cnt = ATOMIC_INIT(0);
27DECLARE_WAIT_QUEUE_HEAD(genl_sk_destructing_waitq);
28
26void genl_lock(void) 29void genl_lock(void)
27{ 30{
28 mutex_lock(&genl_mutex); 31 mutex_lock(&genl_mutex);
@@ -435,15 +438,18 @@ int genl_unregister_family(struct genl_family *family)
435 438
436 genl_lock_all(); 439 genl_lock_all();
437 440
438 genl_unregister_mc_groups(family);
439
440 list_for_each_entry(rc, genl_family_chain(family->id), family_list) { 441 list_for_each_entry(rc, genl_family_chain(family->id), family_list) {
441 if (family->id != rc->id || strcmp(rc->name, family->name)) 442 if (family->id != rc->id || strcmp(rc->name, family->name))
442 continue; 443 continue;
443 444
445 genl_unregister_mc_groups(family);
446
444 list_del(&rc->family_list); 447 list_del(&rc->family_list);
445 family->n_ops = 0; 448 family->n_ops = 0;
446 genl_unlock_all(); 449 up_write(&cb_lock);
450 wait_event(genl_sk_destructing_waitq,
451 atomic_read(&genl_sk_destructing_cnt) == 0);
452 genl_unlock();
447 453
448 kfree(family->attrbuf); 454 kfree(family->attrbuf);
449 genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0); 455 genl_ctrl_event(CTRL_CMD_DELFAMILY, family, NULL, 0);
@@ -987,7 +993,7 @@ static struct genl_multicast_group genl_ctrl_groups[] = {
987 993
988static int genl_bind(struct net *net, int group) 994static int genl_bind(struct net *net, int group)
989{ 995{
990 int i, err = 0; 996 int i, err = -ENOENT;
991 997
992 down_read(&cb_lock); 998 down_read(&cb_lock);
993 for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { 999 for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {
@@ -1016,7 +1022,6 @@ static int genl_bind(struct net *net, int group)
1016static void genl_unbind(struct net *net, int group) 1022static void genl_unbind(struct net *net, int group)
1017{ 1023{
1018 int i; 1024 int i;
1019 bool found = false;
1020 1025
1021 down_read(&cb_lock); 1026 down_read(&cb_lock);
1022 for (i = 0; i < GENL_FAM_TAB_SIZE; i++) { 1027 for (i = 0; i < GENL_FAM_TAB_SIZE; i++) {
@@ -1029,14 +1034,11 @@ static void genl_unbind(struct net *net, int group)
1029 1034
1030 if (f->mcast_unbind) 1035 if (f->mcast_unbind)
1031 f->mcast_unbind(net, fam_grp); 1036 f->mcast_unbind(net, fam_grp);
1032 found = true;
1033 break; 1037 break;
1034 } 1038 }
1035 } 1039 }
1036 } 1040 }
1037 up_read(&cb_lock); 1041 up_read(&cb_lock);
1038
1039 WARN_ON(!found);
1040} 1042}
1041 1043
1042static int __net_init genl_pernet_init(struct net *net) 1044static int __net_init genl_pernet_init(struct net *net)