diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2018-03-28 13:29:11 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2018-04-03 15:08:15 -0400 |
commit | 87c5942e8fae81ac296267654a047eb2db81592b (patch) | |
tree | de00193297b93692cfc86f475fe7cb6d6dbdc56a | |
parent | d890be159a71395bd4ceca09233a8a56d7da69ee (diff) |
nfsd: Add I/O trace points in the NFSv4 read proc
NFSv4 read compound processing invokes nfsd_splice_read and
nfs_readv directly, so the trace points currently in nfsd_read are
not invoked for NFSv4 reads.
Move the NFSD READ trace points to common helpers so that NFSv4
reads are captured.
Also, record any local I/O error that occurs, the total count of
bytes that were actually returned, and whether splice or vectored
read was used.
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 | 5 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 10 | ||||
-rw-r--r-- | fs/nfsd/trace.h | 4 | ||||
-rw-r--r-- | fs/nfsd/vfs.c | 34 | ||||
-rw-r--r-- | fs/nfsd/vfs.h | 11 |
5 files changed, 39 insertions, 25 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index b773b314f599..250e0c550fd8 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -751,6 +751,9 @@ nfsd4_read(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, | |||
751 | if (read->rd_offset >= OFFSET_MAX) | 751 | if (read->rd_offset >= OFFSET_MAX) |
752 | return nfserr_inval; | 752 | return nfserr_inval; |
753 | 753 | ||
754 | trace_nfsd_read_start(rqstp, &cstate->current_fh, | ||
755 | read->rd_offset, read->rd_length); | ||
756 | |||
754 | /* | 757 | /* |
755 | * If we do a zero copy read, then a client will see read data | 758 | * If we do a zero copy read, then a client will see read data |
756 | * that reflects the state of the file *after* performing the | 759 | * that reflects the state of the file *after* performing the |
@@ -783,6 +786,8 @@ nfsd4_read_release(union nfsd4_op_u *u) | |||
783 | { | 786 | { |
784 | if (u->read.rd_filp) | 787 | if (u->read.rd_filp) |
785 | fput(u->read.rd_filp); | 788 | fput(u->read.rd_filp); |
789 | trace_nfsd_read_done(u->read.rd_rqstp, u->read.rd_fhp, | ||
790 | u->read.rd_offset, u->read.rd_length); | ||
786 | } | 791 | } |
787 | 792 | ||
788 | static __be32 | 793 | static __be32 |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 9f8ef2c6e508..dd72cdf3662e 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -3427,8 +3427,9 @@ static __be32 nfsd4_encode_splice_read( | |||
3427 | return nfserr_resource; | 3427 | return nfserr_resource; |
3428 | 3428 | ||
3429 | len = maxcount; | 3429 | len = maxcount; |
3430 | nfserr = nfsd_splice_read(read->rd_rqstp, file, | 3430 | nfserr = nfsd_splice_read(read->rd_rqstp, read->rd_fhp, |
3431 | read->rd_offset, &maxcount); | 3431 | file, read->rd_offset, &maxcount); |
3432 | read->rd_length = maxcount; | ||
3432 | if (nfserr) { | 3433 | if (nfserr) { |
3433 | /* | 3434 | /* |
3434 | * nfsd_splice_actor may have already messed with the | 3435 | * nfsd_splice_actor may have already messed with the |
@@ -3511,8 +3512,9 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp, | |||
3511 | read->rd_vlen = v; | 3512 | read->rd_vlen = v; |
3512 | 3513 | ||
3513 | len = maxcount; | 3514 | len = maxcount; |
3514 | nfserr = nfsd_readv(file, read->rd_offset, resp->rqstp->rq_vec, | 3515 | nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset, |
3515 | read->rd_vlen, &maxcount); | 3516 | resp->rqstp->rq_vec, read->rd_vlen, &maxcount); |
3517 | read->rd_length = maxcount; | ||
3516 | if (nfserr) | 3518 | if (nfserr) |
3517 | return nfserr; | 3519 | return nfserr; |
3518 | xdr_truncate_encode(xdr, starting_len + 8 + ((maxcount+3)&~3)); | 3520 | xdr_truncate_encode(xdr, starting_len + 8 + ((maxcount+3)&~3)); |
diff --git a/fs/nfsd/trace.h b/fs/nfsd/trace.h index 653e9ee754d2..a8bbd9d00a9e 100644 --- a/fs/nfsd/trace.h +++ b/fs/nfsd/trace.h | |||
@@ -43,7 +43,8 @@ DEFINE_EVENT(nfsd_io_class, nfsd_##name, \ | |||
43 | TP_ARGS(rqstp, fhp, offset, len)) | 43 | TP_ARGS(rqstp, fhp, offset, len)) |
44 | 44 | ||
45 | DEFINE_NFSD_IO_EVENT(read_start); | 45 | DEFINE_NFSD_IO_EVENT(read_start); |
46 | DEFINE_NFSD_IO_EVENT(read_opened); | 46 | DEFINE_NFSD_IO_EVENT(read_splice); |
47 | DEFINE_NFSD_IO_EVENT(read_vector); | ||
47 | DEFINE_NFSD_IO_EVENT(read_io_done); | 48 | DEFINE_NFSD_IO_EVENT(read_io_done); |
48 | DEFINE_NFSD_IO_EVENT(read_done); | 49 | DEFINE_NFSD_IO_EVENT(read_done); |
49 | DEFINE_NFSD_IO_EVENT(write_start); | 50 | DEFINE_NFSD_IO_EVENT(write_start); |
@@ -82,6 +83,7 @@ DEFINE_EVENT(nfsd_err_class, nfsd_##name, \ | |||
82 | int len), \ | 83 | int len), \ |
83 | TP_ARGS(rqstp, fhp, offset, len)) | 84 | TP_ARGS(rqstp, fhp, offset, len)) |
84 | 85 | ||
86 | DEFINE_NFSD_ERR_EVENT(read_err); | ||
85 | DEFINE_NFSD_ERR_EVENT(write_err); | 87 | DEFINE_NFSD_ERR_EVENT(write_err); |
86 | 88 | ||
87 | #include "state.h" | 89 | #include "state.h" |
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c index ee59a0b24fab..2410b093a2e6 100644 --- a/fs/nfsd/vfs.c +++ b/fs/nfsd/vfs.c | |||
@@ -881,20 +881,24 @@ static int nfsd_direct_splice_actor(struct pipe_inode_info *pipe, | |||
881 | return __splice_from_pipe(pipe, sd, nfsd_splice_actor); | 881 | return __splice_from_pipe(pipe, sd, nfsd_splice_actor); |
882 | } | 882 | } |
883 | 883 | ||
884 | static __be32 | 884 | static __be32 nfsd_finish_read(struct svc_rqst *rqstp, struct svc_fh *fhp, |
885 | nfsd_finish_read(struct file *file, unsigned long *count, int host_err) | 885 | struct file *file, loff_t offset, |
886 | unsigned long *count, int host_err) | ||
886 | { | 887 | { |
887 | if (host_err >= 0) { | 888 | if (host_err >= 0) { |
888 | nfsdstats.io_read += host_err; | 889 | nfsdstats.io_read += host_err; |
889 | *count = host_err; | 890 | *count = host_err; |
890 | fsnotify_access(file); | 891 | fsnotify_access(file); |
892 | trace_nfsd_read_io_done(rqstp, fhp, offset, *count); | ||
891 | return 0; | 893 | return 0; |
892 | } else | 894 | } else { |
895 | trace_nfsd_read_err(rqstp, fhp, offset, host_err); | ||
893 | return nfserrno(host_err); | 896 | return nfserrno(host_err); |
897 | } | ||
894 | } | 898 | } |
895 | 899 | ||
896 | __be32 nfsd_splice_read(struct svc_rqst *rqstp, | 900 | __be32 nfsd_splice_read(struct svc_rqst *rqstp, struct svc_fh *fhp, |
897 | struct file *file, loff_t offset, unsigned long *count) | 901 | struct file *file, loff_t offset, unsigned long *count) |
898 | { | 902 | { |
899 | struct splice_desc sd = { | 903 | struct splice_desc sd = { |
900 | .len = 0, | 904 | .len = 0, |
@@ -904,21 +908,23 @@ __be32 nfsd_splice_read(struct svc_rqst *rqstp, | |||
904 | }; | 908 | }; |
905 | int host_err; | 909 | int host_err; |
906 | 910 | ||
911 | trace_nfsd_read_splice(rqstp, fhp, offset, *count); | ||
907 | rqstp->rq_next_page = rqstp->rq_respages + 1; | 912 | rqstp->rq_next_page = rqstp->rq_respages + 1; |
908 | host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor); | 913 | host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor); |
909 | return nfsd_finish_read(file, count, host_err); | 914 | return nfsd_finish_read(rqstp, fhp, file, offset, count, host_err); |
910 | } | 915 | } |
911 | 916 | ||
912 | __be32 nfsd_readv(struct file *file, loff_t offset, struct kvec *vec, int vlen, | 917 | __be32 nfsd_readv(struct svc_rqst *rqstp, struct svc_fh *fhp, |
913 | unsigned long *count) | 918 | struct file *file, loff_t offset, |
919 | struct kvec *vec, int vlen, unsigned long *count) | ||
914 | { | 920 | { |
915 | struct iov_iter iter; | 921 | struct iov_iter iter; |
916 | int host_err; | 922 | int host_err; |
917 | 923 | ||
924 | trace_nfsd_read_vector(rqstp, fhp, offset, *count); | ||
918 | iov_iter_kvec(&iter, READ | ITER_KVEC, vec, vlen, *count); | 925 | iov_iter_kvec(&iter, READ | ITER_KVEC, vec, vlen, *count); |
919 | host_err = vfs_iter_read(file, &iter, &offset, 0); | 926 | host_err = vfs_iter_read(file, &iter, &offset, 0); |
920 | 927 | return nfsd_finish_read(rqstp, fhp, file, offset, count, host_err); | |
921 | return nfsd_finish_read(file, count, host_err); | ||
922 | } | 928 | } |
923 | 929 | ||
924 | /* | 930 | /* |
@@ -1034,14 +1040,10 @@ __be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, | |||
1034 | 1040 | ||
1035 | ra = nfsd_init_raparms(file); | 1041 | ra = nfsd_init_raparms(file); |
1036 | 1042 | ||
1037 | trace_nfsd_read_opened(rqstp, fhp, offset, *count); | ||
1038 | |||
1039 | if (file->f_op->splice_read && test_bit(RQ_SPLICE_OK, &rqstp->rq_flags)) | 1043 | if (file->f_op->splice_read && test_bit(RQ_SPLICE_OK, &rqstp->rq_flags)) |
1040 | err = nfsd_splice_read(rqstp, file, offset, count); | 1044 | err = nfsd_splice_read(rqstp, fhp, file, offset, count); |
1041 | else | 1045 | else |
1042 | err = nfsd_readv(file, offset, vec, vlen, count); | 1046 | err = nfsd_readv(rqstp, fhp, file, offset, vec, vlen, count); |
1043 | |||
1044 | trace_nfsd_read_io_done(rqstp, fhp, offset, *count); | ||
1045 | 1047 | ||
1046 | if (ra) | 1048 | if (ra) |
1047 | nfsd_put_raparams(file, ra); | 1049 | nfsd_put_raparams(file, ra); |
diff --git a/fs/nfsd/vfs.h b/fs/nfsd/vfs.h index be6d8e00453f..a7e107309f76 100644 --- a/fs/nfsd/vfs.h +++ b/fs/nfsd/vfs.h | |||
@@ -78,10 +78,13 @@ __be32 nfsd_commit(struct svc_rqst *, struct svc_fh *, | |||
78 | __be32 nfsd_open(struct svc_rqst *, struct svc_fh *, umode_t, | 78 | __be32 nfsd_open(struct svc_rqst *, struct svc_fh *, umode_t, |
79 | int, struct file **); | 79 | int, struct file **); |
80 | struct raparms; | 80 | struct raparms; |
81 | __be32 nfsd_splice_read(struct svc_rqst *, | 81 | __be32 nfsd_splice_read(struct svc_rqst *rqstp, struct svc_fh *fhp, |
82 | struct file *, loff_t, unsigned long *); | 82 | struct file *file, loff_t offset, |
83 | __be32 nfsd_readv(struct file *, loff_t, struct kvec *, int, | 83 | unsigned long *count); |
84 | unsigned long *); | 84 | __be32 nfsd_readv(struct svc_rqst *rqstp, struct svc_fh *fhp, |
85 | struct file *file, loff_t offset, | ||
86 | struct kvec *vec, int vlen, | ||
87 | unsigned long *count); | ||
85 | __be32 nfsd_read(struct svc_rqst *, struct svc_fh *, | 88 | __be32 nfsd_read(struct svc_rqst *, struct svc_fh *, |
86 | loff_t, struct kvec *, int, unsigned long *); | 89 | loff_t, struct kvec *, int, unsigned long *); |
87 | __be32 nfsd_write(struct svc_rqst *, struct svc_fh *, loff_t, | 90 | __be32 nfsd_write(struct svc_rqst *, struct svc_fh *, loff_t, |