Whamcloud - gitweb
LU-14627 lnet: Ensure ref taken when queueing for discovery
[fs/lustre-release.git] / lnet / klnds / socklnd / socklnd_lib.c
index 7f9ffe0..333fbad 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
@@ -71,11 +69,11 @@ ksocknal_lib_zc_capable(struct ksock_conn *conn)
 }
 
 int
-ksocknal_lib_send_iov(struct ksock_conn *conn, struct ksock_tx *tx,
+ksocknal_lib_send_hdr(struct ksock_conn *conn, struct ksock_tx *tx,
                      struct kvec *scratchiov)
 {
        struct socket  *sock = conn->ksnc_sock;
-       int             nob;
+       int             nob = 0;
        int             rc;
 
        if (*ksocknal_tunables.ksnd_enable_csum        && /* checksum enabled */
@@ -96,11 +94,10 @@ ksocknal_lib_send_iov(struct ksock_conn *conn, struct ksock_tx *tx,
                unsigned int niov = tx->tx_niov;
 #endif
                struct msghdr msg = { .msg_flags = MSG_DONTWAIT };
-                int  i;
 
-               for (nob = i = 0; i < niov; i++) {
-                       scratchiov[i] = tx->tx_iov[i];
-                       nob += scratchiov[i].iov_len;
+               if (tx->tx_niov) {
+                       scratchiov[0] = tx->tx_hdr;
+                       nob += scratchiov[0].iov_len;
                }
 
                if (!list_empty(&conn->ksnc_tx_queue) ||
@@ -141,12 +138,8 @@ ksocknal_lib_send_kiov(struct ksock_conn *conn, struct ksock_tx *tx,
                    fragsize < tx->tx_resid)
                        msgflg |= MSG_MORE;
 
-               if (sk->sk_prot->sendpage != NULL) {
-                       rc = sk->sk_prot->sendpage(sk, page,
-                                                  offset, fragsize, msgflg);
-               } else {
-                       rc = tcp_sendpage(sk, page, offset, fragsize, msgflg);
-               }
+               rc = sk->sk_prot->sendpage(sk, page,
+                                          offset, fragsize, msgflg);
        } else {
 #if SOCKNAL_SINGLE_FRAG_TX || !SOCKNAL_RISK_KMAP_DEADLOCK
                struct kvec     scratch;
@@ -182,16 +175,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
@@ -384,29 +375,23 @@ ksocknal_lib_csum_tx(struct ksock_tx *tx)
         __u32        csum;
         void        *base;
 
-        LASSERT(tx->tx_iov[0].iov_base == (void *)&tx->tx_msg);
-        LASSERT(tx->tx_conn != NULL);
-        LASSERT(tx->tx_conn->ksnc_proto == &ksocknal_protocol_v2x);
+       LASSERT(tx->tx_hdr.iov_base == (void *)&tx->tx_msg);
+       LASSERT(tx->tx_conn != NULL);
+       LASSERT(tx->tx_conn->ksnc_proto == &ksocknal_protocol_v2x);
 
         tx->tx_msg.ksm_csum = 0;
 
-        csum = ksocknal_csum(~0, (void *)tx->tx_iov[0].iov_base,
-                             tx->tx_iov[0].iov_len);
+       csum = ksocknal_csum(~0, (void *)tx->tx_hdr.iov_base,
+                            tx->tx_hdr.iov_len);
 
-        if (tx->tx_kiov != NULL) {
-                for (i = 0; i < tx->tx_nkiov; i++) {
-                        base = kmap(tx->tx_kiov[i].bv_page) +
-                               tx->tx_kiov[i].bv_offset;
+       for (i = 0; i < tx->tx_nkiov; i++) {
+               base = kmap(tx->tx_kiov[i].bv_page) +
+                       tx->tx_kiov[i].bv_offset;
 
-                        csum = ksocknal_csum(csum, base, tx->tx_kiov[i].bv_len);
+               csum = ksocknal_csum(csum, base, tx->tx_kiov[i].bv_len);
 
-                        kunmap(tx->tx_kiov[i].bv_page);
-                }
-        } else {
-                for (i = 1; i < tx->tx_niov; i++)
-                        csum = ksocknal_csum(csum, tx->tx_iov[i].iov_base,
-                                             tx->tx_iov[i].iov_len);
-        }
+               kunmap(tx->tx_kiov[i].bv_page);
+       }
 
         if (*ksocknal_tunables.ksnd_inject_csum_error) {
                 csum++;
@@ -419,162 +404,132 @@ 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)
 {
-        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);
 
-        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;
-
-        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);
-        }
+       /* snapshot tunables */
+       keep_idle  = *ksocknal_tunables.ksnd_keepalive_idle;
+       keep_count = *ksocknal_tunables.ksnd_keepalive_count;
+       keep_intvl = *ksocknal_tunables.ksnd_keepalive_intvl;
 
-        if (!do_keepalive)
-                return (0);
+       do_keepalive = (keep_idle > 0 && keep_count > 0 && keep_intvl > 0);
 
-       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);
-        }
+#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_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_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_KEEPCNT,
-                              (char *)&keep_count, sizeof(keep_count));
-        if (rc != 0) {
-                CERROR ("Can't set TCP_KEEPCNT: %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;
+       }
 
-        return (0);
+       return (0);
 }
 
 void
@@ -583,30 +538,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);