Whamcloud - gitweb
LU-17705 ptlrpc: replace synchronize_rcu() with rcu_barrier()
[fs/lustre-release.git] / lnet / klnds / socklnd / socklnd_lib.c
index 375128c..f5e4b87 100644 (file)
@@ -27,7 +27,6 @@
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
- * Lustre is a trademark of Sun Microsystems, Inc.
  */
 
 #include "socklnd.h"
@@ -36,25 +35,24 @@ int
 ksocknal_lib_get_conn_addrs(struct ksock_conn *conn)
 {
        int rc = lnet_sock_getaddr(conn->ksnc_sock, true,
-                                  &conn->ksnc_ipaddr,
-                                  &conn->ksnc_port);
+                                  &conn->ksnc_peeraddr);
 
-        /* Didn't need the {get,put}connsock dance to deref ksnc_sock... */
-        LASSERT (!conn->ksnc_closing);
+       /* Didn't need the {get,put}connsock dance to deref ksnc_sock... */
+       LASSERT(!conn->ksnc_closing);
 
-        if (rc != 0) {
-                CERROR ("Error %d getting sock peer_ni IP\n", rc);
-                return rc;
-        }
+       if (rc != 0) {
+               CERROR("Error %d getting sock peer_ni IP\n", rc);
+               return rc;
+       }
 
        rc = lnet_sock_getaddr(conn->ksnc_sock, false,
-                                 &conn->ksnc_myipaddr, NULL);
-        if (rc != 0) {
-                CERROR ("Error %d getting sock local IP\n", rc);
-                return rc;
-        }
+                              &conn->ksnc_myaddr);
+       if (rc != 0) {
+               CERROR("Error %d getting sock local IP\n", rc);
+               return rc;
+       }
 
-        return 0;
+       return 0;
 }
 
 int
@@ -111,6 +109,25 @@ ksocknal_lib_send_hdr(struct ksock_conn *conn, struct ksock_tx *tx,
        return rc;
 }
 
+static int
+ksocknal_lib_sendpage(struct socket *sock, struct bio_vec *kiov, int msgflg)
+{
+#ifdef MSG_SPLICE_PAGES
+       struct msghdr msg = {.msg_flags = msgflg | MSG_SPLICE_PAGES};
+
+       iov_iter_bvec(&msg.msg_iter, ITER_SOURCE, kiov, 1, kiov->bv_len);
+
+       return sock_sendmsg(sock, &msg);
+#else
+       struct sock   *sk = sock->sk;
+       struct page *page = kiov->bv_page;
+       int offset = kiov->bv_offset;
+       int fragsize = kiov->bv_len;
+
+       return sk->sk_prot->sendpage(sk, page, offset, fragsize, msgflg);
+#endif
+}
+
 int
 ksocknal_lib_send_kiov(struct ksock_conn *conn, struct ksock_tx *tx,
                       struct kvec *scratchiov)
@@ -127,21 +144,16 @@ ksocknal_lib_send_kiov(struct ksock_conn *conn, struct ksock_tx *tx,
         * or leave them alone. */
        if (tx->tx_msg.ksm_zc_cookies[0] != 0) {
                /* Zero copy is enabled */
-               struct sock   *sk = sock->sk;
-               struct page   *page = kiov->bv_page;
-               int            offset = kiov->bv_offset;
-               int            fragsize = kiov->bv_len;
                int            msgflg = MSG_DONTWAIT;
 
                CDEBUG(D_NET, "page %p + offset %x for %d\n",
-                              page, offset, kiov->bv_len);
+                              kiov->bv_page, kiov->bv_offset, kiov->bv_len);
 
                if (!list_empty(&conn->ksnc_tx_queue) ||
-                   fragsize < tx->tx_resid)
+                   kiov->bv_len < tx->tx_resid)
                        msgflg |= MSG_MORE;
 
-               rc = sk->sk_prot->sendpage(sk, page,
-                                          offset, fragsize, msgflg);
+               rc = ksocknal_lib_sendpage(sock, kiov, msgflg);
        } else {
 #if SOCKNAL_SINGLE_FRAG_TX || !SOCKNAL_RISK_KMAP_DEADLOCK
                struct kvec     scratch;
@@ -177,16 +189,14 @@ ksocknal_lib_send_kiov(struct ksock_conn *conn, struct ksock_tx *tx,
 void
 ksocknal_lib_eager_ack(struct ksock_conn *conn)
 {
-       int opt = 1;
        struct socket *sock = conn->ksnc_sock;
 
-        /* Remind the socket to ACK eagerly.  If I don't, the socket might
-         * think I'm about to send something it could piggy-back the ACK
-         * on, introducing delay in completing zero-copy sends in my
-         * peer_ni. */
+       /* Remind the socket to ACK eagerly.  If I don't, the socket might
+        * think I'm about to send something it could piggy-back the ACK on,
+        * introducing delay in completing zero-copy sends in my peer_ni.
+        */
 
-       kernel_setsockopt(sock, SOL_TCP, TCP_QUICKACK,
-                         (char *)&opt, sizeof(opt));
+       tcp_sock_set_quickack(sock->sk, 1);
 }
 
 int
@@ -408,162 +418,137 @@ ksocknal_lib_csum_tx(struct ksock_tx *tx)
 int
 ksocknal_lib_get_conn_tunables(struct ksock_conn *conn, int *txmem, int *rxmem, int *nagle)
 {
-        struct socket *sock = conn->ksnc_sock;
-        int            len;
-        int            rc;
-
-        rc = ksocknal_connsock_addref(conn);
-        if (rc != 0) {
-                LASSERT (conn->ksnc_closing);
-                *txmem = *rxmem = *nagle = 0;
-                return (-ESHUTDOWN);
-        }
+       struct socket *sock = conn->ksnc_sock;
+       struct tcp_sock *tp = tcp_sk(sock->sk);
+
+       if (ksocknal_connsock_addref(conn) < 0) {
+               LASSERT(conn->ksnc_closing);
+               *txmem = 0;
+               *rxmem = 0;
+               *nagle = 0;
+               return -ESHUTDOWN;
+       }
 
-       rc = lnet_sock_getbuf(sock, txmem, rxmem);
-        if (rc == 0) {
-                len = sizeof(*nagle);
-               rc = kernel_getsockopt(sock, SOL_TCP, TCP_NODELAY,
-                                      (char *)nagle, &len);
-        }
+       lnet_sock_getbuf(sock, txmem, rxmem);
+
+       *nagle = !(tp->nonagle & TCP_NAGLE_OFF);
 
-        ksocknal_connsock_decref(conn);
+       ksocknal_connsock_decref(conn);
 
-        if (rc == 0)
-                *nagle = !*nagle;
-        else
-                *txmem = *rxmem = *nagle = 0;
 
-        return (rc);
+       return 0;
 }
 
 int
-ksocknal_lib_setup_sock (struct socket *sock)
+ksocknal_lib_setup_sock(struct socket *sock, struct lnet_ni *ni)
 {
-        int             rc;
-        int             option;
-        int             keep_idle;
-        int             keep_intvl;
-        int             keep_count;
-        int             do_keepalive;
-        struct linger   linger;
-
-        sock->sk->sk_allocation = GFP_NOFS;
-
-        /* Ensure this socket aborts active sends immediately when we close
-         * it. */
-
-        linger.l_onoff = 0;
-        linger.l_linger = 0;
-
-       rc = kernel_setsockopt(sock, SOL_SOCKET, SO_LINGER,
-                              (char *)&linger, sizeof(linger));
-        if (rc != 0) {
-                CERROR ("Can't set SO_LINGER: %d\n", rc);
-                return (rc);
-        }
+       int rc;
+       int keep_idle;
+       int keep_intvl;
+       int keep_count;
+       int do_keepalive;
+       struct tcp_sock *tp = tcp_sk(sock->sk);
+       struct lnet_ioctl_config_socklnd_tunables *lndtun;
 
-        option = -1;
-       rc = kernel_setsockopt(sock, SOL_TCP, TCP_LINGER2,
-                              (char *)&option, sizeof(option));
-        if (rc != 0) {
-                CERROR ("Can't set SO_LINGER2: %d\n", rc);
-                return (rc);
-        }
+       sock->sk->sk_allocation = GFP_NOFS;
 
-        if (!*ksocknal_tunables.ksnd_nagle) {
-                option = 1;
+       /* Ensure this socket aborts active sends immediately when closed. */
+       sock_reset_flag(sock->sk, SOCK_LINGER);
 
-               rc = kernel_setsockopt(sock, SOL_TCP, TCP_NODELAY,
-                                      (char *)&option, sizeof(option));
-                if (rc != 0) {
-                        CERROR ("Can't disable nagle: %d\n", rc);
-                        return (rc);
-                }
-        }
+       tp->linger2 = -1;
 
-       rc = lnet_sock_setbuf(sock,
-                             *ksocknal_tunables.ksnd_tx_buffer_size,
-                             *ksocknal_tunables.ksnd_rx_buffer_size);
-        if (rc != 0) {
-                CERROR ("Can't set buffer tx %d, rx %d buffers: %d\n",
-                        *ksocknal_tunables.ksnd_tx_buffer_size,
-                        *ksocknal_tunables.ksnd_rx_buffer_size, rc);
-                return (rc);
-        }
+       if (!*ksocknal_tunables.ksnd_nagle)
+               tcp_sock_set_nodelay(sock->sk);
+
+       lnet_sock_setbuf(sock,
+                        *ksocknal_tunables.ksnd_tx_buffer_size,
+                        *ksocknal_tunables.ksnd_rx_buffer_size);
 
 /* TCP_BACKOFF_* sockopt tunables unsupported in stock kernels */
 #ifdef SOCKNAL_BACKOFF
-        if (*ksocknal_tunables.ksnd_backoff_init > 0) {
-                option = *ksocknal_tunables.ksnd_backoff_init;
+       if (*ksocknal_tunables.ksnd_backoff_init > 0) {
+               int option = *ksocknal_tunables.ksnd_backoff_init;
 #ifdef SOCKNAL_BACKOFF_MS
-                option *= 1000;
+               option *= 1000;
 #endif
 
                rc = kernel_setsockopt(sock, SOL_TCP, TCP_BACKOFF_INIT,
                                       (char *)&option, sizeof(option));
-                if (rc != 0) {
-                        CERROR ("Can't set initial tcp backoff %d: %d\n",
-                                option, rc);
-                        return (rc);
-                }
-        }
+               if (rc != 0) {
+                       CERROR("Can't set initial tcp backoff %d: %d\n",
+                              option, rc);
+                       return rc;
+               }
+       }
 
-        if (*ksocknal_tunables.ksnd_backoff_max > 0) {
-                option = *ksocknal_tunables.ksnd_backoff_max;
+       if (*ksocknal_tunables.ksnd_backoff_max > 0) {
+               int option = *ksocknal_tunables.ksnd_backoff_max;
 #ifdef SOCKNAL_BACKOFF_MS
-                option *= 1000;
+               option *= 1000;
 #endif
 
                rc = kernel_setsockopt(sock, SOL_TCP, TCP_BACKOFF_MAX,
                                       (char *)&option, sizeof(option));
-                if (rc != 0) {
-                        CERROR ("Can't set maximum tcp backoff %d: %d\n",
-                                option, rc);
-                        return (rc);
-                }
-        }
+               if (rc != 0) {
+                       CERROR("Can't set maximum tcp backoff %d: %d\n",
+                              option, rc);
+                       return rc;
+               }
+       }
 #endif
 
-        /* snapshot tunables */
-        keep_idle  = *ksocknal_tunables.ksnd_keepalive_idle;
-        keep_count = *ksocknal_tunables.ksnd_keepalive_count;
-        keep_intvl = *ksocknal_tunables.ksnd_keepalive_intvl;
+       /* snapshot tunables */
+       keep_idle  = *ksocknal_tunables.ksnd_keepalive_idle;
+       keep_count = *ksocknal_tunables.ksnd_keepalive_count;
+       keep_intvl = *ksocknal_tunables.ksnd_keepalive_intvl;
 
-        do_keepalive = (keep_idle > 0 && keep_count > 0 && keep_intvl > 0);
+       do_keepalive = (keep_idle > 0 && keep_count > 0 && keep_intvl > 0);
 
-        option = (do_keepalive ? 1 : 0);
-       rc = kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
-                              (char *)&option, sizeof(option));
-        if (rc != 0) {
-                CERROR ("Can't set SO_KEEPALIVE: %d\n", rc);
-                return (rc);
-        }
-
-        if (!do_keepalive)
-                return (0);
+#ifdef HAVE_KERNEL_SETSOCKOPT
+       /* open-coded version doesn't work in all kernels, and
+        * there is no helper function, so call kernel_setsockopt()
+        * directly.
+        */
+       {
+               int option = (do_keepalive ? 1 : 0);
+               kernel_setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE,
+                                 (char *)&option, sizeof(option));
+       }
+#else
+       if (sock->sk->sk_prot->keepalive)
+               sock->sk->sk_prot->keepalive(sock->sk, do_keepalive);
+       if (do_keepalive)
+               sock_set_flag(sock->sk, SOCK_KEEPOPEN);
+       else
+               sock_reset_flag(sock->sk, SOCK_KEEPOPEN);
+#endif /* HAVE_KERNEL_SETSOCKOPT */
+
+       if (!do_keepalive)
+               return (0);
+
+       rc = tcp_sock_set_keepidle(sock->sk, keep_idle);
+       if (rc != 0) {
+               CERROR("Can't set TCP_KEEPIDLE: %d\n", rc);
+               return rc;
+       }
 
-       rc = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPIDLE,
-                              (char *)&keep_idle, sizeof(keep_idle));
-        if (rc != 0) {
-                CERROR ("Can't set TCP_KEEPIDLE: %d\n", rc);
-                return (rc);
-        }
+       rc = tcp_sock_set_keepintvl(sock->sk, keep_intvl);
+       if (rc != 0) {
+               CERROR("Can't set TCP_KEEPINTVL: %d\n", rc);
+               return rc;
+       }
 
-       rc = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPINTVL,
-                              (char *)&keep_intvl, sizeof(keep_intvl));
-        if (rc != 0) {
-                CERROR ("Can't set TCP_KEEPINTVL: %d\n", rc);
-                return (rc);
-        }
+       rc = tcp_sock_set_keepcnt(sock->sk, keep_count);
+       if (rc != 0) {
+               CERROR("Can't set TCP_KEEPCNT: %d\n", rc);
+               return rc;
+       }
 
-       rc = kernel_setsockopt(sock, SOL_TCP, TCP_KEEPCNT,
-                              (char *)&keep_count, sizeof(keep_count));
-        if (rc != 0) {
-                CERROR ("Can't set TCP_KEEPCNT: %d\n", rc);
-                return (rc);
-        }
+       lndtun = &ni->ni_lnd_tunables.lnd_tun_u.lnd_sock;
+       if (lndtun->lnd_tos >= 0)
+               ip_sock_set_tos(sock->sk, lndtun->lnd_tos);
 
-        return (0);
+       return (0);
 }
 
 void
@@ -572,30 +557,27 @@ ksocknal_lib_push_conn(struct ksock_conn *conn)
        struct sock *sk;
        struct tcp_sock *tp;
        int nonagle;
-       int val = 1;
        int rc;
 
-        rc = ksocknal_connsock_addref(conn);
-        if (rc != 0)                            /* being shut down */
-                return;
+       rc = ksocknal_connsock_addref(conn);
+       if (rc != 0)                            /* being shut down */
+               return;
 
        sk = conn->ksnc_sock->sk;
        tp = tcp_sk(sk);
 
-        lock_sock (sk);
-        nonagle = tp->nonagle;
-        tp->nonagle = 1;
-        release_sock (sk);
+       lock_sock(sk);
+       nonagle = tp->nonagle;
+       tp->nonagle = TCP_NAGLE_OFF;
+       release_sock(sk);
 
-       rc = kernel_setsockopt(conn->ksnc_sock, SOL_TCP, TCP_NODELAY,
-                              (char *)&val, sizeof(val));
-        LASSERT (rc == 0);
+       tcp_sock_set_nodelay(conn->ksnc_sock->sk);
 
-        lock_sock (sk);
-        tp->nonagle = nonagle;
-        release_sock (sk);
+       lock_sock(sk);
+       tp->nonagle = nonagle;
+       release_sock(sk);
 
-        ksocknal_connsock_decref(conn);
+       ksocknal_connsock_decref(conn);
 }
 
 void ksocknal_read_callback(struct ksock_conn *conn);
@@ -611,11 +593,10 @@ ksocknal_data_ready(struct sock *sk, int n)
 #endif
 {
        struct ksock_conn  *conn;
-       ENTRY;
 
         /* interleave correctly with closing sockets... */
         LASSERT(!in_irq());
-       read_lock(&ksocknal_data.ksnd_global_lock);
+       read_lock_bh(&ksocknal_data.ksnd_global_lock);
 
        conn = sk->sk_user_data;
        if (conn == NULL) {     /* raced with ksocknal_terminate_conn */
@@ -628,9 +609,7 @@ ksocknal_data_ready(struct sock *sk, int n)
        } else
                ksocknal_read_callback(conn);
 
-       read_unlock(&ksocknal_data.ksnd_global_lock);
-
-       EXIT;
+       read_unlock_bh(&ksocknal_data.ksnd_global_lock);
 }
 
 static void