• Benjamin Coddington's avatar
    NFS: switch back to to ->iterate() · b044f645
    Benjamin Coddington authored
    NFS has some optimizations for readdir to choose between using READDIR or
    READDIRPLUS based on workload, and which NFS operation to use is determined
    by subsequent interactions with lookup, d_revalidate, and getattr.
    
    Concurrent use of nfs_readdir() via ->iterate_shared() can cause those
    optimizations to repeatedly invalidate the pagecache used to store
    directory entries during readdir(), which causes some very bad performance
    for directories with many entries (more than about 10000).
    
    There's a couple ways to fix this in NFS, but no fix would be as simple as
    going back to ->iterate() to serialize nfs_readdir(), and neither fix I
    tested performed as well as going back to ->iterate().
    
    The first required taking the directory's i_lock for each entry, with the
    result of terrible contention.
    
    The second way adds another flag to the nfs_inode, and so keeps the
    optimizations working for large directories.  The difference from using
    ->iterate() here is that much more memory is consumed for a given workload
    without any performance gain.
    
    The workings of nfs_readdir() are such that concurrent users are serialized
    within read_cache_page() waiting to retrieve pages of entries from the
    server.  By serializing this work in iterate_dir() instead, contention for
    cache pages is reduced.  Waiting processes can have an uncontended pass at
    the entirety of the directory's pagecache once previous processes have
    completed filling it.
    
    v2 - Keep the bits needed for parallel lookup
    Signed-off-by: default avatarBenjamin Coddington <bcodding@redhat.com>
    Signed-off-by: default avatarTrond Myklebust <trond.myklebust@primarydata.com>
    b044f645
dir.c 64.4 KB