diff options
author | Bryan Schumaker <bjschuma@netapp.com> | 2010-10-21 16:33:18 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-10-23 15:27:37 -0400 |
commit | 82f2e5472e2304e531c2fa85e457f4a71070044e (patch) | |
tree | 45e170b0ec64bcc07e51ae36919ca6cba1163703 /fs/nfs/nfs4xdr.c | |
parent | ae42c70a60fe330d9c2af7c4b92ce78484308e37 (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.c | 55 |
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 | ||
1386 | static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr) | 1386 | static 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); |