aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfsd/nfs4xdr.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index d9d7fa94967f..9d76ee311ddc 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -1597,12 +1597,39 @@ nfsd4_opnum_in_range(struct nfsd4_compoundargs *argp, struct nfsd4_op *op)
1597 return true; 1597 return true;
1598} 1598}
1599 1599
1600/*
1601 * Return a rough estimate of the maximum possible reply size. Note the
1602 * estimate includes rpc headers so is meant to be passed to
1603 * svc_reserve, not svc_reserve_auth.
1604 *
1605 * Also note the current compound encoding permits only one operation to
1606 * use pages beyond the first one, so the maximum possible length is the
1607 * maximum over these values, not the sum.
1608 */
1609static int nfsd4_max_reply(u32 opnum)
1610{
1611 switch (opnum) {
1612 case OP_READLINK:
1613 case OP_READDIR:
1614 /*
1615 * Both of these ops take a single page for data and put
1616 * the head and tail in another page:
1617 */
1618 return 2 * PAGE_SIZE;
1619 case OP_READ:
1620 return INT_MAX;
1621 default:
1622 return PAGE_SIZE;
1623 }
1624}
1625
1600static __be32 1626static __be32
1601nfsd4_decode_compound(struct nfsd4_compoundargs *argp) 1627nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1602{ 1628{
1603 DECODE_HEAD; 1629 DECODE_HEAD;
1604 struct nfsd4_op *op; 1630 struct nfsd4_op *op;
1605 bool cachethis = false; 1631 bool cachethis = false;
1632 int max_reply = PAGE_SIZE;
1606 int i; 1633 int i;
1607 1634
1608 READ_BUF(4); 1635 READ_BUF(4);
@@ -1652,10 +1679,14 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp)
1652 * op in the compound wants to be cached: 1679 * op in the compound wants to be cached:
1653 */ 1680 */
1654 cachethis |= nfsd4_cache_this_op(op); 1681 cachethis |= nfsd4_cache_this_op(op);
1682
1683 max_reply = max(max_reply, nfsd4_max_reply(op->opnum));
1655 } 1684 }
1656 /* Sessions make the DRC unnecessary: */ 1685 /* Sessions make the DRC unnecessary: */
1657 if (argp->minorversion) 1686 if (argp->minorversion)
1658 cachethis = false; 1687 cachethis = false;
1688 if (max_reply != INT_MAX)
1689 svc_reserve(argp->rqstp, max_reply);
1659 argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE; 1690 argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE;
1660 1691
1661 DECODE_TAIL; 1692 DECODE_TAIL;