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
