summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorNeilBrown <neilb@suse.de>2015-05-08 13:10:40 +1000
committerTrond Myklebust <trond.myklebust@primarydata.com>2015-06-02 08:55:27 -0400
commit7ef5ca4fe41e6a51d9bdcbbf7c66f203675e8500 (patch)
treee6c6d1c377d0d379a85b2467122001b5e8c6e50b /fs
parent5cae02f42793130e1387f4ec09c4d07056ce9fa5 (diff)
downloadop-kernel-dev-7ef5ca4fe41e6a51d9bdcbbf7c66f203675e8500.zip
op-kernel-dev-7ef5ca4fe41e6a51d9bdcbbf7c66f203675e8500.tar.gz
NFS: report more appropriate block size for directories.
In glibc 2.21 (and several previous), a call to opendir() will result in a 32K (BUFSIZ*4) buffer being allocated and passed to getdents. However a call to fdopendir() results in an 'fstat' request to determine block size and a matching buffer allocated for subsequent use with getdents. This will typically be 1M. The first getdents call on an NFS directory will always use READDIR_PLUS (or NFSv4 equivalent) if available. Subsequent getdents calls only use this more expensive version if some 'stat' requests are made between the getdents calls. For this reason it is good to keep at least that first getdents call relatively short. When fdopendir() and readdir() is used on a large directory, it takes approximately 32 times as long to complete as using "opendir". Current versions of 'find' use fdopendir() and demonstrate this slowness. 'stat' on a directory currently returns the 'wsize'. This number has no meaning on directories. Actual READDIR requests are limited to ->dtsize, which itself is capped at 4 pages, coincidently the same as BUFSIZ*4. So this is a meaningful number to use as the blocksize on directories, and has the effect of making 'find' on large directories go a lot faster. Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/inode.c2
1 files changed, 2 insertions, 0 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index f734562..14b4709 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -678,6 +678,8 @@ int nfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
if (!err) {
generic_fillattr(inode, stat);
stat->ino = nfs_compat_user_ino64(NFS_FILEID(inode));
+ if (S_ISDIR(inode->i_mode))
+ stat->blksize = NFS_SERVER(inode)->dtsize;
}
out:
trace_nfs_getattr_exit(inode, err);
OpenPOWER on IntegriCloud