This patch attempts to enable RCU-walk for fscrypt. It looks harmless at glance and could have better performance than do ref-walk only.
Signed-off-by: Gao Xiang <gaoxian...@huawei.com> --- change log v2: - READ_ONCE(dir->d_parent) -> READ_ONCE(dentry->d_parent) fs/crypto/crypto.c | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c index b38c574..9bd21c0 100644 --- a/fs/crypto/crypto.c +++ b/fs/crypto/crypto.c @@ -319,20 +319,24 @@ static int fscrypt_d_revalidate(struct dentry *dentry, unsigned int flags) { struct dentry *dir; int dir_has_key, cached_with_key; - - if (flags & LOOKUP_RCU) - return -ECHILD; - - dir = dget_parent(dentry); - if (!IS_ENCRYPTED(d_inode(dir))) { - dput(dir); + struct inode *dir_inode; + + rcu_read_lock(); +repeat: + dir = READ_ONCE(dentry->d_parent); + dir_inode = d_inode_rcu(dir); + if (!IS_ENCRYPTED(dir_inode)) { + rcu_read_unlock(); return 0; } + dir_has_key = (dir_inode->i_crypt_info != NULL); + if (unlikely(READ_ONCE(dir->d_lockref.count) < 0 || + READ_ONCE(dentry->d_parent) != dir)) + goto repeat; + rcu_read_unlock(); cached_with_key = READ_ONCE(dentry->d_flags) & DCACHE_ENCRYPTED_WITH_KEY; - dir_has_key = (d_inode(dir)->i_crypt_info != NULL); - dput(dir); /* * If the dentry was cached without the key, and it is a -- 1.9.1