summaryrefslogtreecommitdiffstats
path: root/fs/nfs/write.c
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2017-08-21 15:00:49 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2017-09-11 22:20:38 -0400
commit8224b2734ab1da4996b851e1e5d3047e7a0df499 (patch)
treec1c06680d8db8ac2212e8d916760735fb9864d51 /fs/nfs/write.c
parent70d2f7b1ea19b7e43e36ccc63496f45f9908134d (diff)
downloadlinux-8224b2734ab1da4996b851e1e5d3047e7a0df499.tar.bz2
NFS: Add static NFS I/O tracepoints
Tools like tcpdump and rpcdebug can be very useful. But there are plenty of environments where they are difficult or impossible to use. For example, we've had customers report I/O failures during workloads so heavy that collecting network traffic or enabling RPC debugging are themselves onerous. The kernel's static tracepoints are lightweight (less likely to introduce timing changes) and efficient (the trace data is compact). They also work in scenarios where capturing network traffic is not possible due to lack of hardware support (some InfiniBand HCAs) or where data or network privacy is a concern. Introduce tracepoints that show when an NFS READ, WRITE, or COMMIT is initiated, and when it completes. Record the arguments and results of each operation, which are not shown by existing sunrpc module's tracepoints. For instance, the recorded offset and count can be used to match an "initiate" event to a "done" event. If an NFS READ result returns fewer bytes than requested or zero, seeing the EOF flag can be probative. Seeing an NFS4ERR_BAD_STATEID result is also indication of a particular class of problems. The timing information attached to each event record can often be useful as well. Usage example: [root@manet tmp]# trace-cmd record -e nfs:*initiate* -e nfs:*done /sys/kernel/debug/tracing/events/nfs/*initiate*/filter /sys/kernel/debug/tracing/events/nfs/*done/filter Hit Ctrl^C to stop recording ^CKernel buffer statistics: Note: "entries" are the entries left in the kernel ring buffer and are not recorded in the trace data. They should all be zero. CPU: 0 entries: 0 overrun: 0 commit overrun: 0 bytes: 3680 oldest event ts: 78.367422 now ts: 100.124419 dropped events: 0 read events: 74 ... and so on. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r--fs/nfs/write.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index f68083db63c8..c66206ac4ebf 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1383,6 +1383,8 @@ static void nfs_initiate_write(struct nfs_pgio_header *hdr,
task_setup_data->priority = priority;
rpc_ops->write_setup(hdr, msg);
+ trace_nfs_initiate_write(hdr->inode, hdr->io_start, hdr->good_bytes,
+ hdr->args.stable);
nfs4_state_protect_write(NFS_SERVER(hdr->inode)->nfs_client,
&task_setup_data->rpc_client, msg, hdr);
@@ -1540,7 +1542,10 @@ static int nfs_writeback_done(struct rpc_task *task,
status = NFS_PROTO(inode)->write_done(task, hdr);
if (status != 0)
return status;
+
nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, hdr->res.count);
+ trace_nfs_writeback_done(inode, task->tk_status,
+ hdr->args.offset, hdr->res.verf);
if (hdr->res.verf->committed < hdr->args.stable &&
task->tk_status >= 0) {
@@ -1669,6 +1674,7 @@ int nfs_initiate_commit(struct rpc_clnt *clnt, struct nfs_commit_data *data,
};
/* Set up the initial task struct. */
nfs_ops->commit_setup(data, &msg);
+ trace_nfs_initiate_commit(data);
dprintk("NFS: initiated commit call\n");
@@ -1793,6 +1799,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
/* Call the NFS version-specific code */
NFS_PROTO(data->inode)->commit_done(task, data);
+ trace_nfs_commit_done(data);
}
static void nfs_commit_release_pages(struct nfs_commit_data *data)