NFS: report more appropriate block size for directories.
authorNeilBrown <neilb@suse.de>
Fri, 8 May 2015 03:10:40 +0000 (13:10 +1000)
committerTrond Myklebust <trond.myklebust@primarydata.com>
Tue, 2 Jun 2015 12:55:27 +0000 (08:55 -0400)
commit7ef5ca4fe41e6a51d9bdcbbf7c66f203675e8500
treee6c6d1c377d0d379a85b2467122001b5e8c6e50b
parent5cae02f42793130e1387f4ec09c4d07056ce9fa5
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>
fs/nfs/inode.c