Commit a5cda73e authored by Chuck Lever's avatar Chuck Lever

SUNRPC: Restructure svc_tcp_recv_record()

Refactor: svc_recvfrom() is going to be converted to read into
bio_vecs in a moment. Unhook the only other caller,
svc_tcp_recv_record(), which just wants to read the 4-byte stream
record marker into a kvec.

While we're in the area, streamline this helper by straight-lining
the hot path, replace dprintk call sites with tracepoints, and
reduce the number of atomic bit operations in this path.
Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent 02648908
......@@ -1443,6 +1443,30 @@ TRACE_EVENT(svcsock_new_socket,
)
);
TRACE_EVENT(svcsock_marker,
TP_PROTO(
const struct svc_xprt *xprt,
__be32 marker
),
TP_ARGS(xprt, marker),
TP_STRUCT__entry(
__field(unsigned int, length)
__field(bool, last)
__string(addr, xprt->xpt_remotebuf)
),
TP_fast_assign(
__entry->length = be32_to_cpu(marker) & RPC_FRAGMENT_SIZE_MASK;
__entry->last = be32_to_cpu(marker) & RPC_LAST_STREAM_FRAGMENT;
__assign_str(addr, xprt->xpt_remotebuf);
),
TP_printk("addr=%s length=%u%s", __get_str(addr),
__entry->length, __entry->last ? " (last)" : "")
);
DECLARE_EVENT_CLASS(svcsock_class,
TP_PROTO(
const struct svc_xprt *xprt,
......
......@@ -828,47 +828,45 @@ static void svc_tcp_clear_pages(struct svc_sock *svsk)
}
/*
* Receive fragment record header.
* If we haven't gotten the record length yet, get the next four bytes.
* Receive fragment record header into sk_marker.
*/
static int svc_tcp_recv_record(struct svc_sock *svsk, struct svc_rqst *rqstp)
static ssize_t svc_tcp_read_marker(struct svc_sock *svsk,
struct svc_rqst *rqstp)
{
struct svc_serv *serv = svsk->sk_xprt.xpt_server;
unsigned int want;
int len;
ssize_t want, len;
/* If we haven't gotten the record length yet,
* get the next four bytes.
*/
if (svsk->sk_tcplen < sizeof(rpc_fraghdr)) {
struct msghdr msg = { NULL };
struct kvec iov;
want = sizeof(rpc_fraghdr) - svsk->sk_tcplen;
iov.iov_base = ((char *)&svsk->sk_marker) + svsk->sk_tcplen;
iov.iov_len = want;
len = svc_recvfrom(rqstp, &iov, 1, want, 0);
iov_iter_kvec(&msg.msg_iter, READ, &iov, 1, want);
len = sock_recvmsg(svsk->sk_sock, &msg, MSG_DONTWAIT);
if (len < 0)
goto error;
return len;
svsk->sk_tcplen += len;
if (len < want) {
dprintk("svc: short recvfrom while reading record "
"length (%d of %d)\n", len, want);
return -EAGAIN;
/* call again to read the remaining bytes */
goto err_short;
}
dprintk("svc: TCP record, %d bytes\n", svc_sock_reclen(svsk));
trace_svcsock_marker(&svsk->sk_xprt, svsk->sk_marker);
if (svc_sock_reclen(svsk) + svsk->sk_datalen >
serv->sv_max_mesg) {
net_notice_ratelimited("RPC: fragment too large: %d\n",
svc_sock_reclen(svsk));
goto err_delete;
}
svsk->sk_xprt.xpt_server->sv_max_mesg)
goto err_too_large;
}
return svc_sock_reclen(svsk);
error:
dprintk("RPC: TCP recv_record got %d\n", len);
return len;
err_delete:
err_too_large:
net_notice_ratelimited("svc: %s %s RPC fragment too large: %d\n",
__func__, svsk->sk_xprt.xpt_server->sv_name,
svc_sock_reclen(svsk));
set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
err_short:
return -EAGAIN;
}
......@@ -961,12 +959,13 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
test_bit(XPT_CONN, &svsk->sk_xprt.xpt_flags),
test_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags));
len = svc_tcp_recv_record(svsk, rqstp);
clear_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags);
len = svc_tcp_read_marker(svsk, rqstp);
if (len < 0)
goto error;
base = svc_tcp_restore_pages(svsk, rqstp);
want = svc_sock_reclen(svsk) - (svsk->sk_tcplen - sizeof(rpc_fraghdr));
want = len - (svsk->sk_tcplen - sizeof(rpc_fraghdr));
vec = rqstp->rq_vec;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment