diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2013-12-31 13:22:59 -0500 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2013-12-31 14:01:54 -0500 |
commit | 2118071d3b0d57a03fad77885f4fdc364798aa87 (patch) | |
tree | fe39bd6cceeccf9072518bff2a7f1f0d205371bd /net | |
parent | df2772700c6ee706be7b2fd16c6bf2c1bf63cda0 (diff) |
SUNRPC: Report connection error values to rpc_tasks on the pending queue
Currently we only report EAGAIN, which is not descriptive enough for
softconn tasks.
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/xprtsock.c | 41 |
1 files changed, 36 insertions, 5 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index dd9d295813cf..ab006b7b7ab8 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -257,6 +257,7 @@ struct sock_xprt { | |||
257 | void (*old_data_ready)(struct sock *, int); | 257 | void (*old_data_ready)(struct sock *, int); |
258 | void (*old_state_change)(struct sock *); | 258 | void (*old_state_change)(struct sock *); |
259 | void (*old_write_space)(struct sock *); | 259 | void (*old_write_space)(struct sock *); |
260 | void (*old_error_report)(struct sock *); | ||
260 | }; | 261 | }; |
261 | 262 | ||
262 | /* | 263 | /* |
@@ -274,6 +275,11 @@ struct sock_xprt { | |||
274 | */ | 275 | */ |
275 | #define TCP_RPC_REPLY (1UL << 6) | 276 | #define TCP_RPC_REPLY (1UL << 6) |
276 | 277 | ||
278 | static inline struct rpc_xprt *xprt_from_sock(struct sock *sk) | ||
279 | { | ||
280 | return (struct rpc_xprt *) sk->sk_user_data; | ||
281 | } | ||
282 | |||
277 | static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt) | 283 | static inline struct sockaddr *xs_addr(struct rpc_xprt *xprt) |
278 | { | 284 | { |
279 | return (struct sockaddr *) &xprt->addr; | 285 | return (struct sockaddr *) &xprt->addr; |
@@ -799,6 +805,7 @@ static void xs_save_old_callbacks(struct sock_xprt *transport, struct sock *sk) | |||
799 | transport->old_data_ready = sk->sk_data_ready; | 805 | transport->old_data_ready = sk->sk_data_ready; |
800 | transport->old_state_change = sk->sk_state_change; | 806 | transport->old_state_change = sk->sk_state_change; |
801 | transport->old_write_space = sk->sk_write_space; | 807 | transport->old_write_space = sk->sk_write_space; |
808 | transport->old_error_report = sk->sk_error_report; | ||
802 | } | 809 | } |
803 | 810 | ||
804 | static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk) | 811 | static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *sk) |
@@ -806,6 +813,33 @@ static void xs_restore_old_callbacks(struct sock_xprt *transport, struct sock *s | |||
806 | sk->sk_data_ready = transport->old_data_ready; | 813 | sk->sk_data_ready = transport->old_data_ready; |
807 | sk->sk_state_change = transport->old_state_change; | 814 | sk->sk_state_change = transport->old_state_change; |
808 | sk->sk_write_space = transport->old_write_space; | 815 | sk->sk_write_space = transport->old_write_space; |
816 | sk->sk_error_report = transport->old_error_report; | ||
817 | } | ||
818 | |||
819 | /** | ||
820 | * xs_error_report - callback to handle TCP socket state errors | ||
821 | * @sk: socket | ||
822 | * | ||
823 | * Note: we don't call sock_error() since there may be a rpc_task | ||
824 | * using the socket, and so we don't want to clear sk->sk_err. | ||
825 | */ | ||
826 | static void xs_error_report(struct sock *sk) | ||
827 | { | ||
828 | struct rpc_xprt *xprt; | ||
829 | int err; | ||
830 | |||
831 | read_lock_bh(&sk->sk_callback_lock); | ||
832 | if (!(xprt = xprt_from_sock(sk))) | ||
833 | goto out; | ||
834 | |||
835 | err = -sk->sk_err; | ||
836 | if (err == 0) | ||
837 | goto out; | ||
838 | dprintk("RPC: xs_error_report client %p, error=%d...\n", | ||
839 | xprt, -err); | ||
840 | xprt_wake_pending_tasks(xprt, err); | ||
841 | out: | ||
842 | read_unlock_bh(&sk->sk_callback_lock); | ||
809 | } | 843 | } |
810 | 844 | ||
811 | static void xs_reset_transport(struct sock_xprt *transport) | 845 | static void xs_reset_transport(struct sock_xprt *transport) |
@@ -885,11 +919,6 @@ static void xs_destroy(struct rpc_xprt *xprt) | |||
885 | module_put(THIS_MODULE); | 919 | module_put(THIS_MODULE); |
886 | } | 920 | } |
887 | 921 | ||
888 | static inline struct rpc_xprt *xprt_from_sock(struct sock *sk) | ||
889 | { | ||
890 | return (struct rpc_xprt *) sk->sk_user_data; | ||
891 | } | ||
892 | |||
893 | static int xs_local_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb) | 922 | static int xs_local_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb) |
894 | { | 923 | { |
895 | struct xdr_skb_reader desc = { | 924 | struct xdr_skb_reader desc = { |
@@ -1869,6 +1898,7 @@ static int xs_local_finish_connecting(struct rpc_xprt *xprt, | |||
1869 | sk->sk_user_data = xprt; | 1898 | sk->sk_user_data = xprt; |
1870 | sk->sk_data_ready = xs_local_data_ready; | 1899 | sk->sk_data_ready = xs_local_data_ready; |
1871 | sk->sk_write_space = xs_udp_write_space; | 1900 | sk->sk_write_space = xs_udp_write_space; |
1901 | sk->sk_error_report = xs_error_report; | ||
1872 | sk->sk_allocation = GFP_ATOMIC; | 1902 | sk->sk_allocation = GFP_ATOMIC; |
1873 | 1903 | ||
1874 | xprt_clear_connected(xprt); | 1904 | xprt_clear_connected(xprt); |
@@ -2146,6 +2176,7 @@ static int xs_tcp_finish_connecting(struct rpc_xprt *xprt, struct socket *sock) | |||
2146 | sk->sk_data_ready = xs_tcp_data_ready; | 2176 | sk->sk_data_ready = xs_tcp_data_ready; |
2147 | sk->sk_state_change = xs_tcp_state_change; | 2177 | sk->sk_state_change = xs_tcp_state_change; |
2148 | sk->sk_write_space = xs_tcp_write_space; | 2178 | sk->sk_write_space = xs_tcp_write_space; |
2179 | sk->sk_error_report = xs_error_report; | ||
2149 | sk->sk_allocation = GFP_ATOMIC; | 2180 | sk->sk_allocation = GFP_ATOMIC; |
2150 | 2181 | ||
2151 | /* socket options */ | 2182 | /* socket options */ |