Skip to content

Commit e86e663

Browse files
committed
fscrypt: Drop d_revalidate for valid dentries during lookup
Unencrypted and encrypted-dentries where the key is available don't need to be revalidated by fscrypt, since they don't go stale from under VFS and the key cannot be removed for the encrypted case without evicting the dentry. Disable their d_revalidate hook on the first lookup, to avoid repeated revalidation later. This is done in preparation to always configuring d_op through sb->s_d_op. The only part detail is that, since the filesystem might have other features that require revalidation, we only apply this optimization if the d_revalidate handler is fscrypt_d_revalidate itself. Finally, we need to clean the dentry->flags even for unencrypted dentries, so the ->d_lock might be acquired even for them. In order to avoid doing it for filesystems that don't care about fscrypt at all, we peek ->d_flags without the lock at first, and only acquire it if we actually need to write the flag. Reviewed-by: Eric Biggers <ebiggers@google.com> Link: https://lore.kernel.org/r/20240221171412.10710-4-krisman@suse.de Signed-off-by: Gabriel Krisman Bertazi <krisman@suse.de>
1 parent 8b6bb99 commit e86e663

File tree

1 file changed

+22
-0
lines changed

1 file changed

+22
-0
lines changed

include/linux/fscrypt.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,10 +264,29 @@ static inline bool fscrypt_is_nokey_name(const struct dentry *dentry)
264264
static inline void fscrypt_prepare_dentry(struct dentry *dentry,
265265
bool is_nokey_name)
266266
{
267+
/*
268+
* This code tries to only take ->d_lock when necessary to write
269+
* to ->d_flags. We shouldn't be peeking on d_flags for
270+
* DCACHE_OP_REVALIDATE unlocked, but in the unlikely case
271+
* there is a race, the worst it can happen is that we fail to
272+
* unset DCACHE_OP_REVALIDATE and pay the cost of an extra
273+
* d_revalidate.
274+
*/
267275
if (is_nokey_name) {
268276
spin_lock(&dentry->d_lock);
269277
dentry->d_flags |= DCACHE_NOKEY_NAME;
270278
spin_unlock(&dentry->d_lock);
279+
} else if (dentry->d_flags & DCACHE_OP_REVALIDATE &&
280+
dentry->d_op->d_revalidate == fscrypt_d_revalidate) {
281+
/*
282+
* Unencrypted dentries and encrypted dentries where the
283+
* key is available are always valid from fscrypt
284+
* perspective. Avoid the cost of calling
285+
* fscrypt_d_revalidate unnecessarily.
286+
*/
287+
spin_lock(&dentry->d_lock);
288+
dentry->d_flags &= ~DCACHE_OP_REVALIDATE;
289+
spin_unlock(&dentry->d_lock);
271290
}
272291
}
273292

@@ -997,6 +1016,9 @@ static inline int fscrypt_prepare_lookup(struct inode *dir,
9971016
fname->usr_fname = &dentry->d_name;
9981017
fname->disk_name.name = (unsigned char *)dentry->d_name.name;
9991018
fname->disk_name.len = dentry->d_name.len;
1019+
1020+
fscrypt_prepare_dentry(dentry, false);
1021+
10001022
return 0;
10011023
}
10021024

0 commit comments

Comments
 (0)