ext4 crypto: allocate bounce pages using GFP_NOWAIT
Previously we allocated bounce pages using a combination of alloc_page() and mempool_alloc() with the __GFP_WAIT bit set. Instead, use mempool_alloc() with GFP_NOWAIT. The mempool_alloc() function will try using alloc_pages() initially, and then only use the mempool reserve of pages if alloc_pages() is unable to fulfill the request. This minimizes the the impact on the mm layer when we need to do a large amount of writeback of encrypted files, as Jaeguk Kim had reported that under a heavy fio workload on a system with restricted amounts memory (which unfortunately, includes many mobile handsets), he had observed the the OOM killer getting triggered several times. Using GFP_NOWAIT If the mempool_alloc() function fails, we will retry the page writeback at a later time; the function of the mempool is to ensure that we can writeback at least 32 pages at a time, so we can more efficiently dispatch I/O under high memory pressure situations. In the future we should make this be a tunable so we can determine the best tradeoff between permanently sequestering memory and the ability to quickly launder pages so we can free up memory quickly when necessary. Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
parent
e298e73bd7
commit
3dbb5eb9a3
|
@ -71,12 +71,8 @@ void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx)
|
|||
{
|
||||
unsigned long flags;
|
||||
|
||||
if (ctx->flags & EXT4_WRITE_PATH_FL && ctx->w.bounce_page) {
|
||||
if (ctx->flags & EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL)
|
||||
__free_page(ctx->w.bounce_page);
|
||||
else
|
||||
mempool_free(ctx->w.bounce_page, ext4_bounce_page_pool);
|
||||
}
|
||||
if (ctx->flags & EXT4_WRITE_PATH_FL && ctx->w.bounce_page)
|
||||
mempool_free(ctx->w.bounce_page, ext4_bounce_page_pool);
|
||||
ctx->w.bounce_page = NULL;
|
||||
ctx->w.control_page = NULL;
|
||||
if (ctx->flags & EXT4_CTX_REQUIRES_FREE_ENCRYPT_FL) {
|
||||
|
@ -317,22 +313,11 @@ static int ext4_page_crypto(struct ext4_crypto_ctx *ctx,
|
|||
|
||||
static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx)
|
||||
{
|
||||
struct page *ciphertext_page = alloc_page(GFP_NOFS);
|
||||
|
||||
if (!ciphertext_page) {
|
||||
/* This is a potential bottleneck, but at least we'll have
|
||||
* forward progress. */
|
||||
ciphertext_page = mempool_alloc(ext4_bounce_page_pool,
|
||||
GFP_NOFS);
|
||||
if (ciphertext_page == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
ctx->flags &= ~EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL;
|
||||
} else {
|
||||
ctx->flags |= EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL;
|
||||
}
|
||||
ctx->w.bounce_page = mempool_alloc(ext4_bounce_page_pool, GFP_NOWAIT);
|
||||
if (ctx->w.bounce_page == NULL)
|
||||
return ERR_PTR(-ENOMEM);
|
||||
ctx->flags |= EXT4_WRITE_PATH_FL;
|
||||
ctx->w.bounce_page = ciphertext_page;
|
||||
return ciphertext_page;
|
||||
return ctx->w.bounce_page;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -83,8 +83,7 @@ struct ext4_crypt_info {
|
|||
};
|
||||
|
||||
#define EXT4_CTX_REQUIRES_FREE_ENCRYPT_FL 0x00000001
|
||||
#define EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL 0x00000002
|
||||
#define EXT4_WRITE_PATH_FL 0x00000004
|
||||
#define EXT4_WRITE_PATH_FL 0x00000002
|
||||
|
||||
struct ext4_crypto_ctx {
|
||||
union {
|
||||
|
|
Loading…
Reference in a new issue