diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-09-04 12:16:23 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2013-09-04 12:26:31 -0400 |
commit | 40b5ea0c25669cb99ba7f4836437a7ebaba91408 (patch) | |
tree | 756eab3cf0403304bf922472308676e7396dc2c1 | |
parent | b6a85258d8223a87e7ecf25791e634617a159f79 (diff) |
SUNRPC: Add tracepoints to help debug socket connection issues
Add client side debugging to help trace socket connection/disconnection
and unexpected state change issues.
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r-- | include/trace/events/sunrpc.h | 131 | ||||
-rw-r--r-- | net/sunrpc/xprtsock.c | 13 |
2 files changed, 143 insertions, 1 deletions
diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h index 43be87d5dd58..b74a8acd38fa 100644 --- a/include/trace/events/sunrpc.h +++ b/include/trace/events/sunrpc.h | |||
@@ -6,6 +6,8 @@ | |||
6 | 6 | ||
7 | #include <linux/sunrpc/sched.h> | 7 | #include <linux/sunrpc/sched.h> |
8 | #include <linux/sunrpc/clnt.h> | 8 | #include <linux/sunrpc/clnt.h> |
9 | #include <net/tcp_states.h> | ||
10 | #include <linux/net.h> | ||
9 | #include <linux/tracepoint.h> | 11 | #include <linux/tracepoint.h> |
10 | 12 | ||
11 | DECLARE_EVENT_CLASS(rpc_task_status, | 13 | DECLARE_EVENT_CLASS(rpc_task_status, |
@@ -172,6 +174,135 @@ DEFINE_EVENT(rpc_task_queued, rpc_task_wakeup, | |||
172 | 174 | ||
173 | ); | 175 | ); |
174 | 176 | ||
177 | #define rpc_show_socket_state(state) \ | ||
178 | __print_symbolic(state, \ | ||
179 | { SS_FREE, "FREE" }, \ | ||
180 | { SS_UNCONNECTED, "UNCONNECTED" }, \ | ||
181 | { SS_CONNECTING, "CONNECTING," }, \ | ||
182 | { SS_CONNECTED, "CONNECTED," }, \ | ||
183 | { SS_DISCONNECTING, "DISCONNECTING" }) | ||
184 | |||
185 | #define rpc_show_sock_state(state) \ | ||
186 | __print_symbolic(state, \ | ||
187 | { TCP_ESTABLISHED, "ESTABLISHED" }, \ | ||
188 | { TCP_SYN_SENT, "SYN_SENT" }, \ | ||
189 | { TCP_SYN_RECV, "SYN_RECV" }, \ | ||
190 | { TCP_FIN_WAIT1, "FIN_WAIT1" }, \ | ||
191 | { TCP_FIN_WAIT2, "FIN_WAIT2" }, \ | ||
192 | { TCP_TIME_WAIT, "TIME_WAIT" }, \ | ||
193 | { TCP_CLOSE, "CLOSE" }, \ | ||
194 | { TCP_CLOSE_WAIT, "CLOSE_WAIT" }, \ | ||
195 | { TCP_LAST_ACK, "LAST_ACK" }, \ | ||
196 | { TCP_LISTEN, "LISTEN" }, \ | ||
197 | { TCP_CLOSING, "CLOSING" }) | ||
198 | |||
199 | DECLARE_EVENT_CLASS(xs_socket_event, | ||
200 | |||
201 | TP_PROTO( | ||
202 | struct rpc_xprt *xprt, | ||
203 | struct socket *socket | ||
204 | ), | ||
205 | |||
206 | TP_ARGS(xprt, socket), | ||
207 | |||
208 | TP_STRUCT__entry( | ||
209 | __field(unsigned int, socket_state) | ||
210 | __field(unsigned int, sock_state) | ||
211 | __field(unsigned long long, ino) | ||
212 | __string(dstaddr, | ||
213 | xprt->address_strings[RPC_DISPLAY_ADDR]) | ||
214 | __string(dstport, | ||
215 | xprt->address_strings[RPC_DISPLAY_PORT]) | ||
216 | ), | ||
217 | |||
218 | TP_fast_assign( | ||
219 | struct inode *inode = SOCK_INODE(socket); | ||
220 | __entry->socket_state = socket->state; | ||
221 | __entry->sock_state = socket->sk->sk_state; | ||
222 | __entry->ino = (unsigned long long)inode->i_ino; | ||
223 | __assign_str(dstaddr, | ||
224 | xprt->address_strings[RPC_DISPLAY_ADDR]); | ||
225 | __assign_str(dstport, | ||
226 | xprt->address_strings[RPC_DISPLAY_PORT]); | ||
227 | ), | ||
228 | |||
229 | TP_printk( | ||
230 | "socket:[%llu] dstaddr=%s/%s " | ||
231 | "state=%u (%s) sk_state=%u (%s)", | ||
232 | __entry->ino, __get_str(dstaddr), __get_str(dstport), | ||
233 | __entry->socket_state, | ||
234 | rpc_show_socket_state(__entry->socket_state), | ||
235 | __entry->sock_state, | ||
236 | rpc_show_sock_state(__entry->sock_state) | ||
237 | ) | ||
238 | ); | ||
239 | #define DEFINE_RPC_SOCKET_EVENT(name) \ | ||
240 | DEFINE_EVENT(xs_socket_event, name, \ | ||
241 | TP_PROTO( \ | ||
242 | struct rpc_xprt *xprt, \ | ||
243 | struct socket *socket \ | ||
244 | ), \ | ||
245 | TP_ARGS(xprt, socket)) | ||
246 | |||
247 | DECLARE_EVENT_CLASS(xs_socket_event_done, | ||
248 | |||
249 | TP_PROTO( | ||
250 | struct rpc_xprt *xprt, | ||
251 | struct socket *socket, | ||
252 | int error | ||
253 | ), | ||
254 | |||
255 | TP_ARGS(xprt, socket, error), | ||
256 | |||
257 | TP_STRUCT__entry( | ||
258 | __field(int, error) | ||
259 | __field(unsigned int, socket_state) | ||
260 | __field(unsigned int, sock_state) | ||
261 | __field(unsigned long long, ino) | ||
262 | __string(dstaddr, | ||
263 | xprt->address_strings[RPC_DISPLAY_ADDR]) | ||
264 | __string(dstport, | ||
265 | xprt->address_strings[RPC_DISPLAY_PORT]) | ||
266 | ), | ||
267 | |||
268 | TP_fast_assign( | ||
269 | struct inode *inode = SOCK_INODE(socket); | ||
270 | __entry->socket_state = socket->state; | ||
271 | __entry->sock_state = socket->sk->sk_state; | ||
272 | __entry->ino = (unsigned long long)inode->i_ino; | ||
273 | __entry->error = error; | ||
274 | __assign_str(dstaddr, | ||
275 | xprt->address_strings[RPC_DISPLAY_ADDR]); | ||
276 | __assign_str(dstport, | ||
277 | xprt->address_strings[RPC_DISPLAY_PORT]); | ||
278 | ), | ||
279 | |||
280 | TP_printk( | ||
281 | "error=%d socket:[%llu] dstaddr=%s/%s " | ||
282 | "state=%u (%s) sk_state=%u (%s)", | ||
283 | __entry->error, | ||
284 | __entry->ino, __get_str(dstaddr), __get_str(dstport), | ||
285 | __entry->socket_state, | ||
286 | rpc_show_socket_state(__entry->socket_state), | ||
287 | __entry->sock_state, | ||
288 | rpc_show_sock_state(__entry->sock_state) | ||
289 | ) | ||
290 | ); | ||
291 | #define DEFINE_RPC_SOCKET_EVENT_DONE(name) \ | ||
292 | DEFINE_EVENT(xs_socket_event_done, name, \ | ||
293 | TP_PROTO( \ | ||
294 | struct rpc_xprt *xprt, \ | ||
295 | struct socket *socket, \ | ||
296 | int error \ | ||
297 | ), \ | ||
298 | TP_ARGS(xprt, socket, error)) | ||
299 | |||
300 | DEFINE_RPC_SOCKET_EVENT(rpc_socket_state_change); | ||
301 | DEFINE_RPC_SOCKET_EVENT_DONE(rpc_socket_connect); | ||
302 | DEFINE_RPC_SOCKET_EVENT_DONE(rpc_socket_reset_connection); | ||
303 | DEFINE_RPC_SOCKET_EVENT(rpc_socket_close); | ||
304 | DEFINE_RPC_SOCKET_EVENT(rpc_socket_shutdown); | ||
305 | |||
175 | #endif /* _TRACE_SUNRPC_H */ | 306 | #endif /* _TRACE_SUNRPC_H */ |
176 | 307 | ||
177 | #include <trace/define_trace.h> | 308 | #include <trace/define_trace.h> |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index ddf0602603bd..b98bce5461b5 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -47,6 +47,8 @@ | |||
47 | #include <net/udp.h> | 47 | #include <net/udp.h> |
48 | #include <net/tcp.h> | 48 | #include <net/tcp.h> |
49 | 49 | ||
50 | #include <trace/events/sunrpc.h> | ||
51 | |||
50 | #include "sunrpc.h" | 52 | #include "sunrpc.h" |
51 | 53 | ||
52 | static void xs_close(struct rpc_xprt *xprt); | 54 | static void xs_close(struct rpc_xprt *xprt); |
@@ -665,8 +667,10 @@ static void xs_tcp_shutdown(struct rpc_xprt *xprt) | |||
665 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); | 667 | struct sock_xprt *transport = container_of(xprt, struct sock_xprt, xprt); |
666 | struct socket *sock = transport->sock; | 668 | struct socket *sock = transport->sock; |
667 | 669 | ||
668 | if (sock != NULL) | 670 | if (sock != NULL) { |
669 | kernel_sock_shutdown(sock, SHUT_WR); | 671 | kernel_sock_shutdown(sock, SHUT_WR); |
672 | trace_rpc_socket_shutdown(xprt, sock); | ||
673 | } | ||
670 | } | 674 | } |
671 | 675 | ||
672 | /** | 676 | /** |
@@ -811,6 +815,7 @@ static void xs_reset_transport(struct sock_xprt *transport) | |||
811 | 815 | ||
812 | sk->sk_no_check = 0; | 816 | sk->sk_no_check = 0; |
813 | 817 | ||
818 | trace_rpc_socket_close(&transport->xprt, sock); | ||
814 | sock_release(sock); | 819 | sock_release(sock); |
815 | } | 820 | } |
816 | 821 | ||
@@ -1492,6 +1497,7 @@ static void xs_tcp_state_change(struct sock *sk) | |||
1492 | sock_flag(sk, SOCK_ZAPPED), | 1497 | sock_flag(sk, SOCK_ZAPPED), |
1493 | sk->sk_shutdown); | 1498 | sk->sk_shutdown); |
1494 | 1499 | ||
1500 | trace_rpc_socket_state_change(xprt, sk->sk_socket); | ||
1495 | switch (sk->sk_state) { | 1501 | switch (sk->sk_state) { |
1496 | case TCP_ESTABLISHED: | 1502 | case TCP_ESTABLISHED: |
1497 | spin_lock(&xprt->transport_lock); | 1503 | spin_lock(&xprt->transport_lock); |
@@ -1896,6 +1902,7 @@ static int xs_local_setup_socket(struct sock_xprt *transport) | |||
1896 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); | 1902 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); |
1897 | 1903 | ||
1898 | status = xs_local_finish_connecting(xprt, sock); | 1904 | status = xs_local_finish_connecting(xprt, sock); |
1905 | trace_rpc_socket_connect(xprt, sock, status); | ||
1899 | switch (status) { | 1906 | switch (status) { |
1900 | case 0: | 1907 | case 0: |
1901 | dprintk("RPC: xprt %p connected to %s\n", | 1908 | dprintk("RPC: xprt %p connected to %s\n", |
@@ -2039,6 +2046,7 @@ static void xs_udp_setup_socket(struct work_struct *work) | |||
2039 | xprt->address_strings[RPC_DISPLAY_PORT]); | 2046 | xprt->address_strings[RPC_DISPLAY_PORT]); |
2040 | 2047 | ||
2041 | xs_udp_finish_connecting(xprt, sock); | 2048 | xs_udp_finish_connecting(xprt, sock); |
2049 | trace_rpc_socket_connect(xprt, sock, 0); | ||
2042 | status = 0; | 2050 | status = 0; |
2043 | out: | 2051 | out: |
2044 | xprt_clear_connecting(xprt); | 2052 | xprt_clear_connecting(xprt); |
@@ -2064,6 +2072,8 @@ static void xs_abort_connection(struct sock_xprt *transport) | |||
2064 | memset(&any, 0, sizeof(any)); | 2072 | memset(&any, 0, sizeof(any)); |
2065 | any.sa_family = AF_UNSPEC; | 2073 | any.sa_family = AF_UNSPEC; |
2066 | result = kernel_connect(transport->sock, &any, sizeof(any), 0); | 2074 | result = kernel_connect(transport->sock, &any, sizeof(any), 0); |
2075 | trace_rpc_socket_reset_connection(&transport->xprt, | ||
2076 | transport->sock, result); | ||
2067 | if (!result) | 2077 | if (!result) |
2068 | xs_sock_reset_connection_flags(&transport->xprt); | 2078 | xs_sock_reset_connection_flags(&transport->xprt); |
2069 | dprintk("RPC: AF_UNSPEC connect return code %d\n", result); | 2079 | dprintk("RPC: AF_UNSPEC connect return code %d\n", result); |
@@ -2194,6 +2204,7 @@ static void xs_tcp_setup_socket(struct work_struct *work) | |||
2194 | xprt->address_strings[RPC_DISPLAY_PORT]); | 2204 | xprt->address_strings[RPC_DISPLAY_PORT]); |
2195 | 2205 | ||
2196 | status = xs_tcp_finish_connecting(xprt, sock); | 2206 | status = xs_tcp_finish_connecting(xprt, sock); |
2207 | trace_rpc_socket_connect(xprt, sock, status); | ||
2197 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", | 2208 | dprintk("RPC: %p connect status %d connected %d sock state %d\n", |
2198 | xprt, -status, xprt_connected(xprt), | 2209 | xprt, -status, xprt_connected(xprt), |
2199 | sock->sk->sk_state); | 2210 | sock->sk->sk_state); |