Skip to content
  1. Jun 04, 2014
  2. Jun 03, 2014
  3. Jun 02, 2014
  4. May 31, 2014
    • Linus Torvalds's avatar
      dcache: add missing lockdep annotation · 9f12600f
      Linus Torvalds authored
      
      
      lock_parent() very much on purpose does nested locking of dentries, and
      is careful to maintain the right order (lock parent first).  But because
      it didn't annotate the nested locking order, lockdep thought it might be
      a deadlock on d_lock, and complained.
      
      Add the proper annotation for the inner locking of the child dentry to
      make lockdep happy.
      
      Introduced by commit 046b961b ("shrink_dentry_list(): take parent's
      ->d_lock earlier").
      
      Reported-and-tested-by: default avatarJosh Boyer <jwboyer@fedoraproject.org>
      Cc: Al Viro <viro@zeniv.linux.org.uk>
      Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
      9f12600f
  5. May 30, 2014
    • Al Viro's avatar
      dentry_kill() doesn't need the second argument now · 8cbf74da
      Al Viro authored
      
      
      it's 1 in the only remaining caller.
      
      Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
      8cbf74da
    • Al Viro's avatar
      dealing with the rest of shrink_dentry_list() livelock · b2b80195
      Al Viro authored
      
      
      We have the same problem with ->d_lock order in the inner loop, where
      we are dropping references to ancestors.  Same solution, basically -
      instead of using dentry_kill() we use lock_parent() (introduced in the
      previous commit) to get that lock in a safe way, recheck ->d_count
      (in case if lock_parent() has ended up dropping and retaking ->d_lock
      and somebody managed to grab a reference during that window), trylock
      the inode->i_lock and use __dentry_kill() to do the rest.
      
      Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
      b2b80195
    • Al Viro's avatar
      shrink_dentry_list(): take parent's ->d_lock earlier · 046b961b
      Al Viro authored
      
      
      The cause of livelocks there is that we are taking ->d_lock on
      dentry and its parent in the wrong order, forcing us to use
      trylock on the parent's one.  d_walk() takes them in the right
      order, and unfortunately it's not hard to create a situation
      when shrink_dentry_list() can't make progress since trylock
      keeps failing, and shrink_dcache_parent() or check_submounts_and_drop()
      keeps calling d_walk() disrupting the very shrink_dentry_list() it's
      waiting for.
      
      Solution is straightforward - if that trylock fails, let's unlock
      the dentry itself and take locks in the right order.  We need to
      stabilize ->d_parent without holding ->d_lock, but that's doable
      using RCU.  And we'd better do that in the very beginning of the
      loop in shrink_dentry_list(), since the checks on refcount, etc.
      would need to be redone anyway.
      
      That deals with a half of the problem - killing dentries on the
      shrink list itself.  Another one (dropping their parents) is
      in the next commit.
      
      locking parent is interesting - it would be easy to do rcu_read_lock(),
      lock whatever we think is a parent, lock dentry itself and check
      if the parent is still the right one.  Except that we need to check
      that *before* locking the dentry, or we are risking taking ->d_lock
      out of order.  Fortunately, once the D1 is locked, we can check if
      D2->d_parent is equal to D1 without the need to lock D2; D2->d_parent
      can start or stop pointing to D1 only under D1->d_lock, so taking
      D1->d_lock is enough.  In other words, the right solution is
      rcu_read_lock/lock what looks like parent right now/check if it's
      still our parent/rcu_read_unlock/lock the child.
      
      Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
      046b961b
  6. May 29, 2014
  7. May 28, 2014
Loading