Pull dropping ->d_lock on lock_for_kill() failure into lock_for_kill() itself. That reduces dentry_kill() to if (!lock_for_kill(dentry)) return NULL; return __dentry_kill(dentry); at which point it's easier to move that if (...) into the beginning of __dentry_kill() itself and rename it into dentry_kill(). Document the new calling conventions of lock_for_kill(). Signed-off-by: Al Viro --- fs/dcache.c | 99 +++++++++++++++++++++++++++-------------------------- 1 file changed, 50 insertions(+), 49 deletions(-) diff --git a/fs/dcache.c b/fs/dcache.c index 6822e8bfc6af..125f280fe6ee 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -691,11 +691,60 @@ static inline void dentry_unlist(struct dentry *dentry) } } -static struct dentry *__dentry_kill(struct dentry *dentry) +/* + * Prepare locking environment for killing a dentry. + * Called under dentry->d_lock. To proceed with eviction of a positive + * dentry we need to get ->i_lock of dentry inode as well and that + * needs to be done carefully - ->i_lock nests outside of ->d_lock, + * so we might need to drop and regain the latter. We use rcu_read_lock() + * to keep the RCU read-side critical area contiguous, so dentry and + * inode won't get freed under us, but dentry state might've changed + * while its ->d_lock had not been held - it might end up getting + * killed, becoming busy, negative, etc. + * + * If dentry is busy (or busy dying, or already dead), unlock dentry + * and return false. Otherwise, return true and have that dentry's + * inode (if any) locked in addition to dentry itself. + */ +static bool lock_for_kill(struct dentry *dentry) +{ + struct inode *inode = dentry->d_inode; + + if (unlikely(dentry->d_lockref.count)) { + spin_unlock(&dentry->d_lock); + return false; + } + + if (!inode || likely(spin_trylock(&inode->i_lock))) + return true; + + rcu_read_lock(); + do { + spin_unlock(&dentry->d_lock); + spin_lock(&inode->i_lock); + spin_lock(&dentry->d_lock); + if (likely(inode == dentry->d_inode)) + break; + spin_unlock(&inode->i_lock); + inode = dentry->d_inode; + } while (inode); + rcu_read_unlock(); + if (likely(!dentry->d_lockref.count)) + return true; + if (inode) + spin_unlock(&inode->i_lock); + spin_unlock(&dentry->d_lock); + return false; +} + +static struct dentry *dentry_kill(struct dentry *dentry) { struct dentry *parent = NULL; bool can_free = true; + if (unlikely(!lock_for_kill(dentry))) + return NULL; + /* * The dentry is now unrecoverably dead to the world. */ @@ -742,54 +791,6 @@ static struct dentry *__dentry_kill(struct dentry *dentry) return parent; } -/* - * Lock a dentry for feeding it to __dentry_kill(). - * Called under rcu_read_lock() and dentry->d_lock; the former - * guarantees that nothing we access will be freed under us. - * Note that dentry is *not* protected from concurrent dentry_kill(), - * d_delete(), etc. - * - * Return false if dentry is busy. Otherwise, return true and have - * that dentry's inode locked. - */ - -static bool lock_for_kill(struct dentry *dentry) -{ - struct inode *inode = dentry->d_inode; - - if (unlikely(dentry->d_lockref.count)) - return false; - - if (!inode || likely(spin_trylock(&inode->i_lock))) - return true; - - rcu_read_lock(); - do { - spin_unlock(&dentry->d_lock); - spin_lock(&inode->i_lock); - spin_lock(&dentry->d_lock); - if (likely(inode == dentry->d_inode)) - break; - spin_unlock(&inode->i_lock); - inode = dentry->d_inode; - } while (inode); - rcu_read_unlock(); - if (likely(!dentry->d_lockref.count)) - return true; - if (inode) - spin_unlock(&inode->i_lock); - return false; -} - -static struct dentry *dentry_kill(struct dentry *dentry) -{ - if (unlikely(!lock_for_kill(dentry))) { - spin_unlock(&dentry->d_lock); - return NULL; - } - return __dentry_kill(dentry); -} - /* * Decide if dentry is worth retaining. Usually this is called with dentry * locked; if not locked, we are more limited and might not be able to tell -- 2.47.3