aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/vfs.c
diff options
context:
space:
mode:
authorTrond Myklebust <trondmy@gmail.com>2019-08-26 13:03:11 -0400
committerJ. Bruce Fields <bfields@redhat.com>2019-09-23 16:24:08 -0400
commit83a63072c815e8a042c60fa964dcbde2a6df0e87 (patch)
tree2c768fecd75e144e5faf38951c96dd73d91e181e /fs/nfsd/vfs.c
parent65643f4c8217edb1f40f7fb05f996c3a4798442a (diff)
nfsd: fix nfs read eof detection
Currently, the knfsd server assumes that a short read indicates an end of file. That assumption is incorrect. The short read means that either we've hit the end of file, or we've hit a read error. In the case of a read error, the client may want to retry (as per the implementation recommendations in RFC1813 and RFC7530), but currently it is being told that it hit an eof. Move the code to detect eof from version specific code into the generic nfsd read. Report eof only in the two following cases: 1) read() returns a zero length short read with no error. 2) the offset+length of the read is >= the file size. Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/vfs.c')
-rw-r--r--fs/nfsd/vfs.c37
1 files changed, 26 insertions, 11 deletions
diff --git a/fs/nfsd/vfs.c b/fs/nfsd/vfs.c
index 0867d5319fdb..bd0a385df3fc 100644
--- a/fs/nfsd/vfs.c
+++ b/fs/nfsd/vfs.c
@@ -834,12 +834,23 @@ static int nfsd_direct_splice_actor(struct pipe_inode_info *pipe,
834 return __splice_from_pipe(pipe, sd, nfsd_splice_actor); 834 return __splice_from_pipe(pipe, sd, nfsd_splice_actor);
835} 835}
836 836
837static u32 nfsd_eof_on_read(struct file *file, loff_t offset, ssize_t len,
838 size_t expected)
839{
840 if (expected != 0 && len == 0)
841 return 1;
842 if (offset+len >= i_size_read(file_inode(file)))
843 return 1;
844 return 0;
845}
846
837static __be32 nfsd_finish_read(struct svc_rqst *rqstp, struct svc_fh *fhp, 847static __be32 nfsd_finish_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
838 struct file *file, loff_t offset, 848 struct file *file, loff_t offset,
839 unsigned long *count, int host_err) 849 unsigned long *count, u32 *eof, ssize_t host_err)
840{ 850{
841 if (host_err >= 0) { 851 if (host_err >= 0) {
842 nfsdstats.io_read += host_err; 852 nfsdstats.io_read += host_err;
853 *eof = nfsd_eof_on_read(file, offset, host_err, *count);
843 *count = host_err; 854 *count = host_err;
844 fsnotify_access(file); 855 fsnotify_access(file);
845 trace_nfsd_read_io_done(rqstp, fhp, offset, *count); 856 trace_nfsd_read_io_done(rqstp, fhp, offset, *count);
@@ -851,7 +862,8 @@ static __be32 nfsd_finish_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
851} 862}
852 863
853__be32 nfsd_splice_read(struct svc_rqst *rqstp, struct svc_fh *fhp, 864__be32 nfsd_splice_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
854 struct file *file, loff_t offset, unsigned long *count) 865 struct file *file, loff_t offset, unsigned long *count,
866 u32 *eof)
855{ 867{
856 struct splice_desc sd = { 868 struct splice_desc sd = {
857 .len = 0, 869 .len = 0,
@@ -859,25 +871,27 @@ __be32 nfsd_splice_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
859 .pos = offset, 871 .pos = offset,
860 .u.data = rqstp, 872 .u.data = rqstp,
861 }; 873 };
862 int host_err; 874 ssize_t host_err;
863 875
864 trace_nfsd_read_splice(rqstp, fhp, offset, *count); 876 trace_nfsd_read_splice(rqstp, fhp, offset, *count);
865 rqstp->rq_next_page = rqstp->rq_respages + 1; 877 rqstp->rq_next_page = rqstp->rq_respages + 1;
866 host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor); 878 host_err = splice_direct_to_actor(file, &sd, nfsd_direct_splice_actor);
867 return nfsd_finish_read(rqstp, fhp, file, offset, count, host_err); 879 return nfsd_finish_read(rqstp, fhp, file, offset, count, eof, host_err);
868} 880}
869 881
870__be32 nfsd_readv(struct svc_rqst *rqstp, struct svc_fh *fhp, 882__be32 nfsd_readv(struct svc_rqst *rqstp, struct svc_fh *fhp,
871 struct file *file, loff_t offset, 883 struct file *file, loff_t offset,
872 struct kvec *vec, int vlen, unsigned long *count) 884 struct kvec *vec, int vlen, unsigned long *count,
885 u32 *eof)
873{ 886{
874 struct iov_iter iter; 887 struct iov_iter iter;
875 int host_err; 888 loff_t ppos = offset;
889 ssize_t host_err;
876 890
877 trace_nfsd_read_vector(rqstp, fhp, offset, *count); 891 trace_nfsd_read_vector(rqstp, fhp, offset, *count);
878 iov_iter_kvec(&iter, READ, vec, vlen, *count); 892 iov_iter_kvec(&iter, READ, vec, vlen, *count);
879 host_err = vfs_iter_read(file, &iter, &offset, 0); 893 host_err = vfs_iter_read(file, &iter, &ppos, 0);
880 return nfsd_finish_read(rqstp, fhp, file, offset, count, host_err); 894 return nfsd_finish_read(rqstp, fhp, file, offset, count, eof, host_err);
881} 895}
882 896
883/* 897/*
@@ -984,7 +998,8 @@ out_nfserr:
984 * N.B. After this call fhp needs an fh_put 998 * N.B. After this call fhp needs an fh_put
985 */ 999 */
986__be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp, 1000__be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
987 loff_t offset, struct kvec *vec, int vlen, unsigned long *count) 1001 loff_t offset, struct kvec *vec, int vlen, unsigned long *count,
1002 u32 *eof)
988{ 1003{
989 struct nfsd_file *nf; 1004 struct nfsd_file *nf;
990 struct file *file; 1005 struct file *file;
@@ -997,9 +1012,9 @@ __be32 nfsd_read(struct svc_rqst *rqstp, struct svc_fh *fhp,
997 1012
998 file = nf->nf_file; 1013 file = nf->nf_file;
999 if (file->f_op->splice_read && test_bit(RQ_SPLICE_OK, &rqstp->rq_flags)) 1014 if (file->f_op->splice_read && test_bit(RQ_SPLICE_OK, &rqstp->rq_flags))
1000 err = nfsd_splice_read(rqstp, fhp, file, offset, count); 1015 err = nfsd_splice_read(rqstp, fhp, file, offset, count, eof);
1001 else 1016 else
1002 err = nfsd_readv(rqstp, fhp, file, offset, vec, vlen, count); 1017 err = nfsd_readv(rqstp, fhp, file, offset, vec, vlen, count, eof);
1003 1018
1004 nfsd_file_put(nf); 1019 nfsd_file_put(nf);
1005 1020