f2fs crypto: split f2fs_crypto_init/exit with two parts

This patch splits f2fs_crypto_init/exit with two parts: base initialization and
memory allocation.

Firstly, f2fs module declares the base encryption memory pointers.
Then, allocating internal memories is done at the first encrypted inode access.

Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
This commit is contained in:
Jaegeuk Kim 2015-05-15 15:37:24 -07:00
parent b9da898b05
commit cfc4d971df
4 changed files with 66 additions and 48 deletions

View file

@ -63,7 +63,7 @@ static mempool_t *f2fs_bounce_page_pool;
static LIST_HEAD(f2fs_free_crypto_ctxs); static LIST_HEAD(f2fs_free_crypto_ctxs);
static DEFINE_SPINLOCK(f2fs_crypto_ctx_lock); static DEFINE_SPINLOCK(f2fs_crypto_ctx_lock);
struct workqueue_struct *f2fs_read_workqueue; static struct workqueue_struct *f2fs_read_workqueue;
static DEFINE_MUTEX(crypto_init); static DEFINE_MUTEX(crypto_init);
static struct kmem_cache *f2fs_crypto_ctx_cachep; static struct kmem_cache *f2fs_crypto_ctx_cachep;
@ -225,10 +225,7 @@ void f2fs_end_io_crypto_work(struct f2fs_crypto_ctx *ctx, struct bio *bio)
queue_work(f2fs_read_workqueue, &ctx->r.work); queue_work(f2fs_read_workqueue, &ctx->r.work);
} }
/** static void f2fs_crypto_destroy(void)
* f2fs_exit_crypto() - Shutdown the f2fs encryption system
*/
void f2fs_exit_crypto(void)
{ {
struct f2fs_crypto_ctx *pos, *n; struct f2fs_crypto_ctx *pos, *n;
@ -241,70 +238,87 @@ void f2fs_exit_crypto(void)
if (f2fs_bounce_page_pool) if (f2fs_bounce_page_pool)
mempool_destroy(f2fs_bounce_page_pool); mempool_destroy(f2fs_bounce_page_pool);
f2fs_bounce_page_pool = NULL; f2fs_bounce_page_pool = NULL;
if (f2fs_read_workqueue)
destroy_workqueue(f2fs_read_workqueue);
f2fs_read_workqueue = NULL;
if (f2fs_crypto_ctx_cachep)
kmem_cache_destroy(f2fs_crypto_ctx_cachep);
f2fs_crypto_ctx_cachep = NULL;
if (f2fs_crypt_info_cachep)
kmem_cache_destroy(f2fs_crypt_info_cachep);
f2fs_crypt_info_cachep = NULL;
} }
/** /**
* f2fs_init_crypto() - Set up for f2fs encryption. * f2fs_crypto_initialize() - Set up for f2fs encryption.
* *
* 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: Zero on success, non-zero otherwise. * Return: Zero on success, non-zero otherwise.
*/ */
int f2fs_init_crypto(void) int f2fs_crypto_initialize(void)
{ {
int i, res = -ENOMEM; int i, res = -ENOMEM;
if (f2fs_bounce_page_pool)
return 0;
mutex_lock(&crypto_init); mutex_lock(&crypto_init);
if (f2fs_read_workqueue) if (f2fs_bounce_page_pool)
goto already_initialized; goto already_initialized;
for (i = 0; i < num_prealloc_crypto_ctxs; i++) {
struct f2fs_crypto_ctx *ctx;
ctx = kmem_cache_zalloc(f2fs_crypto_ctx_cachep, GFP_KERNEL);
if (!ctx)
goto fail;
list_add(&ctx->free_list, &f2fs_free_crypto_ctxs);
}
/* must be allocated at the last step to avoid race condition above */
f2fs_bounce_page_pool =
mempool_create_page_pool(num_prealloc_crypto_pages, 0);
if (!f2fs_bounce_page_pool)
goto fail;
already_initialized:
mutex_unlock(&crypto_init);
return 0;
fail:
f2fs_crypto_destroy();
mutex_unlock(&crypto_init);
return res;
}
/**
* f2fs_exit_crypto() - Shutdown the f2fs encryption system
*/
void f2fs_exit_crypto(void)
{
f2fs_crypto_destroy();
if (f2fs_read_workqueue)
destroy_workqueue(f2fs_read_workqueue);
if (f2fs_crypto_ctx_cachep)
kmem_cache_destroy(f2fs_crypto_ctx_cachep);
if (f2fs_crypt_info_cachep)
kmem_cache_destroy(f2fs_crypt_info_cachep);
}
int __init f2fs_init_crypto(void)
{
int res = -ENOMEM;
f2fs_read_workqueue = alloc_workqueue("f2fs_crypto", WQ_HIGHPRI, 0); f2fs_read_workqueue = alloc_workqueue("f2fs_crypto", WQ_HIGHPRI, 0);
if (!f2fs_read_workqueue) if (!f2fs_read_workqueue)
goto fail; goto fail;
f2fs_crypto_ctx_cachep = KMEM_CACHE(f2fs_crypto_ctx, f2fs_crypto_ctx_cachep = KMEM_CACHE(f2fs_crypto_ctx,
SLAB_RECLAIM_ACCOUNT); SLAB_RECLAIM_ACCOUNT);
if (!f2fs_crypto_ctx_cachep) if (!f2fs_crypto_ctx_cachep)
goto fail; goto fail;
f2fs_crypt_info_cachep = KMEM_CACHE(f2fs_crypt_info, f2fs_crypt_info_cachep = KMEM_CACHE(f2fs_crypt_info,
SLAB_RECLAIM_ACCOUNT); SLAB_RECLAIM_ACCOUNT);
if (!f2fs_crypt_info_cachep) if (!f2fs_crypt_info_cachep)
goto fail; goto fail;
for (i = 0; i < num_prealloc_crypto_ctxs; i++) {
struct f2fs_crypto_ctx *ctx;
ctx = kmem_cache_zalloc(f2fs_crypto_ctx_cachep, GFP_KERNEL);
if (!ctx) {
res = -ENOMEM;
goto fail;
}
list_add(&ctx->free_list, &f2fs_free_crypto_ctxs);
}
f2fs_bounce_page_pool =
mempool_create_page_pool(num_prealloc_crypto_pages, 0);
if (!f2fs_bounce_page_pool) {
res = -ENOMEM;
goto fail;
}
already_initialized:
mutex_unlock(&crypto_init);
return 0; return 0;
fail: fail:
f2fs_exit_crypto(); f2fs_exit_crypto();
mutex_unlock(&crypto_init);
return res; return res;
} }

View file

@ -115,11 +115,9 @@ int _f2fs_get_encryption_info(struct inode *inode)
struct user_key_payload *ukp; struct user_key_payload *ukp;
int res; int res;
if (!f2fs_read_workqueue) { res = f2fs_crypto_initialize();
res = f2fs_init_crypto(); if (res)
if (res) return res;
return res;
}
if (fi->i_crypt_info) { if (fi->i_crypt_info) {
if (!fi->i_crypt_info->ci_keyring_key || if (!fi->i_crypt_info->ci_keyring_key ||

View file

@ -2005,7 +2005,6 @@ int f2fs_get_policy(struct inode *, struct f2fs_encryption_policy *);
/* crypt.c */ /* crypt.c */
extern struct kmem_cache *f2fs_crypt_info_cachep; extern struct kmem_cache *f2fs_crypt_info_cachep;
extern struct workqueue_struct *f2fs_read_workqueue;
bool f2fs_valid_contents_enc_mode(uint32_t); bool f2fs_valid_contents_enc_mode(uint32_t);
uint32_t f2fs_validate_encryption_key_size(uint32_t, uint32_t); uint32_t f2fs_validate_encryption_key_size(uint32_t, uint32_t);
struct f2fs_crypto_ctx *f2fs_get_crypto_ctx(struct inode *); struct f2fs_crypto_ctx *f2fs_get_crypto_ctx(struct inode *);
@ -2032,7 +2031,8 @@ int f2fs_fname_usr_to_disk(struct inode *, const struct qstr *,
void f2fs_restore_and_release_control_page(struct page **); void f2fs_restore_and_release_control_page(struct page **);
void f2fs_restore_control_page(struct page *); void f2fs_restore_control_page(struct page *);
int f2fs_init_crypto(void); int __init f2fs_init_crypto(void);
int f2fs_crypto_initialize(void);
void f2fs_exit_crypto(void); void f2fs_exit_crypto(void);
int f2fs_has_encryption_key(struct inode *); int f2fs_has_encryption_key(struct inode *);
@ -2059,7 +2059,7 @@ void f2fs_fname_free_filename(struct f2fs_filename *);
static inline void f2fs_restore_and_release_control_page(struct page **p) { } static inline void f2fs_restore_and_release_control_page(struct page **p) { }
static inline void f2fs_restore_control_page(struct page *p) { } static inline void f2fs_restore_control_page(struct page *p) { }
static inline int f2fs_init_crypto(void) { return 0; } static inline int __init f2fs_init_crypto(void) { return 0; }
static inline void f2fs_exit_crypto(void) { } static inline void f2fs_exit_crypto(void) { }
static inline int f2fs_has_encryption_key(struct inode *i) { return 0; } static inline int f2fs_has_encryption_key(struct inode *i) { return 0; }

View file

@ -1359,13 +1359,18 @@ static int __init init_f2fs_fs(void)
err = -ENOMEM; err = -ENOMEM;
goto free_extent_cache; goto free_extent_cache;
} }
err = register_filesystem(&f2fs_fs_type); err = f2fs_init_crypto();
if (err) if (err)
goto free_kset; goto free_kset;
err = register_filesystem(&f2fs_fs_type);
if (err)
goto free_crypto;
f2fs_create_root_stats(); f2fs_create_root_stats();
f2fs_proc_root = proc_mkdir("fs/f2fs", NULL); f2fs_proc_root = proc_mkdir("fs/f2fs", NULL);
return 0; return 0;
free_crypto:
f2fs_exit_crypto();
free_kset: free_kset:
kset_unregister(f2fs_kset); kset_unregister(f2fs_kset);
free_extent_cache: free_extent_cache:
@ -1387,6 +1392,7 @@ static void __exit exit_f2fs_fs(void)
remove_proc_entry("fs/f2fs", NULL); remove_proc_entry("fs/f2fs", NULL);
f2fs_destroy_root_stats(); f2fs_destroy_root_stats();
unregister_filesystem(&f2fs_fs_type); unregister_filesystem(&f2fs_fs_type);
f2fs_exit_crypto();
destroy_extent_cache(); destroy_extent_cache();
destroy_checkpoint_caches(); destroy_checkpoint_caches();
destroy_segment_manager_caches(); destroy_segment_manager_caches();