The following is a backport of SUNRPC fix for a NFS hang (Kernel Bug
16494) and related fixes for SYN_SENT state handling and
proper clearing of the srcport field in the SUNRPC transport.

Signed-off-by: Peter Holland <[email protected]>

---
--- /dev/null   Thu Jan 01 00:00:00 1970 +0000
+++ 
b/target/linux/generic-2.6/patches-2.6.32/983-backport_sunrpc_nfs_hang_fixes.patch
  Mon
Dec 12 13:33:36 2011 -0800
@@ -0,0 +1,95 @@
+--- linux-2.6.32.27/net/sunrpc/xprtsock.c      2010-12-09 13:29:45.000000000 
-0800
++++ linux-2.6.32.27-new/net/sunrpc/xprtsock.c  2011-12-12
11:00:37.000000000 -0800
+@@ -743,6 +743,8 @@
+       if (sk == NULL)
+               return;
+
++        transport->srcport = 0;
++
+       write_lock_bh(&sk->sk_callback_lock);
+       transport->inet = NULL;
+       transport->sock = NULL;
+@@ -1341,10 +1343,11 @@
+       if (!(xprt = xprt_from_sock(sk)))
+               goto out;
+       dprintk("RPC:       xs_tcp_state_change client %p...\n", xprt);
+-      dprintk("RPC:       state %x conn %d dead %d zapped %d\n",
++      dprintk("RPC:       state %x conn %d dead %d zapped %d sk_shutdown 
%d\n",
+                       sk->sk_state, xprt_connected(xprt),
+                       sock_flag(sk, SOCK_DEAD),
+-                      sock_flag(sk, SOCK_ZAPPED));
++                        sock_flag(sk, SOCK_ZAPPED),
++                        sk->sk_shutdown);
+
+       switch (sk->sk_state) {
+       case TCP_ESTABLISHED:
+@@ -1378,7 +1381,6 @@
+       case TCP_CLOSE_WAIT:
+               /* The server initiated a shutdown of the socket */
+               xprt_force_disconnect(xprt);
+-      case TCP_SYN_SENT:
+               xprt->connect_cookie++;
+ {
+       unsigned int state = transport->inet->sk_state;
+
+-      if (state == TCP_CLOSE && transport->sock->state == SS_UNCONNECTED)
+-              return;
+-      if ((1 << state) & (TCPF_ESTABLISHED|TCPF_SYN_SENT))
+-              return;
++        if (state == TCP_CLOSE && transport->sock->state == SS_UNCONNECTED) {
++            /* we don't need to abort the connection if the socket
++             * hasn't undergone a shutdown
++             */
++            if (transport->inet->sk_shutdown == 0)
++                return;
++            dprintk("RPC:       %s: TCP_CLOSEd and sk_shutdown set to %d\n",
++                    __func__, transport->inet->sk_shutdown);
++        }
++        if ((1 << state) & (TCPF_ESTABLISHED|TCPF_SYN_SENT)) {
++            /* we don't need to abort the connection if the socket
++             * hasn't undergone a shutdown
++             */
++            if (transport->inet->sk_shutdown == 0)
++                return;
++            dprintk("RPC:       %s: ESTABLISHED/SYN_SENT "
++                    "sk_shutdown set to %d\n",
++                    __func__, transport->inet->sk_shutdown);
++        }
+       xs_abort_connection(xprt, transport);
+ }
+
+ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct
socket *sock)
+ {
+       struct sock_xprt *transport = container_of(xprt, struct sock_xprt, 
xprt);
++        int ret = -ENOTCONN;
+
+       if (!transport->inet) {
+               struct sock *sk = sock->sk;
+@@ -1856,12 +1874,22 @@
+       }
+
+       if (!xprt_bound(xprt))
+-              return -ENOTCONN;
++                goto out;
+
+       /* Tell the socket layer to start connecting... */
+       xprt->stat.connect_count++;
+       xprt->stat.connect_start = jiffies;
+-      return kernel_connect(sock, xs_addr(xprt), xprt->addrlen, O_NONBLOCK);
++        ret = kernel_connect(sock, xs_addr(xprt), xprt->addrlen, O_NONBLOCK);
++        switch (ret) {
++        case 0:
++        case -EINPROGRESS:
++                /* SYN_SENT! */
++                xprt->connect_cookie++;
++                if (xprt->reestablish_timeout < XS_TCP_INIT_REEST_TO)
++                        xprt->reestablish_timeout = XS_TCP_INIT_REEST_TO;
++        }
++out:
++        return ret;
+ }
+
+ /**
_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to