aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc/xprtsock.c
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2008-10-28 15:21:39 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2008-10-28 15:21:39 -0400
commit2a9e1cfa23fb62da37739af81127dab5af095d99 (patch)
tree3fdb86f69ea598163f7096e1f85fd8f5c86bb896 /net/sunrpc/xprtsock.c
parente946217e4fdaa67681bbabfa8e6b18641921f750 (diff)
SUNRPC: Respond promptly to server TCP resets
If the server sends us an RST error while we're in the TCP_ESTABLISHED state, then that will not result in a state change, and so the RPC client ends up hanging forever (see http://bugzilla.kernel.org/show_bug.cgi?id=11154) We can intercept the reset by setting up an sk->sk_error_report callback, which will then allow us to initiate a proper shutdown and retry... We also make sure that if the send request receives an ECONNRESET, then we shutdown too... Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/xprtsock.c')
-rw-r--r--net/sunrpc/xprtsock.c58
1 files changed, 48 insertions, 10 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 9a288d5eea64..0a50361e3d83 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -249,6 +249,7 @@ struct sock_xprt {
249 void (*old_data_ready)(struct sock *, int); 249 void (*old_data_ready)(struct sock *, int);
250 void (*old_state_change)(struct sock *); 250 void (*old_state_change)(struct sock *);
251 void (*old_write_space)(struct sock *); 251 void (*old_write_space)(struct sock *);
252 void (*old_error_report)(struct sock *);
252}; 253};
253 254
254/* 255/*
@@ -698,8 +699,9 @@ static int xs_tcp_send_request(struct rpc_task *task)
698 case -EAGAIN: 699 case -EAGAIN:
699 xs_nospace(task); 700 xs_nospace(task);
700 break; 701 break;
701 case -ECONNREFUSED:
702 case -ECONNRESET: 702 case -ECONNRESET:
703 xs_tcp_shutdown(xprt);
704 case -ECONNREFUSED:
703 case -ENOTCONN: 705 case -ENOTCONN:
704 case -EPIPE: 706 case -EPIPE:
705 status = -ENOTCONN; 707 status = -ENOTCONN;
@@ -742,6 +744,22 @@ out_release:
742 xprt_release_xprt(xprt, task); 744 xprt_release_xprt(xprt, task);
743} 745}
744 746
747static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk)
748{
749 transport->old_data_ready = sk->sk_data_ready;
750 transport->old_state_change = sk->sk_state_change;
751 transport->old_write_space = sk->sk_write_space;
752 transport->old_error_report = sk->sk_error_report;
753}
754
755static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk)
756{
757 sk->sk_data_ready = transport->old_data_ready;
758 sk->sk_state_change = transport->old_state_change;
759 sk->sk_write_space = transport->old_write_space;
760 sk->sk_error_report = transport->old_error_report;
761}
762
745/** 763/**
746 * xs_close - close a socket 764 * xs_close - close a socket
747 * @xprt: transport 765 * @xprt: transport
@@ -765,9 +783,8 @@ static void xs_close(struct rpc_xprt *xprt)
765 transport->sock = NULL; 783 transport->sock = NULL;
766 784
767 sk->sk_user_data = NULL; 785 sk->sk_user_data = NULL;
768 sk->sk_data_ready = transport->old_data_ready; 786
769 sk->sk_state_change = transport->old_state_change; 787 xs_restore_old_callbacks(transport, sk);
770 sk->sk_write_space = transport->old_write_space;
771 write_unlock_bh(&sk->sk_callback_lock); 788 write_unlock_bh(&sk->sk_callback_lock);
772 789
773 sk->sk_no_check = 0; 790 sk->sk_no_check = 0;
@@ -1180,6 +1197,28 @@ static void xs_tcp_state_change(struct sock *sk)
1180} 1197}
1181 1198
1182/** 1199/**
1200 * xs_tcp_error_report - callback mainly for catching RST events
1201 * @sk: socket
1202 */
1203static void xs_tcp_error_report(struct sock *sk)
1204{
1205 struct rpc_xprt *xprt;
1206
1207 read_lock(&sk->sk_callback_lock);
1208 if (sk->sk_err != ECONNRESET || sk->sk_state != TCP_ESTABLISHED)
1209 goto out;
1210 if (!(xprt = xprt_from_sock(sk)))
1211 goto out;
1212 dprintk("RPC: %s client %p...\n"
1213 "RPC: error %d\n",
1214 __func__, xprt, sk->sk_err);
1215
1216 xprt_force_disconnect(xprt);
1217out:
1218 read_unlock(&sk->sk_callback_lock);
1219}
1220
1221/**
1183 * xs_udp_write_space - callback invoked when socket buffer space 1222 * xs_udp_write_space - callback invoked when socket buffer space
1184 * becomes available 1223 * becomes available
1185 * @sk: socket whose state has changed 1224 * @sk: socket whose state has changed
@@ -1454,10 +1493,9 @@ static void xs_udp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
1454 1493
1455 write_lock_bh(&sk->sk_callback_lock); 1494 write_lock_bh(&sk->sk_callback_lock);
1456 1495
1496 xs_save_old_callbacks(transport, sk);
1497
1457 sk->sk_user_data = xprt; 1498 sk->sk_user_data = xprt;
1458 transport->old_data_ready = sk->sk_data_ready;
1459 transport->old_state_change = sk->sk_state_change;
1460 transport->old_write_space = sk->sk_write_space;
1461 sk->sk_data_ready = xs_udp_data_ready; 1499 sk->sk_data_ready = xs_udp_data_ready;
1462 sk->sk_write_space = xs_udp_write_space; 1500 sk->sk_write_space = xs_udp_write_space;
1463 sk->sk_no_check = UDP_CSUM_NORCV; 1501 sk->sk_no_check = UDP_CSUM_NORCV;
@@ -1589,13 +1627,13 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock)
1589 1627
1590 write_lock_bh(&sk->sk_callback_lock); 1628 write_lock_bh(&sk->sk_callback_lock);
1591 1629
1630 xs_save_old_callbacks(transport, sk);
1631
1592 sk->sk_user_data = xprt; 1632 sk->sk_user_data = xprt;
1593 transport->old_data_ready = sk->sk_data_ready;
1594 transport->old_state_change = sk->sk_state_change;
1595 transport->old_write_space = sk->sk_write_space;
1596 sk->sk_data_ready = xs_tcp_data_ready; 1633 sk->sk_data_ready = xs_tcp_data_ready;
1597 sk->sk_state_change = xs_tcp_state_change; 1634 sk->sk_state_change = xs_tcp_state_change;
1598 sk->sk_write_space = xs_tcp_write_space; 1635 sk->sk_write_space = xs_tcp_write_space;
1636 sk->sk_error_report = xs_tcp_error_report;
1599 sk->sk_allocation = GFP_ATOMIC; 1637 sk->sk_allocation = GFP_ATOMIC;
1600 1638
1601 /* socket options */ 1639 /* socket options */