diff options
author | J. Bruce Fields <bfields@redhat.com> | 2014-03-11 15:39:13 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-05-30 17:31:57 -0400 |
commit | 4f0cefbf389c28b0a2be34960797adb0c84ee43d (patch) | |
tree | 8ef1923fa15d4e2372e73e48df203facc4085c7c /fs/nfsd | |
parent | 8c7424cff6bd33459945646cfcbf6dc6c899ab24 (diff) |
nfsd4: more precise nfsd4_max_reply
It will turn out to be useful to have a more accurate estimate of reply
size; so, piggyback on the existing op reply-size estimators.
Also move nfsd4_max_reply to nfs4proc.c to get easier access to struct
nfsd4_operation and friends. (Thanks to Christoph Hellwig for pointing
out that simplification.)
Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd')
-rw-r--r-- | fs/nfsd/nfs4proc.c | 12 | ||||
-rw-r--r-- | fs/nfsd/nfs4xdr.c | 35 | ||||
-rw-r--r-- | fs/nfsd/xdr4.h | 1 |
3 files changed, 17 insertions, 31 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c index 20aad5a3005f..59c319528cf9 100644 --- a/fs/nfsd/nfs4proc.c +++ b/fs/nfsd/nfs4proc.c | |||
@@ -1854,6 +1854,18 @@ static struct nfsd4_operation nfsd4_ops[] = { | |||
1854 | }, | 1854 | }, |
1855 | }; | 1855 | }; |
1856 | 1856 | ||
1857 | int nfsd4_max_reply(struct svc_rqst *rqstp, struct nfsd4_op *op) | ||
1858 | { | ||
1859 | struct nfsd4_operation *opdesc; | ||
1860 | nfsd4op_rsize estimator; | ||
1861 | |||
1862 | if (op->opnum == OP_ILLEGAL) | ||
1863 | return op_encode_hdr_size * sizeof(__be32); | ||
1864 | opdesc = OPDESC(op); | ||
1865 | estimator = opdesc->op_rsize_bop; | ||
1866 | return estimator ? estimator(rqstp, op) : PAGE_SIZE; | ||
1867 | } | ||
1868 | |||
1857 | void warn_on_nonidempotent_op(struct nfsd4_op *op) | 1869 | void warn_on_nonidempotent_op(struct nfsd4_op *op) |
1858 | { | 1870 | { |
1859 | if (OPDESC(op)->op_flags & OP_MODIFIES_SOMETHING) { | 1871 | if (OPDESC(op)->op_flags & OP_MODIFIES_SOMETHING) { |
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 2f0ea20edb23..8b3d24de9cac 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c | |||
@@ -1605,40 +1605,13 @@ nfsd4_opnum_in_range(struct nfsd4_compoundargs *argp, struct nfsd4_op *op) | |||
1605 | return true; | 1605 | return true; |
1606 | } | 1606 | } |
1607 | 1607 | ||
1608 | /* | ||
1609 | * Return a rough estimate of the maximum possible reply size. Note the | ||
1610 | * estimate includes rpc headers so is meant to be passed to | ||
1611 | * svc_reserve, not svc_reserve_auth. | ||
1612 | * | ||
1613 | * Also note the current compound encoding permits only one operation to | ||
1614 | * use pages beyond the first one, so the maximum possible length is the | ||
1615 | * maximum over these values, not the sum. | ||
1616 | */ | ||
1617 | static int nfsd4_max_reply(u32 opnum) | ||
1618 | { | ||
1619 | switch (opnum) { | ||
1620 | case OP_READLINK: | ||
1621 | case OP_READDIR: | ||
1622 | /* | ||
1623 | * Both of these ops take a single page for data and put | ||
1624 | * the head and tail in another page: | ||
1625 | */ | ||
1626 | return 2 * PAGE_SIZE; | ||
1627 | case OP_GETATTR: | ||
1628 | case OP_READ: | ||
1629 | return INT_MAX; | ||
1630 | default: | ||
1631 | return PAGE_SIZE; | ||
1632 | } | ||
1633 | } | ||
1634 | |||
1635 | static __be32 | 1608 | static __be32 |
1636 | nfsd4_decode_compound(struct nfsd4_compoundargs *argp) | 1609 | nfsd4_decode_compound(struct nfsd4_compoundargs *argp) |
1637 | { | 1610 | { |
1638 | DECODE_HEAD; | 1611 | DECODE_HEAD; |
1639 | struct nfsd4_op *op; | 1612 | struct nfsd4_op *op; |
1640 | bool cachethis = false; | 1613 | bool cachethis = false; |
1641 | int max_reply = PAGE_SIZE; | 1614 | int max_reply = 2 * RPC_MAX_AUTH_SIZE + 8; /* opcnt, status */ |
1642 | int i; | 1615 | int i; |
1643 | 1616 | ||
1644 | READ_BUF(4); | 1617 | READ_BUF(4); |
@@ -1647,6 +1620,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) | |||
1647 | SAVEMEM(argp->tag, argp->taglen); | 1620 | SAVEMEM(argp->tag, argp->taglen); |
1648 | READ32(argp->minorversion); | 1621 | READ32(argp->minorversion); |
1649 | READ32(argp->opcnt); | 1622 | READ32(argp->opcnt); |
1623 | max_reply += 4 + (XDR_QUADLEN(argp->taglen) << 2); | ||
1650 | 1624 | ||
1651 | if (argp->taglen > NFSD4_MAX_TAGLEN) | 1625 | if (argp->taglen > NFSD4_MAX_TAGLEN) |
1652 | goto xdr_error; | 1626 | goto xdr_error; |
@@ -1684,7 +1658,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) | |||
1684 | */ | 1658 | */ |
1685 | cachethis |= nfsd4_cache_this_op(op); | 1659 | cachethis |= nfsd4_cache_this_op(op); |
1686 | 1660 | ||
1687 | max_reply = max(max_reply, nfsd4_max_reply(op->opnum)); | 1661 | max_reply += nfsd4_max_reply(argp->rqstp, op); |
1688 | 1662 | ||
1689 | if (op->status) { | 1663 | if (op->status) { |
1690 | argp->opcnt = i+1; | 1664 | argp->opcnt = i+1; |
@@ -1694,8 +1668,7 @@ nfsd4_decode_compound(struct nfsd4_compoundargs *argp) | |||
1694 | /* Sessions make the DRC unnecessary: */ | 1668 | /* Sessions make the DRC unnecessary: */ |
1695 | if (argp->minorversion) | 1669 | if (argp->minorversion) |
1696 | cachethis = false; | 1670 | cachethis = false; |
1697 | if (max_reply != INT_MAX) | 1671 | svc_reserve(argp->rqstp, max_reply); |
1698 | svc_reserve(argp->rqstp, max_reply); | ||
1699 | argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE; | 1672 | argp->rqstp->rq_cachetype = cachethis ? RC_REPLBUFF : RC_NOCACHE; |
1700 | 1673 | ||
1701 | DECODE_TAIL; | 1674 | DECODE_TAIL; |
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h index ee9ffdc8a0cb..41e522993d94 100644 --- a/fs/nfsd/xdr4.h +++ b/fs/nfsd/xdr4.h | |||
@@ -536,6 +536,7 @@ static inline bool nfsd4_last_compound_op(struct svc_rqst *rqstp) | |||
536 | return argp->opcnt == resp->opcnt; | 536 | return argp->opcnt == resp->opcnt; |
537 | } | 537 | } |
538 | 538 | ||
539 | int nfsd4_max_reply(struct svc_rqst *rqstp, struct nfsd4_op *op); | ||
539 | void warn_on_nonidempotent_op(struct nfsd4_op *op); | 540 | void warn_on_nonidempotent_op(struct nfsd4_op *op); |
540 | 541 | ||
541 | #define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs) | 542 | #define NFS4_SVC_XDRSIZE sizeof(struct nfsd4_compoundargs) |