mirror of
https://github.com/torvalds/linux.git
synced 2026-07-30 11:11:26 +02:00
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>
This commit is contained in:
parent
0954b4b558
commit
b4143e0e71
30
fs/dcache.c
30
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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user