SUNRPC: Refactor recvfrom path dealing with incomplete TCP receives
authorChuck Lever <chuck.lever@oracle.com>
Wed, 20 May 2020 16:29:13 +0000 (12:29 -0400)
committerChuck Lever <chuck.lever@oracle.com>
Wed, 20 May 2020 19:43:35 +0000 (15:43 -0400)
Clean up: move exception processing out of the main path.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
include/trace/events/sunrpc.h
net/sunrpc/svcsock.c

index bfea554..8165987 100644 (file)
@@ -1503,9 +1503,40 @@ DECLARE_EVENT_CLASS(svcsock_class,
 DEFINE_SVCSOCK_EVENT(udp_send);
 DEFINE_SVCSOCK_EVENT(tcp_send);
 DEFINE_SVCSOCK_EVENT(tcp_recv);
+DEFINE_SVCSOCK_EVENT(tcp_recv_eagain);
+DEFINE_SVCSOCK_EVENT(tcp_recv_err);
 DEFINE_SVCSOCK_EVENT(data_ready);
 DEFINE_SVCSOCK_EVENT(write_space);
 
+TRACE_EVENT(svcsock_tcp_recv_short,
+       TP_PROTO(
+               const struct svc_xprt *xprt,
+               u32 expected,
+               u32 received
+       ),
+
+       TP_ARGS(xprt, expected, received),
+
+       TP_STRUCT__entry(
+               __field(u32, expected)
+               __field(u32, received)
+               __field(unsigned long, flags)
+               __string(addr, xprt->xpt_remotebuf)
+       ),
+
+       TP_fast_assign(
+               __entry->expected = expected;
+               __entry->received = received;
+               __entry->flags = xprt->xpt_flags;
+               __assign_str(addr, xprt->xpt_remotebuf);
+       ),
+
+       TP_printk("addr=%s flags=%s expected=%u received=%u",
+               __get_str(addr), show_svc_xprt_flags(__entry->flags),
+               __entry->expected, __entry->received
+       )
+);
+
 TRACE_EVENT(svcsock_tcp_state,
        TP_PROTO(
                const struct svc_xprt *xprt,
index 8cf06b6..087e21b 100644 (file)
@@ -968,23 +968,10 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
                svsk->sk_tcplen += len;
                svsk->sk_datalen += len;
        }
-       if (len != want || !svc_sock_final_rec(svsk)) {
-               svc_tcp_save_pages(svsk, rqstp);
-               if (len < 0 && len != -EAGAIN)
-                       goto err_delete;
-               if (len == want)
-                       svc_tcp_fragment_received(svsk);
-               else
-                       dprintk("svc: incomplete TCP record (%d of %d)\n",
-                               (int)(svsk->sk_tcplen - sizeof(rpc_fraghdr)),
-                               svc_sock_reclen(svsk));
-               goto err_noclose;
-       }
-
-       if (svsk->sk_datalen < 8) {
-               svsk->sk_datalen = 0;
-               goto err_delete; /* client is nuts. */
-       }
+       if (len != want || !svc_sock_final_rec(svsk))
+               goto err_incomplete;
+       if (svsk->sk_datalen < 8)
+               goto err_nuts;
 
        rqstp->rq_arg.len = svsk->sk_datalen;
        rqstp->rq_arg.page_base = 0;
@@ -1019,14 +1006,26 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
 
        return rqstp->rq_arg.len;
 
+err_incomplete:
+       svc_tcp_save_pages(svsk, rqstp);
+       if (len < 0 && len != -EAGAIN)
+               goto err_delete;
+       if (len == want)
+               svc_tcp_fragment_received(svsk);
+       else
+               trace_svcsock_tcp_recv_short(&svsk->sk_xprt,
+                               svc_sock_reclen(svsk),
+                               svsk->sk_tcplen - sizeof(rpc_fraghdr));
+       goto err_noclose;
 error:
        if (len != -EAGAIN)
                goto err_delete;
-       dprintk("RPC: TCP recvfrom got EAGAIN\n");
+       trace_svcsock_tcp_recv_eagain(&svsk->sk_xprt, 0);
        return 0;
+err_nuts:
+       svsk->sk_datalen = 0;
 err_delete:
-       printk(KERN_NOTICE "%s: recvfrom returned errno %d\n",
-              svsk->sk_xprt.xpt_server->sv_name, -len);
+       trace_svcsock_tcp_recv_err(&svsk->sk_xprt, len);
        set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
 err_noclose:
        return 0;       /* record not complete */