These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / net / rds / tcp_listen.c
index 0da49e3..0936a4a 100644 (file)
 #include "rds.h"
 #include "tcp.h"
 
-/*
- * cheesy, but simple..
- */
-static void rds_tcp_accept_worker(struct work_struct *work);
-static DECLARE_WORK(rds_tcp_listen_work, rds_tcp_accept_worker);
-static struct socket *rds_tcp_listen_sock;
-
-static int rds_tcp_keepalive(struct socket *sock)
+int rds_tcp_keepalive(struct socket *sock)
 {
        /* values below based on xs_udp_default_timeout */
        int keepidle = 5; /* send a probe 'keepidle' secs after last data */
@@ -77,7 +70,7 @@ bail:
        return ret;
 }
 
-static int rds_tcp_accept_one(struct socket *sock)
+int rds_tcp_accept_one(struct socket *sock)
 {
        struct socket *new_sock = NULL;
        struct rds_connection *conn;
@@ -85,8 +78,9 @@ static int rds_tcp_accept_one(struct socket *sock)
        struct inet_sock *inet;
        struct rds_tcp_connection *rs_tcp;
 
-       ret = sock_create_lite(sock->sk->sk_family, sock->sk->sk_type,
-                              sock->sk->sk_protocol, &new_sock);
+       ret = sock_create_kern(sock_net(sock->sk), sock->sk->sk_family,
+                              sock->sk->sk_type, sock->sk->sk_protocol,
+                              &new_sock);
        if (ret)
                goto out;
 
@@ -108,35 +102,35 @@ static int rds_tcp_accept_one(struct socket *sock)
                 &inet->inet_saddr, ntohs(inet->inet_sport),
                 &inet->inet_daddr, ntohs(inet->inet_dport));
 
-       conn = rds_conn_create(inet->inet_saddr, inet->inet_daddr,
+       conn = rds_conn_create(sock_net(sock->sk),
+                              inet->inet_saddr, inet->inet_daddr,
                               &rds_tcp_transport, GFP_KERNEL);
        if (IS_ERR(conn)) {
                ret = PTR_ERR(conn);
                goto out;
        }
        /* An incoming SYN request came in, and TCP just accepted it.
-        * We always create a new conn for listen side of TCP, and do not
-        * add it to the c_hash_list.
         *
         * If the client reboots, this conn will need to be cleaned up.
         * rds_tcp_state_change() will do that cleanup
         */
        rs_tcp = (struct rds_tcp_connection *)conn->c_transport_data;
-       WARN_ON(!rs_tcp || rs_tcp->t_sock);
-
-       /*
-        * see the comment above rds_queue_delayed_reconnect()
-        */
-       if (!rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_CONNECTING)) {
-               if (rds_conn_state(conn) == RDS_CONN_UP)
-                       rds_tcp_stats_inc(s_tcp_listen_closed_stale);
-               else
-                       rds_tcp_stats_inc(s_tcp_connect_raced);
-               rds_conn_drop(conn);
+       if (rs_tcp->t_sock &&
+           ntohl(inet->inet_saddr) < ntohl(inet->inet_daddr)) {
+               struct sock *nsk = new_sock->sk;
+
+               nsk->sk_user_data = NULL;
+               nsk->sk_prot->disconnect(nsk, 0);
+               tcp_done(nsk);
+               new_sock = NULL;
                ret = 0;
                goto out;
+       } else if (rs_tcp->t_sock) {
+               rds_tcp_restore_callbacks(rs_tcp->t_sock, rs_tcp);
+               conn->c_outgoing = 0;
        }
 
+       rds_conn_transition(conn, RDS_CONN_DOWN, RDS_CONN_CONNECTING);
        rds_tcp_set_callbacks(new_sock, conn);
        rds_connect_complete(conn);
        new_sock = NULL;
@@ -148,12 +142,6 @@ out:
        return ret;
 }
 
-static void rds_tcp_accept_worker(struct work_struct *work)
-{
-       while (rds_tcp_accept_one(rds_tcp_listen_sock) == 0)
-               cond_resched();
-}
-
 void rds_tcp_listen_data_ready(struct sock *sk)
 {
        void (*ready)(struct sock *sk);
@@ -174,20 +162,20 @@ void rds_tcp_listen_data_ready(struct sock *sk)
         * socket
         */
        if (sk->sk_state == TCP_LISTEN)
-               queue_work(rds_wq, &rds_tcp_listen_work);
+               rds_tcp_accept_work(sk);
 
 out:
        read_unlock(&sk->sk_callback_lock);
        ready(sk);
 }
 
-int rds_tcp_listen_init(void)
+struct socket *rds_tcp_listen_init(struct net *net)
 {
        struct sockaddr_in sin;
        struct socket *sock = NULL;
        int ret;
 
-       ret = sock_create(PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
+       ret = sock_create_kern(net, PF_INET, SOCK_STREAM, IPPROTO_TCP, &sock);
        if (ret < 0)
                goto out;
 
@@ -211,17 +199,15 @@ int rds_tcp_listen_init(void)
        if (ret < 0)
                goto out;
 
-       rds_tcp_listen_sock = sock;
-       sock = NULL;
+       return sock;
 out:
        if (sock)
                sock_release(sock);
-       return ret;
+       return NULL;
 }
 
-void rds_tcp_listen_stop(void)
+void rds_tcp_listen_stop(struct socket *sock)
 {
-       struct socket *sock = rds_tcp_listen_sock;
        struct sock *sk;
 
        if (!sock)
@@ -242,5 +228,4 @@ void rds_tcp_listen_stop(void)
        /* wait for accepts to stop and close the socket */
        flush_workqueue(rds_wq);
        sock_release(sock);
-       rds_tcp_listen_sock = NULL;
 }