aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs4xdr.c
diff options
context:
space:
mode:
authorBryan Schumaker <bjschuma@netapp.com>2010-10-21 16:33:18 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-10-23 15:27:37 -0400
commit82f2e5472e2304e531c2fa85e457f4a71070044e (patch)
tree45e170b0ec64bcc07e51ae36919ca6cba1163703 /fs/nfs/nfs4xdr.c
parentae42c70a60fe330d9c2af7c4b92ce78484308e37 (diff)
NFS: Readdir plus in v4
By requsting more attributes during a readdir, we can mimic the readdir plus operation that was in NFSv3. To test, I ran the command `ls -lU --color=none` on directories with various numbers of files. Without readdir plus, I see this: n files | 100 | 1,000 | 10,000 | 100,000 | 1,000,000 --------+-----------+-----------+-----------+-----------+---------- real | 0m00.153s | 0m00.589s | 0m05.601s | 0m56.691s | 9m59.128s user | 0m00.007s | 0m00.007s | 0m00.077s | 0m00.703s | 0m06.800s sys | 0m00.010s | 0m00.070s | 0m00.633s | 0m06.423s | 1m10.005s access | 3 | 1 | 1 | 4 | 31 getattr | 2 | 1 | 1 | 1 | 1 lookup | 104 | 1,003 | 10,003 | 100,003 | 1,000,003 readdir | 2 | 16 | 158 | 1,575 | 15,749 total | 111 | 1,021 | 10,163 | 101,583 | 1,015,784 With readdir plus enabled, I see this: n files | 100 | 1,000 | 10,000 | 100,000 | 1,000,000 --------+-----------+-----------+-----------+-----------+---------- real | 0m00.115s | 0m00.206s | 0m01.079s | 0m12.521s | 2m07.528s user | 0m00.003s | 0m00.003s | 0m00.040s | 0m00.290s | 0m03.296s sys | 0m00.007s | 0m00.020s | 0m00.120s | 0m01.357s | 0m17.556s access | 3 | 1 | 1 | 1 | 7 getattr | 2 | 1 | 1 | 1 | 1 lookup | 4 | 3 | 3 | 3 | 3 readdir | 6 | 62 | 630 | 6,300 | 62,993 total | 15 | 67 | 635 | 6,305 | 63,004 Readdir plus disabled has about a 16x increase in the number of rpc calls and is 4 - 5 times slower on large directories. Signed-off-by: Bryan Schumaker <bjschuma@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
-rw-r--r--fs/nfs/nfs4xdr.c55
1 files changed, 27 insertions, 28 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c
index b7eff205d3d8..ccfb1c92b262 100644
--- a/fs/nfs/nfs4xdr.c
+++ b/fs/nfs/nfs4xdr.c
@@ -1385,12 +1385,20 @@ static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args,
1385 1385
1386static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) 1386static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr)
1387{ 1387{
1388 uint32_t attrs[2] = { 1388 uint32_t attrs[2] = {0, 0};
1389 FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID,
1390 FATTR4_WORD1_MOUNTED_ON_FILEID,
1391 };
1392 __be32 *p; 1389 __be32 *p;
1393 1390
1391 if (readdir->plus) {
1392 attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE|
1393 FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE;
1394 attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER|
1395 FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV|
1396 FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS|
1397 FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
1398 }
1399 attrs[0] |= FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID;
1400 attrs[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID;
1401
1394 p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20); 1402 p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20);
1395 *p++ = cpu_to_be32(OP_READDIR); 1403 *p++ = cpu_to_be32(OP_READDIR);
1396 p = xdr_encode_hyper(p, readdir->cookie); 1404 p = xdr_encode_hyper(p, readdir->cookie);
@@ -1398,11 +1406,15 @@ static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg
1398 *p++ = cpu_to_be32(readdir->count >> 1); /* We're not doing readdirplus */ 1406 *p++ = cpu_to_be32(readdir->count >> 1); /* We're not doing readdirplus */
1399 *p++ = cpu_to_be32(readdir->count); 1407 *p++ = cpu_to_be32(readdir->count);
1400 *p++ = cpu_to_be32(2); 1408 *p++ = cpu_to_be32(2);
1401 /* Switch to mounted_on_fileid if the server supports it */ 1409
1402 if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID) 1410 if (!readdir->plus) {
1403 attrs[0] &= ~FATTR4_WORD0_FILEID; 1411 /* Switch to mounted_on_fileid if the server supports it */
1404 else 1412 if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
1405 attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID; 1413 attrs[0] &= ~FATTR4_WORD0_FILEID;
1414 else
1415 attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
1416 }
1417
1406 *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]); 1418 *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]);
1407 *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]); 1419 *p = cpu_to_be32(attrs[1] & readdir->bitmask[1]);
1408 hdr->nops++; 1420 hdr->nops++;
@@ -5768,7 +5780,8 @@ static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp, uint32_t *p,
5768} 5780}
5769#endif /* CONFIG_NFS_V4_1 */ 5781#endif /* CONFIG_NFS_V4_1 */
5770 5782
5771__be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, int plus) 5783__be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
5784 struct nfs_server *server, int plus)
5772{ 5785{
5773 uint32_t bitmap[2] = {0}; 5786 uint32_t bitmap[2] = {0};
5774 uint32_t len; 5787 uint32_t len;
@@ -5824,24 +5837,10 @@ __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, int
5824 goto out_overflow; 5837 goto out_overflow;
5825 len = XDR_QUADLEN(ntohl(*p++)); /* attribute buffer length */ 5838 len = XDR_QUADLEN(ntohl(*p++)); /* attribute buffer length */
5826 if (len > 0) { 5839 if (len > 0) {
5827 if (bitmap[0] & FATTR4_WORD0_RDATTR_ERROR) { 5840 if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, server, 1) < 0)
5828 bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR; 5841 goto out_overflow;
5829 /* Ignore the return value of rdattr_error for now */ 5842 if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID)
5830 p = xdr_inline_decode(xdr, 4); 5843 entry->ino = entry->fattr->fileid;
5831 if (unlikely(!p))
5832 goto out_overflow;
5833 }
5834 if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID) {
5835 p = xdr_inline_decode(xdr, 8);
5836 if (unlikely(!p))
5837 goto out_overflow;
5838 xdr_decode_hyper(p, &entry->ino);
5839 } else if (bitmap[0] == FATTR4_WORD0_FILEID) {
5840 p = xdr_inline_decode(xdr, 8);
5841 if (unlikely(!p))
5842 goto out_overflow;
5843 xdr_decode_hyper(p, &entry->ino);
5844 }
5845 } 5844 }
5846 5845
5847 p = xdr_inline_peek(xdr, 8); 5846 p = xdr_inline_peek(xdr, 8);