Skip to content
  • NeilBrown's avatar
    VFS: don't keep disconnected dentries on d_anon · f1ee6162
    NeilBrown authored
    The original purpose of the per-superblock d_anon list was to
    keep disconnected dentries in the cache between consecutive
    requests to the NFS server.  Dentries can be disconnected if
    a client holds a file open and repeatedly performs IO on it,
    and if the server drops the dentry, whether due to memory
    pressure, server restart, or "echo 3 > /proc/sys/vm/drop_caches".
    
    This purpose was thwarted by commit 75a6f82a
    
     ("freeing unlinked
    file indefinitely delayed") which caused disconnected dentries
    to be freed as soon as their refcount reached zero.
    
    This means that, when a dentry being used by nfsd gets disconnected, a
    new one needs to be allocated for every request (unless requests
    overlap).  As the dentry has no name, no parent, and no children,
    there is little of value to cache.  As small memory allocations are
    typically fast (from per-cpu free lists) this likely has little cost.
    
    This means that the original purpose of s_anon is no longer relevant:
    there is no longer any need to keep disconnected dentries on a list so
    they appear to be hashed.
    
    However, s_anon now has a new use.  When you mount an NFS filesystem,
    the dentry stored in s_root is just a placebo.  The "real" root dentry
    is allocated using d_obtain_root() and so it kept on the s_anon list.
    I don't know the reason for this, but suspect it related to NFSv4
    where a mount of "server:/some/path" require NFS to look up the root
    filehandle on the server, then walk down "/some" and "/path" to get
    the filehandle to mount.
    
    Whatever the reason, NFS depends on the s_anon list and on
    shrink_dcache_for_umount() pruning all dentries on this list.  So we
    cannot simply remove s_anon.
    
    We could just leave the code unchanged, but apart from that being
    potentially confusing, the (unfair) bit-spin-lock which protects
    s_anon can become a bottle neck when lots of disconnected dentries are
    being created.
    
    So this patch renames s_anon to s_roots, and stops storing
    disconnected dentries on the list.  Only dentries obtained with
    d_obtain_root() are now stored on this list.  There are many fewer of
    these (only NFS and NILFS2 use the call, and only during filesystem
    mount) so contention on the bit-lock will not be a problem.
    
    Possibly an alternate solution should be found for NFS and NILFS2, but
    that would require understanding their needs first.
    
    Signed-off-by: default avatarNeilBrown <neilb@suse.com>
    Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
    f1ee6162