aboutsummaryrefslogtreecommitdiffstats
path: root/net/netlink/af_netlink.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2014-12-27 02:20:30 -0500
committerDavid S. Miller <davem@davemloft.net>2014-12-27 02:20:30 -0500
commit24f626d3439f61d87fca0c0c07f614fba41a4e92 (patch)
treeadc927b4f3fb05268c6ca808aee5d0109351fec1 /net/netlink/af_netlink.c
parentMerge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth (diff)
parentgenetlink: pass multicast bind/unbind to families (diff)
downloadlinux-dev-24f626d3439f61d87fca0c0c07f614fba41a4e92.tar.xz
linux-dev-24f626d3439f61d87fca0c0c07f614fba41a4e92.zip
Merge branch 'netlink_multicast'
Johannes Berg says: ==================== netlink/genetlink cleanups & multicast improvements I'm looking at using the multicast group functionality in a way that would benefit from knowing when there are subscribers to avoid collecting the required data when there aren't any. During this I noticed that the unbind for multicast groups doesn't actually work - it's never called when sockets are closed. Luckily, nobody actually uses the functionality. While looking at the code trying to find why it's not called and where the multicast listeners are actually removed, I found the potential cleanup in patch 3. Patch 2 also has a cleanup for a generic netlink API in this area. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/netlink/af_netlink.c')
-rw-r--r--net/netlink/af_netlink.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 074cf3e91c6f..f29b63fad932 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1091,8 +1091,10 @@ static void netlink_remove(struct sock *sk)
mutex_unlock(&nl_sk_hash_lock);
netlink_table_grab();
- if (nlk_sk(sk)->subscriptions)
+ if (nlk_sk(sk)->subscriptions) {
__sk_del_bind_node(sk);
+ netlink_update_listeners(sk);
+ }
netlink_table_ungrab();
}
@@ -1226,8 +1228,8 @@ static int netlink_release(struct socket *sock)
module_put(nlk->module);
- netlink_table_grab();
if (netlink_is_kernel(sk)) {
+ netlink_table_grab();
BUG_ON(nl_table[sk->sk_protocol].registered == 0);
if (--nl_table[sk->sk_protocol].registered == 0) {
struct listeners *old;
@@ -1241,11 +1243,16 @@ static int netlink_release(struct socket *sock)
nl_table[sk->sk_protocol].flags = 0;
nl_table[sk->sk_protocol].registered = 0;
}
- } else if (nlk->subscriptions) {
- netlink_update_listeners(sk);
+ netlink_table_ungrab();
}
- 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(i + 1);
+ }
kfree(nlk->groups);
nlk->groups = NULL;
@@ -1410,8 +1417,8 @@ static int netlink_realloc_groups(struct sock *sk)
return err;
}
-static void netlink_unbind(int group, long unsigned int groups,
- struct netlink_sock *nlk)
+static void netlink_undo_bind(int group, long unsigned int groups,
+ struct netlink_sock *nlk)
{
int undo;
@@ -1461,7 +1468,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
err = nlk->netlink_bind(group);
if (!err)
continue;
- netlink_unbind(group, groups, nlk);
+ netlink_undo_bind(group, groups, nlk);
return err;
}
}
@@ -1471,7 +1478,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr,
netlink_insert(sk, net, nladdr->nl_pid) :
netlink_autobind(sock);
if (err) {
- netlink_unbind(nlk->ngroups, groups, nlk);
+ netlink_undo_bind(nlk->ngroups, groups, nlk);
return err;
}
}