fs: dcache reduce d_parent locking
Use RCU to simplify locking in dget_parent. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
This commit is contained in:
parent
dc0474be3e
commit
a734eb458a
21
fs/dcache.c
21
fs/dcache.c
@ -446,24 +446,27 @@ struct dentry *dget_parent(struct dentry *dentry)
|
|||||||
struct dentry *ret;
|
struct dentry *ret;
|
||||||
|
|
||||||
repeat:
|
repeat:
|
||||||
spin_lock(&dentry->d_lock);
|
/*
|
||||||
|
* Don't need rcu_dereference because we re-check it was correct under
|
||||||
|
* the lock.
|
||||||
|
*/
|
||||||
|
rcu_read_lock();
|
||||||
ret = dentry->d_parent;
|
ret = dentry->d_parent;
|
||||||
if (!ret)
|
if (!ret) {
|
||||||
goto out;
|
rcu_read_unlock();
|
||||||
if (dentry == ret) {
|
|
||||||
ret->d_count++;
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
if (!spin_trylock(&ret->d_lock)) {
|
spin_lock(&ret->d_lock);
|
||||||
spin_unlock(&dentry->d_lock);
|
if (unlikely(ret != dentry->d_parent)) {
|
||||||
cpu_relax();
|
spin_unlock(&ret->d_lock);
|
||||||
|
rcu_read_unlock();
|
||||||
goto repeat;
|
goto repeat;
|
||||||
}
|
}
|
||||||
|
rcu_read_unlock();
|
||||||
BUG_ON(!ret->d_count);
|
BUG_ON(!ret->d_count);
|
||||||
ret->d_count++;
|
ret->d_count++;
|
||||||
spin_unlock(&ret->d_lock);
|
spin_unlock(&ret->d_lock);
|
||||||
out:
|
out:
|
||||||
spin_unlock(&dentry->d_lock);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dget_parent);
|
EXPORT_SYMBOL(dget_parent);
|
||||||
|
Loading…
Reference in New Issue
Block a user