Skip to content

Commit 8224b27

Browse files
chucklevertrondmypd
authored andcommitted
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 <[email protected]> Signed-off-by: Trond Myklebust <[email protected]>
1 parent 70d2f7b commit 8224b27

File tree

3 files changed

+259
-0
lines changed

3 files changed

+259
-0
lines changed

fs/nfs/nfstrace.h

Lines changed: 248 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -719,6 +719,254 @@ TRACE_EVENT(nfs_sillyrename_unlink,
719719
__get_str(name)
720720
)
721721
);
722+
723+
TRACE_EVENT(nfs_initiate_read,
724+
TP_PROTO(
725+
const struct inode *inode,
726+
loff_t offset, unsigned long count
727+
),
728+
729+
TP_ARGS(inode, offset, count),
730+
731+
TP_STRUCT__entry(
732+
__field(loff_t, offset)
733+
__field(unsigned long, count)
734+
__field(dev_t, dev)
735+
__field(u32, fhandle)
736+
__field(u64, fileid)
737+
),
738+
739+
TP_fast_assign(
740+
const struct nfs_inode *nfsi = NFS_I(inode);
741+
742+
__entry->offset = offset;
743+
__entry->count = count;
744+
__entry->dev = inode->i_sb->s_dev;
745+
__entry->fileid = nfsi->fileid;
746+
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
747+
),
748+
749+
TP_printk(
750+
"fileid=%02x:%02x:%llu fhandle=0x%08x "
751+
"offset=%lld count=%lu",
752+
MAJOR(__entry->dev), MINOR(__entry->dev),
753+
(unsigned long long)__entry->fileid,
754+
__entry->fhandle,
755+
__entry->offset, __entry->count
756+
)
757+
);
758+
759+
TRACE_EVENT(nfs_readpage_done,
760+
TP_PROTO(
761+
const struct inode *inode,
762+
int status, loff_t offset, bool eof
763+
),
764+
765+
TP_ARGS(inode, status, offset, eof),
766+
767+
TP_STRUCT__entry(
768+
__field(int, status)
769+
__field(loff_t, offset)
770+
__field(bool, eof)
771+
__field(dev_t, dev)
772+
__field(u32, fhandle)
773+
__field(u64, fileid)
774+
),
775+
776+
TP_fast_assign(
777+
const struct nfs_inode *nfsi = NFS_I(inode);
778+
779+
__entry->status = status;
780+
__entry->offset = offset;
781+
__entry->eof = eof;
782+
__entry->dev = inode->i_sb->s_dev;
783+
__entry->fileid = nfsi->fileid;
784+
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
785+
),
786+
787+
TP_printk(
788+
"fileid=%02x:%02x:%llu fhandle=0x%08x "
789+
"offset=%lld status=%d%s",
790+
MAJOR(__entry->dev), MINOR(__entry->dev),
791+
(unsigned long long)__entry->fileid,
792+
__entry->fhandle,
793+
__entry->offset, __entry->status,
794+
__entry->eof ? " eof" : ""
795+
)
796+
);
797+
798+
/*
799+
* XXX: I tried using NFS_UNSTABLE and friends in this table, but they
800+
* all evaluate to 0 for some reason, even if I include linux/nfs.h.
801+
*/
802+
#define nfs_show_stable(stable) \
803+
__print_symbolic(stable, \
804+
{ 0, " (UNSTABLE)" }, \
805+
{ 1, " (DATA_SYNC)" }, \
806+
{ 2, " (FILE_SYNC)" })
807+
808+
TRACE_EVENT(nfs_initiate_write,
809+
TP_PROTO(
810+
const struct inode *inode,
811+
loff_t offset, unsigned long count,
812+
enum nfs3_stable_how stable
813+
),
814+
815+
TP_ARGS(inode, offset, count, stable),
816+
817+
TP_STRUCT__entry(
818+
__field(loff_t, offset)
819+
__field(unsigned long, count)
820+
__field(enum nfs3_stable_how, stable)
821+
__field(dev_t, dev)
822+
__field(u32, fhandle)
823+
__field(u64, fileid)
824+
),
825+
826+
TP_fast_assign(
827+
const struct nfs_inode *nfsi = NFS_I(inode);
828+
829+
__entry->offset = offset;
830+
__entry->count = count;
831+
__entry->stable = stable;
832+
__entry->dev = inode->i_sb->s_dev;
833+
__entry->fileid = nfsi->fileid;
834+
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
835+
),
836+
837+
TP_printk(
838+
"fileid=%02x:%02x:%llu fhandle=0x%08x "
839+
"offset=%lld count=%lu stable=%d%s",
840+
MAJOR(__entry->dev), MINOR(__entry->dev),
841+
(unsigned long long)__entry->fileid,
842+
__entry->fhandle,
843+
__entry->offset, __entry->count,
844+
__entry->stable, nfs_show_stable(__entry->stable)
845+
)
846+
);
847+
848+
TRACE_EVENT(nfs_writeback_done,
849+
TP_PROTO(
850+
const struct inode *inode,
851+
int status,
852+
loff_t offset,
853+
struct nfs_writeverf *writeverf
854+
),
855+
856+
TP_ARGS(inode, status, offset, writeverf),
857+
858+
TP_STRUCT__entry(
859+
__field(int, status)
860+
__field(loff_t, offset)
861+
__field(enum nfs3_stable_how, stable)
862+
__field(unsigned long long, verifier)
863+
__field(dev_t, dev)
864+
__field(u32, fhandle)
865+
__field(u64, fileid)
866+
),
867+
868+
TP_fast_assign(
869+
const struct nfs_inode *nfsi = NFS_I(inode);
870+
871+
__entry->status = status;
872+
__entry->offset = offset;
873+
__entry->stable = writeverf->committed;
874+
memcpy(&__entry->verifier, &writeverf->verifier,
875+
sizeof(__entry->verifier));
876+
__entry->dev = inode->i_sb->s_dev;
877+
__entry->fileid = nfsi->fileid;
878+
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
879+
),
880+
881+
TP_printk(
882+
"fileid=%02x:%02x:%llu fhandle=0x%08x "
883+
"offset=%lld status=%d stable=%d%s "
884+
"verifier 0x%016llx",
885+
MAJOR(__entry->dev), MINOR(__entry->dev),
886+
(unsigned long long)__entry->fileid,
887+
__entry->fhandle,
888+
__entry->offset, __entry->status,
889+
__entry->stable, nfs_show_stable(__entry->stable),
890+
__entry->verifier
891+
)
892+
);
893+
894+
TRACE_EVENT(nfs_initiate_commit,
895+
TP_PROTO(
896+
const struct nfs_commit_data *data
897+
),
898+
899+
TP_ARGS(data),
900+
901+
TP_STRUCT__entry(
902+
__field(loff_t, offset)
903+
__field(unsigned long, count)
904+
__field(dev_t, dev)
905+
__field(u32, fhandle)
906+
__field(u64, fileid)
907+
),
908+
909+
TP_fast_assign(
910+
const struct inode *inode = data->inode;
911+
const struct nfs_inode *nfsi = NFS_I(inode);
912+
913+
__entry->offset = data->args.offset;
914+
__entry->count = data->args.count;
915+
__entry->dev = inode->i_sb->s_dev;
916+
__entry->fileid = nfsi->fileid;
917+
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
918+
),
919+
920+
TP_printk(
921+
"fileid=%02x:%02x:%llu fhandle=0x%08x "
922+
"offset=%lld count=%lu",
923+
MAJOR(__entry->dev), MINOR(__entry->dev),
924+
(unsigned long long)__entry->fileid,
925+
__entry->fhandle,
926+
__entry->offset, __entry->count
927+
)
928+
);
929+
930+
TRACE_EVENT(nfs_commit_done,
931+
TP_PROTO(
932+
const struct nfs_commit_data *data
933+
),
934+
935+
TP_ARGS(data),
936+
937+
TP_STRUCT__entry(
938+
__field(int, status)
939+
__field(loff_t, offset)
940+
__field(unsigned long long, verifier)
941+
__field(dev_t, dev)
942+
__field(u32, fhandle)
943+
__field(u64, fileid)
944+
),
945+
946+
TP_fast_assign(
947+
const struct inode *inode = data->inode;
948+
const struct nfs_inode *nfsi = NFS_I(inode);
949+
950+
__entry->status = data->res.op_status;
951+
__entry->offset = data->args.offset;
952+
memcpy(&__entry->verifier, &data->verf.verifier,
953+
sizeof(__entry->verifier));
954+
__entry->dev = inode->i_sb->s_dev;
955+
__entry->fileid = nfsi->fileid;
956+
__entry->fhandle = nfs_fhandle_hash(&nfsi->fh);
957+
),
958+
959+
TP_printk(
960+
"fileid=%02x:%02x:%llu fhandle=0x%08x "
961+
"offset=%lld status=%d verifier 0x%016llx",
962+
MAJOR(__entry->dev), MINOR(__entry->dev),
963+
(unsigned long long)__entry->fileid,
964+
__entry->fhandle,
965+
__entry->offset, __entry->status,
966+
__entry->verifier
967+
)
968+
);
969+
722970
#endif /* _TRACE_NFS_H */
723971

724972
#undef TRACE_INCLUDE_PATH

fs/nfs/read.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "iostat.h"
2626
#include "fscache.h"
2727
#include "pnfs.h"
28+
#include "nfstrace.h"
2829

2930
#define NFSDBG_FACILITY NFSDBG_PAGECACHE
3031

@@ -200,6 +201,7 @@ static void nfs_initiate_read(struct nfs_pgio_header *hdr,
200201

201202
task_setup_data->flags |= swap_flags;
202203
rpc_ops->read_setup(hdr, msg);
204+
trace_nfs_initiate_read(inode, hdr->io_start, hdr->good_bytes);
203205
}
204206

205207
static void
@@ -232,6 +234,8 @@ static int nfs_readpage_done(struct rpc_task *task,
232234
return status;
233235

234236
nfs_add_stats(inode, NFSIOS_SERVERREADBYTES, hdr->res.count);
237+
trace_nfs_readpage_done(inode, task->tk_status,
238+
hdr->args.offset, hdr->res.eof);
235239

236240
if (task->tk_status == -ESTALE) {
237241
set_bit(NFS_INO_STALE, &NFS_I(inode)->flags);

fs/nfs/write.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1383,6 +1383,8 @@ static void nfs_initiate_write(struct nfs_pgio_header *hdr,
13831383

13841384
task_setup_data->priority = priority;
13851385
rpc_ops->write_setup(hdr, msg);
1386+
trace_nfs_initiate_write(hdr->inode, hdr->io_start, hdr->good_bytes,
1387+
hdr->args.stable);
13861388

13871389
nfs4_state_protect_write(NFS_SERVER(hdr->inode)->nfs_client,
13881390
&task_setup_data->rpc_client, msg, hdr);
@@ -1540,7 +1542,10 @@ static int nfs_writeback_done(struct rpc_task *task,
15401542
status = NFS_PROTO(inode)->write_done(task, hdr);
15411543
if (status != 0)
15421544
return status;
1545+
15431546
nfs_add_stats(inode, NFSIOS_SERVERWRITTENBYTES, hdr->res.count);
1547+
trace_nfs_writeback_done(inode, task->tk_status,
1548+
hdr->args.offset, hdr->res.verf);
15441549

15451550
if (hdr->res.verf->committed < hdr->args.stable &&
15461551
task->tk_status >= 0) {
@@ -1669,6 +1674,7 @@ int nfs_initiate_commit(struct rpc_clnt *clnt, struct nfs_commit_data *data,
16691674
};
16701675
/* Set up the initial task struct. */
16711676
nfs_ops->commit_setup(data, &msg);
1677+
trace_nfs_initiate_commit(data);
16721678

16731679
dprintk("NFS: initiated commit call\n");
16741680

@@ -1793,6 +1799,7 @@ static void nfs_commit_done(struct rpc_task *task, void *calldata)
17931799

17941800
/* Call the NFS version-specific code */
17951801
NFS_PROTO(data->inode)->commit_done(task, data);
1802+
trace_nfs_commit_done(data);
17961803
}
17971804

17981805
static void nfs_commit_release_pages(struct nfs_commit_data *data)

0 commit comments

Comments
 (0)