diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/netlink/af_netlink.c | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 42d2fb94eff..7fc6b4da4f0 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -140,6 +140,15 @@ static struct hlist_head *nl_pid_hashfn(struct nl_pid_hash *hash, u32 pid) static void netlink_sock_destruct(struct sock *sk) { + struct netlink_sock *nlk = nlk_sk(sk); + + BUG_ON(mutex_is_locked(nlk_sk(sk)->cb_mutex)); + if (nlk->cb) { + if (nlk->cb->done) + nlk->cb->done(nlk->cb); + netlink_destroy_callback(nlk->cb); + } + skb_queue_purge(&sk->sk_receive_queue); if (!sock_flag(sk, SOCK_DEAD)) { @@ -148,7 +157,6 @@ static void netlink_sock_destruct(struct sock *sk) } BUG_TRAP(!atomic_read(&sk->sk_rmem_alloc)); BUG_TRAP(!atomic_read(&sk->sk_wmem_alloc)); - BUG_TRAP(!nlk_sk(sk)->cb); BUG_TRAP(!nlk_sk(sk)->groups); } @@ -456,17 +464,10 @@ static int netlink_release(struct socket *sock) sock_orphan(sk); nlk = nlk_sk(sk); - mutex_lock(nlk->cb_mutex); - if (nlk->cb) { - if (nlk->cb->done) - nlk->cb->done(nlk->cb); - netlink_destroy_callback(nlk->cb); - nlk->cb = NULL; - } - mutex_unlock(nlk->cb_mutex); - - /* OK. Socket is unlinked, and, therefore, - no new packets will arrive */ + /* + * OK. Socket is unlinked, any packets that arrive now + * will be purged. + */ sock->sk = NULL; wake_up_interruptible_all(&nlk->wait); @@ -1426,9 +1427,9 @@ int netlink_dump_start(struct sock *ssk, struct sk_buff *skb, return -ECONNREFUSED; } nlk = nlk_sk(sk); - /* A dump or destruction is in progress... */ + /* A dump is in progress... */ mutex_lock(nlk->cb_mutex); - if (nlk->cb || sock_flag(sk, SOCK_DEAD)) { + if (nlk->cb) { mutex_unlock(nlk->cb_mutex); netlink_destroy_callback(cb); sock_put(sk); |