@@ -1853,8 +1853,8 @@ static inline u32 nfsd4_read_plus_rsize(struct svc_rqst *rqstp, struct nfsd4_op
{
u32 maxcount = svc_max_payload(rqstp);
u32 rlen = min(op->u.read.rd_length, maxcount);
- /* enough extra xdr space for encoding either a hole or data segment. */
- u32 xdr = 5;
+ /* Extra xdr padding for encoding multiple segments. */
+ u32 xdr = 20;
return (op_encode_hdr_size + 2 + xdr + XDR_QUADLEN(rlen)) * sizeof(__be32);
}
@@ -4152,12 +4152,14 @@ nfsd4_encode_read_plus_data(struct nfsd4_compoundres *resp, struct nfsd4_read *r
err = nfsd4_encode_splice_read(resp, read, file, &maxcount);
else
err = nfsd4_encode_readv(resp, read, file, &maxcount);
+ clear_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags);
*p++ = cpu_to_be32(NFS4_CONTENT_DATA);
p = xdr_encode_hyper(p, read->rd_offset);
*p++ = cpu_to_be32(maxcount);
read->rd_offset += maxcount;
+ read->rd_length -= maxcount;
return err;
}
@@ -4181,6 +4183,10 @@ nfsd4_encode_read_plus_hole(struct nfsd4_compoundres *resp, struct nfsd4_read *r
p = xdr_encode_hyper(p, maxcount);
read->rd_offset += maxcount;
+ if (maxcount > read->rd_length)
+ read->rd_length = 0;
+ else
+ read->rd_length -= maxcount;
return nfs_ok;
}
@@ -4210,17 +4216,20 @@ nfsd4_encode_read_plus(struct nfsd4_compoundres *resp, __be32 nfserr,
if (read->rd_tmp_file)
ra = nfsd_init_raparms(file);
- hole_pos = vfs_llseek(file, read->rd_offset, SEEK_HOLE);
- if (hole_pos == -ENXIO)
- goto out_encode;
+ do {
+ hole_pos = vfs_llseek(file, read->rd_offset, SEEK_HOLE);
+ if (hole_pos == -ENXIO)
+ break;
- if (hole_pos == read->rd_offset)
- nfserr = nfsd4_encode_read_plus_hole(resp, read, file);
- else
- nfserr = nfsd4_encode_read_plus_data(resp, read, file, hole_pos);
- segments++;
+ if (hole_pos == read->rd_offset)
+ nfserr = nfsd4_encode_read_plus_hole(resp, read, file);
+ else
+ nfserr = nfsd4_encode_read_plus_data(resp, read, file, hole_pos);
+ if (nfserr)
+ break;
+ segments++;
+ } while (read->rd_length > 0);
-out_encode:
eof = (read->rd_offset >= i_size_read(file_inode(file)));
*p++ = cpu_to_be32(eof);
*p++ = cpu_to_be32(segments);
This patch implements sending an array of segments back to the client. Clients should be prepared to handle multiple segment reads to make this useful. We try to splice the first data segment into the XDR result, and remaining segments are encoded directly. Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com> --- fs/nfsd/nfs4proc.c | 4 ++-- fs/nfsd/nfs4xdr.c | 27 ++++++++++++++++++--------- 2 files changed, 20 insertions(+), 11 deletions(-)