Skip to content
  • Linus Torvalds's avatar
    vfs: get rid of insane dentry hashing rules · dea3667b
    Linus Torvalds authored
    The dentry hashing rules have been really quite complicated for a long
    while, in odd ways.  That made functions like __d_drop() very fragile
    and non-obvious.
    
    In particular, whether a dentry was hashed or not was indicated with an
    explicit DCACHE_UNHASHED bit.  That's despite the fact that the hash
    abstraction that the dentries use actually have a 'is this entry hashed
    or not' model (which is a simple test of the 'pprev' pointer).
    
    The reason that was done is because we used the normal 'is this entry
    unhashed' model to mark whether the dentry had _ever_ been hashed in the
    dentry hash tables, and that logic goes back many years (commit
    b3423415
    
    : "dcache: avoid RCU for never-hashed dentries").
    
    That, in turn, meant that __d_drop had totally different unhashing logic
    for the dentry hash table case and for the anonymous dcache case,
    because in order to use the "is this dentry hashed" logic as a flag for
    whether it had ever been on the RCU hash table, we had to unhash such a
    dentry differently so that we'd never think that it wasn't 'unhashed'
    and wouldn't be free'd correctly.
    
    That's just insane.  It made the logic really hard to follow, when there
    were two different kinds of "unhashed" states, and one of them (the one
    that used "list_bl_unhashed()") really had nothing at all to do with
    being unhashed per se, but with a very subtle lifetime rule instead.
    
    So turn all of it around, and make it logical.
    
    Instead of having a DENTRY_UNHASHED bit in d_flags to indicate whether
    the dentry is on the hash chains or not, use the hash chain unhashed
    logic for that.  Suddenly "d_unhashed()" just uses "list_bl_unhashed()",
    and everything makes sense.
    
    And for the lifetime rule, just use an explicit DENTRY_RCUACCEES bit.
    If we ever insert the dentry into the dentry hash table so that it is
    visible to RCU lookup, we mark it DENTRY_RCUACCESS to show that it now
    needs the RCU lifetime rules.  Now suddently that test at dentry free
    time makes sense too.
    
    And because unhashing now is sane and doesn't depend on where the dentry
    got unhashed from (because the dentry hash chain details doesn't have
    some subtle side effects), we can re-unify the __d_drop() logic and use
    common code for the unhashing.
    
    Also fix one more open-coded hash chain bit_spin_lock() that I missed in
    the previous chain locking cleanup commit.
    
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    dea3667b