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:
Родитель
02648908d1
Коммит
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,
|
||||
TP_PROTO(
|
||||
const struct svc_xprt *xprt,
|
||||
|
|
|
@ -828,47 +828,45 @@ out:
|
|||
}
|
||||
|
||||
/*
|
||||
* 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;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче