1 ext4 crypto: allocate bounce pages using GFP_NOWAIT
3 Previously we allocated bounce pages using a combination of
4 alloc_page() and mempool_alloc() with the __GFP_WAIT bit set.
5 Instead, use mempool_alloc() with GFP_NOWAIT. The mempool_alloc()
6 function will try using alloc_pages() initially, and then only use the
7 mempool reserve of pages if alloc_pages() is unable to fulfill the
10 This minimizes the the impact on the mm layer when we need to do a
11 large amount of writeback of encrypted files, as Jaeguk Kim had
12 reported that under a heavy fio workload on a system with restricted
13 amounts memory (which unfortunately, includes many mobile handsets),
14 he had observed the the OOM killer getting triggered several times.
17 If the mempool_alloc() function fails, we will retry the page
18 writeback at a later time; the function of the mempool is to ensure
19 that we can writeback at least 32 pages at a time, so we can more
20 efficiently dispatch I/O under high memory pressure situations. In
21 the future we should make this be a tunable so we can determine the
22 best tradeoff between permanently sequestering memory and the ability
23 to quickly launder pages so we can free up memory quickly when
26 Signed-off-by: Theodore Ts'o <tytso@mit.edu>
28 fs/ext4/crypto.c | 27 ++++++---------------------
29 fs/ext4/ext4_crypto.h | 3 +--
30 2 files changed, 7 insertions(+), 23 deletions(-)
32 diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
33 index efcb7c0..f5c82e8 100644
34 --- a/fs/ext4/crypto.c
35 +++ b/fs/ext4/crypto.c
36 @@ -71,12 +71,8 @@ void ext4_release_crypto_ctx(struct ext4_crypto_ctx *ctx)
40 - if (ctx->flags & EXT4_WRITE_PATH_FL && ctx->w.bounce_page) {
41 - if (ctx->flags & EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL)
42 - __free_page(ctx->w.bounce_page);
44 - mempool_free(ctx->w.bounce_page, ext4_bounce_page_pool);
46 + if (ctx->flags & EXT4_WRITE_PATH_FL && ctx->w.bounce_page)
47 + mempool_free(ctx->w.bounce_page, ext4_bounce_page_pool);
48 ctx->w.bounce_page = NULL;
49 ctx->w.control_page = NULL;
50 if (ctx->flags & EXT4_CTX_REQUIRES_FREE_ENCRYPT_FL) {
51 @@ -317,22 +313,11 @@ static int ext4_page_crypto(struct ext4_crypto_ctx *ctx,
53 static struct page *alloc_bounce_page(struct ext4_crypto_ctx *ctx)
55 - struct page *ciphertext_page = alloc_page(GFP_NOFS);
57 - if (!ciphertext_page) {
58 - /* This is a potential bottleneck, but at least we'll have
59 - * forward progress. */
60 - ciphertext_page = mempool_alloc(ext4_bounce_page_pool,
62 - if (ciphertext_page == NULL)
63 - return ERR_PTR(-ENOMEM);
64 - ctx->flags &= ~EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL;
66 - ctx->flags |= EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL;
68 + ctx->w.bounce_page = mempool_alloc(ext4_bounce_page_pool, GFP_NOWAIT);
69 + if (ctx->w.bounce_page == NULL)
70 + return ERR_PTR(-ENOMEM);
71 ctx->flags |= EXT4_WRITE_PATH_FL;
72 - ctx->w.bounce_page = ciphertext_page;
73 - return ciphertext_page;
74 + return ctx->w.bounce_page;
78 diff --git a/fs/ext4/ext4_crypto.h b/fs/ext4/ext4_crypto.h
79 index 34e0d24..ac7d4e8 100644
80 --- a/fs/ext4/ext4_crypto.h
81 +++ b/fs/ext4/ext4_crypto.h
82 @@ -83,8 +83,7 @@ struct ext4_crypt_info {
85 #define EXT4_CTX_REQUIRES_FREE_ENCRYPT_FL 0x00000001
86 -#define EXT4_BOUNCE_PAGE_REQUIRES_FREE_ENCRYPT_FL 0x00000002
87 -#define EXT4_WRITE_PATH_FL 0x00000004
88 +#define EXT4_WRITE_PATH_FL 0x00000002
90 struct ext4_crypto_ctx {