Skip to content

Commit 5582863

Browse files
chuckleveramschuma-ntap
authored andcommitted
SUNRPC: Add XDR overflow trace event
This can help field troubleshooting without needing the overhead of a full network capture (ie, tcpdump). Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
1 parent 0ccc61b commit 5582863

File tree

2 files changed

+84
-7
lines changed

2 files changed

+84
-7
lines changed

include/trace/events/sunrpc.h

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,73 @@ TRACE_EVENT(rpc_stats_latency,
254254
__entry->backlog, __entry->rtt, __entry->execute)
255255
);
256256

257+
TRACE_EVENT(rpc_xdr_overflow,
258+
TP_PROTO(
259+
const struct xdr_stream *xdr,
260+
size_t requested
261+
),
262+
263+
TP_ARGS(xdr, requested),
264+
265+
TP_STRUCT__entry(
266+
__field(unsigned int, task_id)
267+
__field(unsigned int, client_id)
268+
__field(int, version)
269+
__field(size_t, requested)
270+
__field(const void *, end)
271+
__field(const void *, p)
272+
__field(const void *, head_base)
273+
__field(size_t, head_len)
274+
__field(const void *, tail_base)
275+
__field(size_t, tail_len)
276+
__field(unsigned int, page_len)
277+
__field(unsigned int, len)
278+
__string(progname,
279+
xdr->rqst->rq_task->tk_client->cl_program->name)
280+
__string(procedure,
281+
xdr->rqst->rq_task->tk_msg.rpc_proc->p_name)
282+
),
283+
284+
TP_fast_assign(
285+
if (xdr->rqst) {
286+
const struct rpc_task *task = xdr->rqst->rq_task;
287+
288+
__entry->task_id = task->tk_pid;
289+
__entry->client_id = task->tk_client->cl_clid;
290+
__assign_str(progname,
291+
task->tk_client->cl_program->name)
292+
__entry->version = task->tk_client->cl_vers;
293+
__assign_str(procedure, task->tk_msg.rpc_proc->p_name)
294+
} else {
295+
__entry->task_id = 0;
296+
__entry->client_id = 0;
297+
__assign_str(progname, "unknown")
298+
__entry->version = 0;
299+
__assign_str(procedure, "unknown")
300+
}
301+
__entry->requested = requested;
302+
__entry->end = xdr->end;
303+
__entry->p = xdr->p;
304+
__entry->head_base = xdr->buf->head[0].iov_base,
305+
__entry->head_len = xdr->buf->head[0].iov_len,
306+
__entry->page_len = xdr->buf->page_len,
307+
__entry->tail_base = xdr->buf->tail[0].iov_base,
308+
__entry->tail_len = xdr->buf->tail[0].iov_len,
309+
__entry->len = xdr->buf->len;
310+
),
311+
312+
TP_printk(
313+
"task:%u@%u %sv%d %s requested=%zu p=%p end=%p xdr=[%p,%zu]/%u/[%p,%zu]/%u\n",
314+
__entry->task_id, __entry->client_id,
315+
__get_str(progname), __entry->version, __get_str(procedure),
316+
__entry->requested, __entry->p, __entry->end,
317+
__entry->head_base, __entry->head_len,
318+
__entry->page_len,
319+
__entry->tail_base, __entry->tail_len,
320+
__entry->len
321+
)
322+
);
323+
257324
/*
258325
* First define the enums in the below macros to be exported to userspace
259326
* via TRACE_DEFINE_ENUM().

net/sunrpc/xdr.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <linux/sunrpc/xdr.h>
1717
#include <linux/sunrpc/msg_prot.h>
1818
#include <linux/bvec.h>
19+
#include <trace/events/sunrpc.h>
1920

2021
/*
2122
* XDR functions for basic NFS types
@@ -554,9 +555,9 @@ static __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr,
554555
int frag1bytes, frag2bytes;
555556

556557
if (nbytes > PAGE_SIZE)
557-
return NULL; /* Bigger buffers require special handling */
558+
goto out_overflow; /* Bigger buffers require special handling */
558559
if (xdr->buf->len + nbytes > xdr->buf->buflen)
559-
return NULL; /* Sorry, we're totally out of space */
560+
goto out_overflow; /* Sorry, we're totally out of space */
560561
frag1bytes = (xdr->end - xdr->p) << 2;
561562
frag2bytes = nbytes - frag1bytes;
562563
if (xdr->iov)
@@ -585,6 +586,9 @@ static __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr,
585586
xdr->buf->page_len += frag2bytes;
586587
xdr->buf->len += nbytes;
587588
return p;
589+
out_overflow:
590+
trace_rpc_xdr_overflow(xdr, nbytes);
591+
return NULL;
588592
}
589593

590594
/**
@@ -902,20 +906,23 @@ static __be32 *xdr_copy_to_scratch(struct xdr_stream *xdr, size_t nbytes)
902906
size_t cplen = (char *)xdr->end - (char *)xdr->p;
903907

904908
if (nbytes > xdr->scratch.iov_len)
905-
return NULL;
909+
goto out_overflow;
906910
p = __xdr_inline_decode(xdr, cplen);
907911
if (p == NULL)
908912
return NULL;
909913
memcpy(cpdest, p, cplen);
914+
if (!xdr_set_next_buffer(xdr))
915+
goto out_overflow;
910916
cpdest += cplen;
911917
nbytes -= cplen;
912-
if (!xdr_set_next_buffer(xdr))
913-
return NULL;
914918
p = __xdr_inline_decode(xdr, nbytes);
915919
if (p == NULL)
916920
return NULL;
917921
memcpy(cpdest, p, nbytes);
918922
return xdr->scratch.iov_base;
923+
out_overflow:
924+
trace_rpc_xdr_overflow(xdr, nbytes);
925+
return NULL;
919926
}
920927

921928
/**
@@ -932,14 +939,17 @@ __be32 * xdr_inline_decode(struct xdr_stream *xdr, size_t nbytes)
932939
{
933940
__be32 *p;
934941

935-
if (nbytes == 0)
942+
if (unlikely(nbytes == 0))
936943
return xdr->p;
937944
if (xdr->p == xdr->end && !xdr_set_next_buffer(xdr))
938-
return NULL;
945+
goto out_overflow;
939946
p = __xdr_inline_decode(xdr, nbytes);
940947
if (p != NULL)
941948
return p;
942949
return xdr_copy_to_scratch(xdr, nbytes);
950+
out_overflow:
951+
trace_rpc_xdr_overflow(xdr, nbytes);
952+
return NULL;
943953
}
944954
EXPORT_SYMBOL_GPL(xdr_inline_decode);
945955

0 commit comments

Comments
 (0)