From 677e4bc4f08609a02ec1bcd28e6f2ef589228f2c Mon Sep 17 00:00:00 2001
From: liangzhen <liangzhen>
Date: Thu, 6 Sep 2007 05:27:45 +0000
Subject: [PATCH] Branch HEAD Fix for TOE Kernel panic by ksocklnd b=13246
 i=eeb

---
 lnet/ChangeLog                         |  6 ++++++
 lnet/klnds/socklnd/socklnd_lib-linux.c | 17 +++++++++++++----
 lnet/libcfs/linux/linux-tcpip.c        | 26 +++++++++++---------------
 3 files changed, 30 insertions(+), 19 deletions(-)

diff --git a/lnet/ChangeLog b/lnet/ChangeLog
index 703d3b2995..d10a02c07c 100644
--- a/lnet/ChangeLog
+++ b/lnet/ChangeLog
@@ -12,6 +12,12 @@
 	mxlnd     - MX 1.2.1 or later,
 	ptllnd    - Portals 3.3 / UNICOS/lc 1.5.x, 2.0.x
 
+Severity   : major
+Bugzilla   : 13236
+Description: TOE Kernel panic by ksocklnd
+Details    : offloaded sockets provide their own implementation of sendpage,
+             can't call tcp_sendpage() directly
+
 Severity   : normal
 Bugzilla   : 10778
 Description: kibnal_shutdown() doesn't finish; lconf --cleanup hangs
diff --git a/lnet/klnds/socklnd/socklnd_lib-linux.c b/lnet/klnds/socklnd/socklnd_lib-linux.c
index e702476ae6..d4d12b77af 100644
--- a/lnet/klnds/socklnd/socklnd_lib-linux.c
+++ b/lnet/klnds/socklnd/socklnd_lib-linux.c
@@ -191,8 +191,10 @@ ksocknal_lib_tunables_init ()
                 .proc_handler = &proc_dointvec
         };
 #endif
-        LASSERT (j == i+1);
-        LASSERT (i < sizeof(ksocknal_ctl_table)/sizeof(ksocknal_ctl_table[0]));
+        ksocknal_ctl_table[i++] =  (cfs_sysctl_table_t) { 0 };
+
+        LASSERT (j == i);
+        LASSERT (i <= sizeof(ksocknal_ctl_table)/sizeof(ksocknal_ctl_table[0]));
 
         ksocknal_tunables.ksnd_sysctl =
                 cfs_register_sysctl_table(ksocknal_top_ctl_table, 0);
@@ -398,6 +400,7 @@ ksocknal_lib_send_kiov (ksock_conn_t *conn, ksock_tx_t *tx)
         if (kiov->kiov_len >= *ksocknal_tunables.ksnd_zc_min_frag &&
             tx->tx_msg.ksm_zc_req_cookie != 0) {
                 /* Zero copy is enabled */
+                struct sock   *sk = sock->sk;
                 struct page   *page = kiov->kiov_page;
                 int            offset = kiov->kiov_offset;
                 int            fragsize = kiov->kiov_len;
@@ -410,7 +413,12 @@ ksocknal_lib_send_kiov (ksock_conn_t *conn, ksock_tx_t *tx)
                     fragsize < tx->tx_resid)
                         msgflg |= MSG_MORE;
 
-                rc = tcp_sendpage(sock, page, offset, fragsize, msgflg);
+                if (sk->sk_prot->sendpage != NULL) {
+                        rc = sk->sk_prot->sendpage(sk, page,
+                                                   offset, fragsize, msgflg);
+                } else {
+                        rc = tcp_sendpage(sock, page, offset, fragsize, msgflg);
+                }
         } else {
 #if SOCKNAL_SINGLE_FRAG_TX || !SOCKNAL_RISK_KMAP_DEADLOCK
                 struct iovec  scratch;
@@ -611,7 +619,8 @@ ksocknal_lib_recv_kiov (ksock_conn_t *conn)
         return (rc);
 }
 
-void ksocknal_lib_csum_tx(ksock_tx_t *tx)
+void
+ksocknal_lib_csum_tx(ksock_tx_t *tx)
 {
         int          i;
         __u32        csum;
diff --git a/lnet/libcfs/linux/linux-tcpip.c b/lnet/libcfs/linux/linux-tcpip.c
index 9cb85efa13..e8ceafd7bb 100644
--- a/lnet/libcfs/linux/linux-tcpip.c
+++ b/lnet/libcfs/linux/linux-tcpip.c
@@ -94,8 +94,7 @@ libcfs_ipif_query (char *name, int *up, __u32 *ip, __u32 *mask)
         nob = strnlen(name, IFNAMSIZ);
         if (nob == IFNAMSIZ) {
                 CERROR("Interface name %s too long\n", name);
-                rc = -EINVAL;
-                goto out;
+                return -EINVAL;
         }
 
         CLASSERT (sizeof(ifr.ifr_name) >= IFNAMSIZ);
@@ -105,14 +104,14 @@ libcfs_ipif_query (char *name, int *up, __u32 *ip, __u32 *mask)
 
         if (rc != 0) {
                 CERROR("Can't get flags for interface %s\n", name);
-                goto out;
+                return rc;
         }
 
         if ((ifr.ifr_flags & IFF_UP) == 0) {
                 CDEBUG(D_NET, "Interface %s down\n", name);
                 *up = 0;
                 *ip = *mask = 0;
-                goto out;
+                return 0;
         }
 
         *up = 1;
@@ -123,7 +122,7 @@ libcfs_ipif_query (char *name, int *up, __u32 *ip, __u32 *mask)
 
         if (rc != 0) {
                 CERROR("Can't get IP address for interface %s\n", name);
-                goto out;
+                return rc;
         }
 
         val = ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
@@ -135,14 +134,13 @@ libcfs_ipif_query (char *name, int *up, __u32 *ip, __u32 *mask)
 
         if (rc != 0) {
                 CERROR("Can't get netmask for interface %s\n", name);
-                goto out;
+                return rc;
         }
 
         val = ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr;
         *mask = ntohl(val);
 
- out:
-        return rc;
+        return 0;
 }
 
 EXPORT_SYMBOL(libcfs_ipif_query);
@@ -571,18 +569,16 @@ EXPORT_SYMBOL(libcfs_sock_listen);
 #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,12)
 int sock_create_lite(int family, int type, int protocol, struct socket **res)
 {
-        int err = 0;
         struct socket *sock;
 
         sock = sock_alloc();
-        if (!sock) {
-                err = -ENOMEM;
-                goto out;
-        }
+        if (sock == NULL) 
+                return -ENOMEM;
+
         sock->type = type;
-out:
         *res = sock;
-        return err;
+
+        return 0;
 }
 #endif
 
-- 
GitLab