aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@redhat.com>2014-03-23 12:01:48 -0400
committerJ. Bruce Fields <bfields@redhat.com>2014-05-30 17:32:06 -0400
commitb86cef60dafcbdf5a19adfa990c2c1672222e677 (patch)
tree46e1a02bc88ba8f9c56f1c9613bb0092448d4783
parent476a7b1f4b2c9c38255653fa55157565be8b14be (diff)
nfsd4: better estimate of getattr response size
We plan to use this estimate to decide whether or not to allow zero-copy reads. Currently we're assuming all getattr's are a page, which can be both too small (ACLs e.g. may be arbitrarily long) and too large (after an upcoming read patch this will unnecessarily prevent zero copy reads in any read compound also containing a getattr). Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r--fs/nfsd/nfs4proc.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index d95d9015e50a..7507effc7c42 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1465,6 +1465,49 @@ static inline u32 nfsd4_create_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op
1465 + nfs4_fattr_bitmap_maxsz) * sizeof(__be32); 1465 + nfs4_fattr_bitmap_maxsz) * sizeof(__be32);
1466} 1466}
1467 1467
1468/*
1469 * Note since this is an idempotent operation we won't insist on failing
1470 * the op prematurely if the estimate is too large. We may turn off splice
1471 * reads unnecessarily.
1472 */
1473static inline u32 nfsd4_getattr_rsize(struct svc_rqst *rqstp,
1474 struct nfsd4_op *op)
1475{
1476 u32 *bmap = op->u.getattr.ga_bmval;
1477 u32 bmap0 = bmap[0], bmap1 = bmap[1], bmap2 = bmap[2];
1478 u32 ret = 0;
1479
1480 if (bmap0 & FATTR4_WORD0_ACL)
1481 return svc_max_payload(rqstp);
1482 if (bmap0 & FATTR4_WORD0_FS_LOCATIONS)
1483 return svc_max_payload(rqstp);
1484
1485 if (bmap1 & FATTR4_WORD1_OWNER) {
1486 ret += IDMAP_NAMESZ + 4;
1487 bmap1 &= ~FATTR4_WORD1_OWNER;
1488 }
1489 if (bmap1 & FATTR4_WORD1_OWNER_GROUP) {
1490 ret += IDMAP_NAMESZ + 4;
1491 bmap1 &= ~FATTR4_WORD1_OWNER_GROUP;
1492 }
1493 if (bmap0 & FATTR4_WORD0_FILEHANDLE) {
1494 ret += NFS4_FHSIZE + 4;
1495 bmap0 &= ~FATTR4_WORD0_FILEHANDLE;
1496 }
1497 if (bmap2 & FATTR4_WORD2_SECURITY_LABEL) {
1498 ret += NFSD4_MAX_SEC_LABEL_LEN + 12;
1499 bmap2 &= ~FATTR4_WORD2_SECURITY_LABEL;
1500 }
1501 /*
1502 * Largest of remaining attributes are 16 bytes (e.g.,
1503 * supported_attributes)
1504 */
1505 ret += 16 * (hweight32(bmap0) + hweight32(bmap1) + hweight32(bmap2));
1506 /* bitmask, length */
1507 ret += 20;
1508 return ret;
1509}
1510
1468static inline u32 nfsd4_link_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op) 1511static inline u32 nfsd4_link_rsize(struct svc_rqst *rqstp, struct nfsd4_op *op)
1469{ 1512{
1470 return (op_encode_hdr_size + op_encode_change_info_maxsz) 1513 return (op_encode_hdr_size + op_encode_change_info_maxsz)
@@ -1603,6 +1646,7 @@ static struct nfsd4_operation nfsd4_ops[] = {
1603 [OP_GETATTR] = { 1646 [OP_GETATTR] = {
1604 .op_func = (nfsd4op_func)nfsd4_getattr, 1647 .op_func = (nfsd4op_func)nfsd4_getattr,
1605 .op_flags = ALLOWED_ON_ABSENT_FS, 1648 .op_flags = ALLOWED_ON_ABSENT_FS,
1649 .op_rsize_bop = nfsd4_getattr_rsize,
1606 .op_name = "OP_GETATTR", 1650 .op_name = "OP_GETATTR",
1607 }, 1651 },
1608 [OP_GETFH] = { 1652 [OP_GETFH] = {