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>
This commit is contained in:
Eric Biggers 2023-04-06 11:12:45 -07:00
parent 41b2ad80fd
commit 83e57e4790
3 changed files with 14 additions and 9 deletions

View File

@ -308,19 +308,24 @@ EXPORT_SYMBOL(fscrypt_decrypt_block_inplace);
/** /**
* fscrypt_initialize() - allocate major buffers for fs encryption. * 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 * We only call this when we start accessing encrypted files, since it
* results in memory getting allocated that wouldn't otherwise be used. * results in memory getting allocated that wouldn't otherwise be used.
* *
* Return: 0 on success; -errno on failure * Return: 0 on success; -errno on failure
*/ */
int fscrypt_initialize(unsigned int cop_flags) int fscrypt_initialize(struct super_block *sb)
{ {
int err = 0; 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. */ /* 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; return 0;
mutex_lock(&fscrypt_init_mutex); mutex_lock(&fscrypt_init_mutex);
@ -328,11 +333,11 @@ int fscrypt_initialize(unsigned int cop_flags)
goto out_unlock; goto out_unlock;
err = -ENOMEM; err = -ENOMEM;
fscrypt_bounce_page_pool = pool = mempool_create_page_pool(num_prealloc_crypto_pages, 0);
mempool_create_page_pool(num_prealloc_crypto_pages, 0); if (!pool)
if (!fscrypt_bounce_page_pool)
goto out_unlock; goto out_unlock;
/* pairs with smp_load_acquire() above */
smp_store_release(&fscrypt_bounce_page_pool, pool);
err = 0; err = 0;
out_unlock: out_unlock:
mutex_unlock(&fscrypt_init_mutex); mutex_unlock(&fscrypt_init_mutex);

View File

@ -264,7 +264,7 @@ typedef enum {
/* crypto.c */ /* crypto.c */
extern struct kmem_cache *fscrypt_info_cachep; 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, int fscrypt_crypt_block(const struct inode *inode, fscrypt_direction_t rw,
u64 lblk_num, struct page *src_page, u64 lblk_num, struct page *src_page,
struct page *dest_page, unsigned int len, struct page *dest_page, unsigned int len,

View File

@ -560,7 +560,7 @@ fscrypt_setup_encryption_info(struct inode *inode,
struct fscrypt_master_key *mk = NULL; struct fscrypt_master_key *mk = NULL;
int res; int res;
res = fscrypt_initialize(inode->i_sb->s_cop->flags); res = fscrypt_initialize(inode->i_sb);
if (res) if (res)
return res; return res;