diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2018-03-27 10:53:27 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2018-04-03 15:08:15 -0400 |
commit | d890be159a71395bd4ceca09233a8a56d7da69ee (patch) | |
tree | c8e7089ab7e52770d57842ecd189275de08bd789 | |
parent | f394b62b7b0dd24757e9813e19f4b6091c5a28f6 (diff) |
nfsd: Add I/O trace points in the NFSv4 write path
NFSv4 write compound processing invokes nfsd_vfs_write directly. The
trace points currently in nfsd_write are not effective for NFSv4
writes.
Move the trace points into the shared nfsd_vfs_write() helper.
After the I/O, we also want to record any local I/O error that
might have occurred, and the total count of bytes that were actually
moved (rather than the requested number).
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r-- | fs/nfsd/nfs4proc.c | 7 | ||||
-rw-r--r-- | fs/nfsd/trace.h | 33 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 23 |
3 files changed, 50 insertions, 13 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 792fbb851046..b773b314f599 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -1001,6 +1001,9 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
1001 | if (write->wr_offset >= OFFSET_MAX) | 1001 | if (write->wr_offset >= OFFSET_MAX) |
1002 | return nfserr_inval; | 1002 | return nfserr_inval; |
1003 | 1003 | ||
1004 | cnt = write->wr_buflen; | ||
1005 | trace_nfsd_write_start(rqstp, &cstate->current_fh, | ||
1006 | write->wr_offset, cnt); | ||
1004 | status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh, | 1007 | status = nfs4_preprocess_stateid_op(rqstp, cstate, &cstate->current_fh, |
1005 | stateid, WR_STATE, &filp, NULL); | 1008 | stateid, WR_STATE, &filp, NULL); |
1006 | if (status) { | 1009 | if (status) { |
@@ -1008,7 +1011,6 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
1008 | return status; | 1011 | return status; |
1009 | } | 1012 | } |
1010 | 1013 | ||
1011 | cnt = write->wr_buflen; | ||
1012 | write->wr_how_written = write->wr_stable_how; | 1014 | write->wr_how_written = write->wr_stable_how; |
1013 | gen_boot_verifier(&write->wr_verifier, SVC_NET(rqstp)); | 1015 | gen_boot_verifier(&write->wr_verifier, SVC_NET(rqstp)); |
1014 | 1016 | ||
@@ -1021,7 +1023,8 @@ nfsd4_write(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
1021 | fput(filp); | 1023 | fput(filp); |
1022 | 1024 | ||
1023 | write->wr_bytes_written = cnt; | 1025 | write->wr_bytes_written = cnt; |
1024 | 1026 | trace_nfsd_write_done(rqstp, &cstate->current_fh, | |
1027 | write->wr_offset, cnt); | ||
1025 | return status; | 1028 | return status; |
1026 | } | 1029 | } |
1027 | 1030 | ||
diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h index 30e04852a4e0..653e9ee754d2 100644 --- a/fs/nfsd/trace.h +++ b/fs/nfsd/trace.h | |||
@@ -51,6 +51,39 @@ DEFINE_NFSD_IO_EVENT(write_opened); | |||
51 | DEFINE_NFSD_IO_EVENT(write_io_done); | 51 | DEFINE_NFSD_IO_EVENT(write_io_done); |
52 | DEFINE_NFSD_IO_EVENT(write_done); | 52 | DEFINE_NFSD_IO_EVENT(write_done); |
53 | 53 | ||
54 | DECLARE_EVENT_CLASS(nfsd_err_class, | ||
55 | TP_PROTO(struct svc_rqst *rqstp, | ||
56 | struct svc_fh *fhp, | ||
57 | loff_t offset, | ||
58 | int status), | ||
59 | TP_ARGS(rqstp, fhp, offset, status), | ||
60 | TP_STRUCT__entry( | ||
61 | __field(u32, xid) | ||
62 | __field(u32, fh_hash) | ||
63 | __field(loff_t, offset) | ||
64 | __field(int, status) | ||
65 | ), | ||
66 | TP_fast_assign( | ||
67 | __entry->xid = be32_to_cpu(rqstp->rq_xid); | ||
68 | __entry->fh_hash = knfsd_fh_hash(&fhp->fh_handle); | ||
69 | __entry->offset = offset; | ||
70 | __entry->status = status; | ||
71 | ), | ||
72 | TP_printk("xid=0x%08x fh_hash=0x%08x offset=%lld status=%d", | ||
73 | __entry->xid, __entry->fh_hash, | ||
74 | __entry->offset, __entry->status) | ||
75 | ) | ||
76 | |||
77 | #define DEFINE_NFSD_ERR_EVENT(name) \ | ||
78 | DEFINE_EVENT(nfsd_err_class, nfsd_##name, \ | ||
79 | TP_PROTO(struct svc_rqst *rqstp, \ | ||
80 | struct svc_fh *fhp, \ | ||
81 | loff_t offset, \ | ||
82 | int len), \ | ||
83 | TP_ARGS(rqstp, fhp, offset, len)) | ||
84 | |||
85 | DEFINE_NFSD_ERR_EVENT(write_err); | ||
86 | |||
54 | #include "state.h" | 87 | #include "state.h" |
55 | 88 | ||
56 | DECLARE_EVENT_CLASS(nfsd_stateid_class, | 89 | DECLARE_EVENT_CLASS(nfsd_stateid_class, |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index 857031952970..ee59a0b24fab 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -965,13 +965,15 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
965 | { | 965 | { |
966 | struct svc_export *exp; | 966 | struct svc_export *exp; |
967 | struct iov_iter iter; | 967 | struct iov_iter iter; |
968 | __be32 err = 0; | 968 | __be32 nfserr; |
969 | int host_err; | 969 | int host_err; |
970 | int use_wgather; | 970 | int use_wgather; |
971 | loff_t pos = offset; | 971 | loff_t pos = offset; |
972 | unsigned int pflags = current->flags; | 972 | unsigned int pflags = current->flags; |
973 | rwf_t flags = 0; | 973 | rwf_t flags = 0; |
974 | 974 | ||
975 | trace_nfsd_write_opened(rqstp, fhp, offset, *cnt); | ||
976 | |||
975 | if (test_bit(RQ_LOCAL, &rqstp->rq_flags)) | 977 | if (test_bit(RQ_LOCAL, &rqstp->rq_flags)) |
976 | /* | 978 | /* |
977 | * We want less throttling in balance_dirty_pages() | 979 | * We want less throttling in balance_dirty_pages() |
@@ -994,22 +996,23 @@ nfsd_vfs_write(struct svc_rqst *rqstp, struct svc_fh *fhp, struct file *file, | |||
994 | host_err = vfs_iter_write(file, &iter, &pos, flags); | 996 | host_err = vfs_iter_write(file, &iter, &pos, flags); |
995 | if (host_err < 0) | 997 | if (host_err < 0) |
996 | goto out_nfserr; | 998 | goto out_nfserr; |
997 | *cnt = host_err; | 999 | nfsdstats.io_write += *cnt; |
998 | nfsdstats.io_write += host_err; | ||
999 | fsnotify_modify(file); | 1000 | fsnotify_modify(file); |
1000 | 1001 | ||
1001 | if (stable && use_wgather) | 1002 | if (stable && use_wgather) |
1002 | host_err = wait_for_concurrent_writes(file); | 1003 | host_err = wait_for_concurrent_writes(file); |
1003 | 1004 | ||
1004 | out_nfserr: | 1005 | out_nfserr: |
1005 | dprintk("nfsd: write complete host_err=%d\n", host_err); | 1006 | if (host_err >= 0) { |
1006 | if (host_err >= 0) | 1007 | trace_nfsd_write_io_done(rqstp, fhp, offset, *cnt); |
1007 | err = 0; | 1008 | nfserr = nfs_ok; |
1008 | else | 1009 | } else { |
1009 | err = nfserrno(host_err); | 1010 | trace_nfsd_write_err(rqstp, fhp, offset, host_err); |
1011 | nfserr = nfserrno(host_err); | ||
1012 | } | ||
1010 | if (test_bit(RQ_LOCAL, &rqstp->rq_flags)) | 1013 | if (test_bit(RQ_LOCAL, &rqstp->rq_flags)) |
1011 | current_restore_flags(pflags, PF_LESS_THROTTLE); | 1014 | current_restore_flags(pflags, PF_LESS_THROTTLE); |
1012 | return err; | 1015 | return nfserr; |
1013 | } | 1016 | } |
1014 | 1017 | ||
1015 | /* | 1018 | /* |
@@ -1067,9 +1070,7 @@ nfsd_write(struct svc_rqst *rqstp, struct svc_fh *fhp, loff_t offset, | |||
1067 | if (err) | 1070 | if (err) |
1068 | goto out; | 1071 | goto out; |
1069 | 1072 | ||
1070 | trace_nfsd_write_opened(rqstp, fhp, offset, *cnt); | ||
1071 | err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen, cnt, stable); | 1073 | err = nfsd_vfs_write(rqstp, fhp, file, offset, vec, vlen, cnt, stable); |
1072 | trace_nfsd_write_io_done(rqstp, fhp, offset, *cnt); | ||
1073 | fput(file); | 1074 | fput(file); |
1074 | out: | 1075 | out: |
1075 | trace_nfsd_write_done(rqstp, fhp, offset, *cnt); | 1076 | trace_nfsd_write_done(rqstp, fhp, offset, *cnt); |