summaryrefslogtreecommitdiff
path: root/fs/crypto
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2023-04-06 11:12:45 -0700
committerEric Biggers <ebiggers@google.com>2023-04-06 11:16:39 -0700
commit83e57e47906ce0e99bd61c70fae514e69960d274 (patch)
tree3b242cfea96fa9f37838c357109d9884ad0b65ec /fs/crypto
parent41b2ad80fdcaafd42fce173cb95847d0cd8614c2 (diff)
fscrypt: optimize fscrypt_initialize()
fscrypt_initialize() is a "one-time init" function that is called whenever the key is set up for any inode on any filesystem. Make it implement "one-time init" more efficiently by not taking a global mutex in the "already initialized case" and doing fewer pointer dereferences. Link: https://lore.kernel.org/r/20230406181245.36091-1-ebiggers@kernel.org Signed-off-by: Eric Biggers <ebiggers@google.com>
Diffstat (limited to 'fs/crypto')
-rw-r--r--fs/crypto/crypto.c19
-rw-r--r--fs/crypto/fscrypt_private.h2
-rw-r--r--fs/crypto/keysetup.c2
3 files changed, 14 insertions, 9 deletions
diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index bf642479269a..6a837e4b80dc 100644
--- a/fs/crypto/crypto.c
+++ b/fs/crypto/crypto.c
@@ -308,19 +308,24 @@ EXPORT_SYMBOL(fscrypt_decrypt_block_inplace);
/**
* fscrypt_initialize() - allocate major buffers for fs encryption.
- * @cop_flags: fscrypt operations flags
+ * @sb: the filesystem superblock
*
* We only call this when we start accessing encrypted files, since it
* results in memory getting allocated that wouldn't otherwise be used.
*
* Return: 0 on success; -errno on failure
*/
-int fscrypt_initialize(unsigned int cop_flags)
+int fscrypt_initialize(struct super_block *sb)
{
int err = 0;
+ mempool_t *pool;
+
+ /* pairs with smp_store_release() below */
+ if (likely(smp_load_acquire(&fscrypt_bounce_page_pool)))
+ return 0;
/* No need to allocate a bounce page pool if this FS won't use it. */
- if (cop_flags & FS_CFLG_OWN_PAGES)
+ if (sb->s_cop->flags & FS_CFLG_OWN_PAGES)
return 0;
mutex_lock(&fscrypt_init_mutex);
@@ -328,11 +333,11 @@ int fscrypt_initialize(unsigned int cop_flags)
goto out_unlock;
err = -ENOMEM;
- fscrypt_bounce_page_pool =
- mempool_create_page_pool(num_prealloc_crypto_pages, 0);
- if (!fscrypt_bounce_page_pool)
+ pool = mempool_create_page_pool(num_prealloc_crypto_pages, 0);
+ if (!pool)
goto out_unlock;
-
+ /* pairs with smp_load_acquire() above */
+ smp_store_release(&fscrypt_bounce_page_pool, pool);
err = 0;
out_unlock:
mutex_unlock(&fscrypt_init_mutex);
diff --git a/fs/crypto/fscrypt_private.h b/fs/crypto/fscrypt_private.h
index 05310aa741fd..7ab5a7b7eef8 100644
--- a/fs/crypto/fscrypt_private.h
+++ b/fs/crypto/fscrypt_private.h
@@ -264,7 +264,7 @@ typedef enum {
/* crypto.c */
extern struct kmem_cache *fscrypt_info_cachep;
-int fscrypt_initialize(unsigned int cop_flags);
+int fscrypt_initialize(struct super_block *sb);
int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw,
u64 lblk_num, struct page *src_page,
struct page *dest_page, unsigned int len,
diff --git a/fs/crypto/keysetup.c b/fs/crypto/keysetup.c
index 84cdae306328..361f41ef46c7 100644
--- a/fs/crypto/keysetup.c
+++ b/fs/crypto/keysetup.c
@@ -560,7 +560,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
struct fscrypt_master_key *mk = NULL;
int res;
- res = fscrypt_initialize(inode->i_sb->s_cop->flags);
+ res = fscrypt_initialize(inode->i_sb);
if (res)
return res;