]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - net/rds/tcp_listen.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[karo-tx-linux.git] / net / rds / tcp_listen.c
index be263cdf268bae5b59a4746d4011d1042ede58cd..f9cc945a77b3c7bab156c5ce0cf71f441fe6cc68 100644 (file)
@@ -35,6 +35,7 @@
 #include <linux/in.h>
 #include <net/tcp.h>
 
+#include "rds_single_path.h"
 #include "rds.h"
 #include "tcp.h"
 
@@ -78,7 +79,9 @@ int rds_tcp_accept_one(struct socket *sock)
        struct inet_sock *inet;
        struct rds_tcp_connection *rs_tcp = NULL;
        int conn_state;
-       struct sock *nsk;
+
+       if (!sock) /* module unload or netns delete in progress */
+               return -ENETUNREACH;
 
        ret = sock_create_kern(sock_net(sock->sk), sock->sk->sk_family,
                               sock->sk->sk_type, sock->sk->sk_protocol,
@@ -129,28 +132,27 @@ int rds_tcp_accept_one(struct socket *sock)
                 * so we must quiesce any send threads before resetting
                 * c_transport_data.
                 */
-               wait_event(conn->c_waitq,
-                          !test_bit(RDS_IN_XMIT, &conn->c_flags));
-               if (ntohl(inet->inet_saddr) < ntohl(inet->inet_daddr)) {
+               if (ntohl(inet->inet_saddr) < ntohl(inet->inet_daddr) ||
+                   !conn->c_path[0].cp_outgoing) {
                        goto rst_nsk;
-               } else if (rs_tcp->t_sock) {
-                       rds_tcp_restore_callbacks(rs_tcp->t_sock, rs_tcp);
-                       conn->c_outgoing = 0;
+               } else {
+                       rds_tcp_reset_callbacks(new_sock, conn);
+                       conn->c_path[0].cp_outgoing = 0;
+                       /* rds_connect_path_complete() marks RDS_CONN_UP */
+                       rds_connect_path_complete(&conn->c_path[0],
+                                                 RDS_CONN_RESETTING);
                }
+       } else {
+               rds_tcp_set_callbacks(new_sock, conn);
+               rds_connect_path_complete(&conn->c_path[0],
+                                         RDS_CONN_CONNECTING);
        }
-       rds_tcp_set_callbacks(new_sock, conn);
-       rds_connect_complete(conn); /* marks RDS_CONN_UP */
        new_sock = NULL;
        ret = 0;
        goto out;
 rst_nsk:
        /* reset the newly returned accept sock and bail */
-       nsk = new_sock->sk;
-       rds_tcp_stats_inc(s_tcp_listen_closed_stale);
-       nsk->sk_user_data = NULL;
-       nsk->sk_prot->disconnect(nsk, 0);
-       tcp_done(nsk);
-       new_sock = NULL;
+       kernel_sock_shutdown(new_sock, SHUT_RDWR);
        ret = 0;
 out:
        if (rs_tcp)
@@ -166,7 +168,7 @@ void rds_tcp_listen_data_ready(struct sock *sk)
 
        rdsdebug("listen data ready sk %p\n", sk);
 
-       read_lock(&sk->sk_callback_lock);
+       read_lock_bh(&sk->sk_callback_lock);
        ready = sk->sk_user_data;
        if (!ready) { /* check for teardown race */
                ready = sk->sk_data_ready;
@@ -183,7 +185,7 @@ void rds_tcp_listen_data_ready(struct sock *sk)
                rds_tcp_accept_work(sk);
 
 out:
-       read_unlock(&sk->sk_callback_lock);
+       read_unlock_bh(&sk->sk_callback_lock);
        ready(sk);
 }