diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2026-04-11 03:56:42 -0400 |
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2026-06-05 00:34:55 -0400 |
| commit | b4143e0e71cd660d05de8d2861e980e7c840eb39 (patch) | |
| tree | 4b3269bea49b2c4d43b4ba4ca427eb83ec111944 | |
| parent | 0954b4b558f7f582615b071b686f42a5a3ce2e53 (diff) | |
| download | linux-b4143e0e71cd660d05de8d2861e980e7c840eb39.tar.gz linux-b4143e0e71cd660d05de8d2861e980e7c840eb39.zip | |
Shift rcu_read_{,un}lock() inside fast_dput()
Shrink rcu_read_lock() scopes surrounding fast_dput() calls.
Both callers are immediately preceded and followed by
rcu_read_lock()/rcu_read_unlock() resp. Shrink that down
into fast_dput() itself; in case when fast_dput() ends up
grabbing ->d_lock, we can pull rcu_read_unlock() up to
right after spin_lock().
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | fs/dcache.c | 30 |
1 files changed, 14 insertions, 16 deletions
diff --git a/fs/dcache.c b/fs/dcache.c index 9851d387349d..ae9b7151e6a4 100644 --- a/fs/dcache.c +++ b/fs/dcache.c @@ -885,17 +885,17 @@ EXPORT_SYMBOL(d_mark_dontcache); * If unsuccessful, we return false, having already taken the dentry lock. * In that case refcount is guaranteed to be zero and we have already * decided that it's not worth keeping around. - * - * The caller needs to hold the RCU read lock, so that the dentry is - * guaranteed to stay around even if the refcount goes down to zero! */ static inline bool fast_dput(struct dentry *dentry) { int ret; /* - * try to decrement the lockref optimistically. + * Try to decrement the lockref optimistically. + * RCU read lock held so that dentry is guaranteed to stay around + * even if the refcount goes down to zero. */ + rcu_read_lock(); ret = lockref_put_return(&dentry->d_lockref); /* @@ -905,6 +905,7 @@ static inline bool fast_dput(struct dentry *dentry) */ if (unlikely(ret < 0)) { spin_lock(&dentry->d_lock); + rcu_read_unlock(); if (WARN_ON_ONCE(dentry->d_lockref.count <= 0)) { spin_unlock(&dentry->d_lock); return true; @@ -916,8 +917,10 @@ static inline bool fast_dput(struct dentry *dentry) /* * If we weren't the last ref, we're done. */ - if (ret) + if (ret) { + rcu_read_unlock(); return true; + } /* * Can we decide that decrement of refcount is all we needed without @@ -925,8 +928,10 @@ static inline bool fast_dput(struct dentry *dentry) * dentry looks like it ought to be retained and there's nothing else * to do. */ - if (retain_dentry(dentry, false)) + if (retain_dentry(dentry, false)) { + rcu_read_unlock(); return true; + } /* * Either not worth retaining or we can't tell without the lock. @@ -934,6 +939,7 @@ static inline bool fast_dput(struct dentry *dentry) * but we'll need to re-check the situation after getting the lock. */ spin_lock(&dentry->d_lock); + rcu_read_unlock(); /* * Did somebody else grab a reference to it in the meantime, and @@ -991,12 +997,8 @@ void dput(struct dentry *dentry) if (!dentry) return; might_sleep(); - rcu_read_lock(); - if (likely(fast_dput(dentry))) { - rcu_read_unlock(); + if (likely(fast_dput(dentry))) return; - } - rcu_read_unlock(); finish_dput(dentry); } EXPORT_SYMBOL(dput); @@ -1044,12 +1046,8 @@ EXPORT_SYMBOL(__move_to_shrink_list); void dput_to_list(struct dentry *dentry, struct list_head *list) { - rcu_read_lock(); - if (likely(fast_dput(dentry))) { - rcu_read_unlock(); + if (likely(fast_dput(dentry))) return; - } - rcu_read_unlock(); __move_to_shrink_list(dentry, list); spin_unlock(&dentry->d_lock); } |
