summaryrefslogtreecommitdiffstats
path: root/fs/crypto/keyinfo.c
diff options
context:
space:
mode:
authorEric Biggers2019-04-10 22:21:15 +0200
committerTheodore Ts'o2019-04-17 18:43:29 +0200
commit2c58d548f5706d085c4b009f6abb945220460632 (patch)
treeb263f432d3ad778b6970ebbb842bd0a577e88cdc /fs/crypto/keyinfo.c
parentvfs: use READ_ONCE() to access ->i_link (diff)
downloadkernel-qcow2-linux-2c58d548f5706d085c4b009f6abb945220460632.tar.gz
kernel-qcow2-linux-2c58d548f5706d085c4b009f6abb945220460632.tar.xz
kernel-qcow2-linux-2c58d548f5706d085c4b009f6abb945220460632.zip
fscrypt: cache decrypted symlink target in ->i_link
Path lookups that traverse encrypted symlink(s) are very slow because each encrypted symlink needs to be decrypted each time it's followed. This also involves dropping out of rcu-walk mode. Make encrypted symlinks faster by caching the decrypted symlink target in ->i_link. The first call to fscrypt_get_symlink() sets it. Then, the existing VFS path lookup code uses the non-NULL ->i_link to take the fast path where ->get_link() isn't called, and lookups in rcu-walk mode remain in rcu-walk mode. Also set ->i_link immediately when a new encrypted symlink is created. To safely free the symlink target after an RCU grace period has elapsed, introduce a new function fscrypt_free_inode(), and make the relevant filesystems call it just before actually freeing the inode. Cc: Al Viro <viro@zeniv.linux.org.uk> Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Diffstat (limited to 'fs/crypto/keyinfo.c')
-rw-r--r--fs/crypto/keyinfo.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/fs/crypto/keyinfo.c b/fs/crypto/keyinfo.c
index bf291c10c682..82989098b2fc 100644
--- a/fs/crypto/keyinfo.c
+++ b/fs/crypto/keyinfo.c
@@ -584,9 +584,30 @@ out:
}
EXPORT_SYMBOL(fscrypt_get_encryption_info);
+/**
+ * fscrypt_put_encryption_info - free most of an inode's fscrypt data
+ *
+ * Free the inode's fscrypt_info. Filesystems must call this when the inode is
+ * being evicted. An RCU grace period need not have elapsed yet.
+ */
void fscrypt_put_encryption_info(struct inode *inode)
{
put_crypt_info(inode->i_crypt_info);
inode->i_crypt_info = NULL;
}
EXPORT_SYMBOL(fscrypt_put_encryption_info);
+
+/**
+ * fscrypt_free_inode - free an inode's fscrypt data requiring RCU delay
+ *
+ * Free the inode's cached decrypted symlink target, if any. Filesystems must
+ * call this after an RCU grace period, just before they free the inode.
+ */
+void fscrypt_free_inode(struct inode *inode)
+{
+ if (IS_ENCRYPTED(inode) && S_ISLNK(inode->i_mode)) {
+ kfree(inode->i_link);
+ inode->i_link = NULL;
+ }
+}
+EXPORT_SYMBOL(fscrypt_free_inode);