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: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
parent
02648908d1
commit
a5cda73e49
|
@ -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,
|
DECLARE_EVENT_CLASS(svcsock_class,
|
||||||
TP_PROTO(
|
TP_PROTO(
|
||||||
const struct svc_xprt *xprt,
|
const struct svc_xprt *xprt,
|
||||||
|
|
|
@ -828,47 +828,45 @@ out:
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Receive fragment record header.
|
* Receive fragment record header into sk_marker.
|
||||||
* If we haven't gotten the record length yet, get the next four bytes.
|
|
||||||
*/
|
*/
|
||||||
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;
|
ssize_t want, len;
|
||||||
unsigned int want;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
|
/* If we haven't gotten the record length yet,
|
||||||
|
* get the next four bytes.
|
||||||
|
*/
|
||||||
if (svsk->sk_tcplen < sizeof(rpc_fraghdr)) {
|
if (svsk->sk_tcplen < sizeof(rpc_fraghdr)) {
|
||||||
|
struct msghdr msg = { NULL };
|
||||||
struct kvec iov;
|
struct kvec iov;
|
||||||
|
|
||||||
want = sizeof(rpc_fraghdr) - svsk->sk_tcplen;
|
want = sizeof(rpc_fraghdr) - svsk->sk_tcplen;
|
||||||
iov.iov_base = ((char *)&svsk->sk_marker) + svsk->sk_tcplen;
|
iov.iov_base = ((char *)&svsk->sk_marker) + svsk->sk_tcplen;
|
||||||
iov.iov_len = want;
|
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)
|
if (len < 0)
|
||||||
goto error;
|
return len;
|
||||||
svsk->sk_tcplen += len;
|
svsk->sk_tcplen += len;
|
||||||
|
|
||||||
if (len < want) {
|
if (len < want) {
|
||||||
dprintk("svc: short recvfrom while reading record "
|
/* call again to read the remaining bytes */
|
||||||
"length (%d of %d)\n", len, want);
|
goto err_short;
|
||||||
return -EAGAIN;
|
|
||||||
}
|
}
|
||||||
|
trace_svcsock_marker(&svsk->sk_xprt, svsk->sk_marker);
|
||||||
dprintk("svc: TCP record, %d bytes\n", svc_sock_reclen(svsk));
|
|
||||||
if (svc_sock_reclen(svsk) + svsk->sk_datalen >
|
if (svc_sock_reclen(svsk) + svsk->sk_datalen >
|
||||||
serv->sv_max_mesg) {
|
svsk->sk_xprt.xpt_server->sv_max_mesg)
|
||||||
net_notice_ratelimited("RPC: fragment too large: %d\n",
|
goto err_too_large;
|
||||||
svc_sock_reclen(svsk));
|
|
||||||
goto err_delete;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return svc_sock_reclen(svsk);
|
return svc_sock_reclen(svsk);
|
||||||
error:
|
|
||||||
dprintk("RPC: TCP recv_record got %d\n", len);
|
err_too_large:
|
||||||
return len;
|
net_notice_ratelimited("svc: %s %s RPC fragment too large: %d\n",
|
||||||
err_delete:
|
__func__, svsk->sk_xprt.xpt_server->sv_name,
|
||||||
|
svc_sock_reclen(svsk));
|
||||||
set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
|
set_bit(XPT_CLOSE, &svsk->sk_xprt.xpt_flags);
|
||||||
|
err_short:
|
||||||
return -EAGAIN;
|
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_CONN, &svsk->sk_xprt.xpt_flags),
|
||||||
test_bit(XPT_CLOSE, &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)
|
if (len < 0)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
base = svc_tcp_restore_pages(svsk, rqstp);
|
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;
|
vec = rqstp->rq_vec;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue