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>
This commit is contained in:

committed by
J. Bruce Fields

parent
65643f4c82
commit
83a63072c8
@@ -3472,7 +3472,7 @@ static __be32 nfsd4_encode_splice_read(
|
||||
|
||||
len = maxcount;
|
||||
nfserr = nfsd_splice_read(read->rd_rqstp, read->rd_fhp,
|
||||
file, read->rd_offset, &maxcount);
|
||||
file, read->rd_offset, &maxcount, &eof);
|
||||
read->rd_length = maxcount;
|
||||
if (nfserr) {
|
||||
/*
|
||||
@@ -3484,9 +3484,6 @@ static __be32 nfsd4_encode_splice_read(
|
||||
return nfserr;
|
||||
}
|
||||
|
||||
eof = nfsd_eof_on_read(len, maxcount, read->rd_offset,
|
||||
d_inode(read->rd_fhp->fh_dentry)->i_size);
|
||||
|
||||
*(p++) = htonl(eof);
|
||||
*(p++) = htonl(maxcount);
|
||||
|
||||
@@ -3557,15 +3554,13 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,
|
||||
|
||||
len = maxcount;
|
||||
nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset,
|
||||
resp->rqstp->rq_vec, read->rd_vlen, &maxcount);
|
||||
resp->rqstp->rq_vec, read->rd_vlen, &maxcount,
|
||||
&eof);
|
||||
read->rd_length = maxcount;
|
||||
if (nfserr)
|
||||
return nfserr;
|
||||
xdr_truncate_encode(xdr, starting_len + 8 + ((maxcount+3)&~3));
|
||||
|
||||
eof = nfsd_eof_on_read(len, maxcount, read->rd_offset,
|
||||
d_inode(read->rd_fhp->fh_dentry)->i_size);
|
||||
|
||||
tmp = htonl(eof);
|
||||
write_bytes_to_xdr_buf(xdr->buf, starting_len , &tmp, 4);
|
||||
tmp = htonl(maxcount);
|
||||
|
Reference in New Issue
Block a user