aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4xdr.c
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2013-11-05 15:07:16 -0500
committerJ. Bruce Fields <bfields@redhat.com>2013-11-13 16:12:54 -0500
commit6ff40decff0ef35a5d755ec60182d7f803356dfb (patch)
tree1dc4117cbd90e5b560d0ba1d8575148d03f0e844 /fs/nfsd/nfs4xdr.c
parent587ac5ee6f9f912926abe34bb323c6f87d53f137 (diff)
nfsd4: improve write performance with better sendspace reservations
Currently the rpc code conservatively refuses to accept rpc's from a client if the sum of its worst-case estimates of the replies it owes that client exceed the send buffer space. Unfortunately our estimate of the worst-case reply for an NFSv4 compound is always the maximum read size. This can unnecessarily limit the number of operations we handle concurrently, for example in the case most operations are writes (which have small replies). We can do a little better if we check which ops the compound contains. This is still a rough estimate, we'll need to improve on it some day. Reported-by: Shyam Kaushik <shyamnfs1@gmail.com> Tested-by: Shyam Kaushik <shyamnfs1@gmail.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
-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;