OSDN Git Service

net: ipv4: Fix a spinlock recursion bug in tcp_v4_nuke.
[android-x86/kernel.git] / net / ipv4 / tcp_ipv4.c
index 19d7b42..b04e5ad 100644 (file)
@@ -1853,6 +1853,40 @@ void tcp_v4_destroy_sock(struct sock *sk)
 
 EXPORT_SYMBOL(tcp_v4_destroy_sock);
 
+/*
+ * tcp_v4_nuke_addr - destroy all sockets on the given local address
+ */
+void tcp_v4_nuke_addr(__u32 saddr)
+{
+       unsigned int bucket;
+
+       for (bucket = 0; bucket < tcp_hashinfo.ehash_size; bucket++) {
+               struct hlist_nulls_node *node;
+               struct sock *sk;
+               spinlock_t *lock = inet_ehash_lockp(&tcp_hashinfo, bucket);
+
+restart:
+               spin_lock_bh(lock);
+               sk_nulls_for_each(sk, node, &tcp_hashinfo.ehash[bucket].chain) {
+                       struct inet_sock *inet = inet_sk(sk);
+
+                       if (inet->rcv_saddr != saddr)
+                               continue;
+                       if (sysctl_ip_dynaddr && sk->sk_state == TCP_SYN_SENT)
+                               continue;
+                       if (sock_flag(sk, SOCK_DEAD))
+                               continue;
+
+                       sk->sk_err = ETIMEDOUT;
+                       sk->sk_error_report(sk);
+                       spin_unlock_bh(lock);
+                       tcp_done(sk);
+                       goto restart;
+               }
+               spin_unlock_bh(lock);
+       }
+}
+
 #ifdef CONFIG_PROC_FS
 /* Proc filesystem TCP sock list dumping. */
 
@@ -2443,7 +2477,7 @@ static struct pernet_operations __net_initdata tcp_sk_ops = {
 void __init tcp_v4_init(void)
 {
        inet_hashinfo_init(&tcp_hashinfo);
-       if (register_pernet_device(&tcp_sk_ops))
+       if (register_pernet_subsys(&tcp_sk_ops))
                panic("Failed to create the TCP control socket.\n");
 }