aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4xdr.c21
1 files changed, 17 insertions, 4 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index cda6226bda91..f6a5cb722697 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1612,6 +1612,8 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1612 struct nfsd4_op *op; 1612 struct nfsd4_op *op;
1613 bool cachethis = false; 1613 bool cachethis = false;
1614 int max_reply = 2 * RPC_MAX_AUTH_SIZE + 8; /* opcnt, status */ 1614 int max_reply = 2 * RPC_MAX_AUTH_SIZE + 8; /* opcnt, status */
1615 int readcount = 0;
1616 int readbytes = 0;
1615 int i; 1617 int i;
1616 1618
1617 READ_BUF(4); 1619 READ_BUF(4);
@@ -1658,7 +1660,11 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1658 */ 1660 */
1659 cachethis |= nfsd4_cache_this_op(op); 1661 cachethis |= nfsd4_cache_this_op(op);
1660 1662
1661 max_reply += nfsd4_max_reply(argp->rqstp, op); 1663 if (op->opnum == OP_READ) {
1664 readcount++;
1665 readbytes += nfsd4_max_reply(argp->rqstp, op);
1666 } else
1667 max_reply += nfsd4_max_reply(argp->rqstp, op);
1662 1668
1663 if (op->status) { 1669 if (op->status) {
1664 argp->opcnt = i+1; 1670 argp->opcnt = i+1;
@@ -1668,9 +1674,12 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1668 /* Sessions make the DRC unnecessary: */ 1674 /* Sessions make the DRC unnecessary: */
1669 if (argp->minorversion) 1675 if (argp->minorversion)
1670 cachethis = false; 1676 cachethis = false;
1671 svc_reserve(argp->rqstp, max_reply); 1677 svc_reserve(argp->rqstp, max_reply + readbytes);
1672 argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE; 1678 argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE;
1673 1679
1680 if (readcount > 1 || max_reply > PAGE_SIZE - 2*RPC_MAX_AUTH_SIZE)
1681 argp->rqstp->rq_splice_ok = false;
1682
1674 DECODE_TAIL; 1683 DECODE_TAIL;
1675} 1684}
1676 1685
@@ -3078,15 +3087,19 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,
3078 return nfserr; 3087 return nfserr;
3079 3088
3080 p = xdr_reserve_space(xdr, 8); /* eof flag and byte count */ 3089 p = xdr_reserve_space(xdr, 8); /* eof flag and byte count */
3081 if (!p) 3090 if (!p) {
3091 WARN_ON_ONCE(resp->rqstp->rq_splice_ok);
3082 return nfserr_resource; 3092 return nfserr_resource;
3093 }
3083 3094
3084 /* Make sure there will be room for padding if needed: */ 3095 /* Make sure there will be room for padding if needed: */
3085 if (xdr->end - xdr->p < 1) 3096 if (xdr->end - xdr->p < 1)
3086 return nfserr_resource; 3097 return nfserr_resource;
3087 3098
3088 if (resp->xdr.buf->page_len) 3099 if (resp->xdr.buf->page_len) {
3100 WARN_ON_ONCE(resp->rqstp->rq_splice_ok);
3089 return nfserr_resource; 3101 return nfserr_resource;
3102 }
3090 3103
3091 maxcount = svc_max_payload(resp->rqstp); 3104 maxcount = svc_max_payload(resp->rqstp);
3092 if (maxcount > read->rd_length) 3105 if (maxcount > read->rd_length)