diff mbox series

fscrypt: optimize fscrypt_initialize()

Message ID 20230406181245.36091-1-ebiggers@kernel.org (mailing list archive)
State Accepted
Headers show
Series fscrypt: optimize fscrypt_initialize() | expand

Commit Message

Eric Biggers April 6, 2023, 6:12 p.m. UTC
From: Eric Biggers <ebiggers@google.com>

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.

Signed-off-by: Eric Biggers <ebiggers@google.com>
---
 fs/crypto/crypto.c          | 19 ++++++++++++-------
 fs/crypto/fscrypt_private.h |  2 +-
 fs/crypto/keysetup.c        |  2 +-
 3 files changed, 14 insertions(+), 9 deletions(-)


base-commit: 41b2ad80fdcaafd42fce173cb95847d0cd8614c2
diff mbox series

Patch

diff --git a/fs/crypto/crypto.c b/fs/crypto/crypto.c
index bf642479269a5..6a837e4b80dcb 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 05310aa741fd6..7ab5a7b7eef8c 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 84cdae3063280..361f41ef46c78 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;