diff options
author | Vitaly Wool <vitalywool@gmail.com> | 2019-09-23 15:36:51 -0700 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-10-05 13:14:10 +0200 |
commit | 5377b8767d64a2a8728702ed7b1ca8d7b1783f01 (patch) | |
tree | dc220e4b484d86266af456b7ea9858353cdebe80 | |
parent | ed99d2d1af39aa2e1539d3f778d92fd3177b2fe2 (diff) | |
download | linux-stable-5377b8767d64a2a8728702ed7b1ca8d7b1783f01.tar.gz linux-stable-5377b8767d64a2a8728702ed7b1ca8d7b1783f01.tar.bz2 linux-stable-5377b8767d64a2a8728702ed7b1ca8d7b1783f01.zip |
z3fold: fix memory leak in kmem cache
commit 63398413c00c7836ea87a1fa205c91d2199b25cf upstream.
Currently there is a leak in init_z3fold_page() -- it allocates handles
from kmem cache even for headless pages, but then they are never used and
never freed, so eventually kmem cache may get exhausted. This patch
provides a fix for that.
Link: http://lkml.kernel.org/r/20190917185352.44cf285d3ebd9e64548de5de@gmail.com
Signed-off-by: Vitaly Wool <vitalywool@gmail.com>
Reported-by: Markus Linnala <markus.linnala@gmail.com>
Tested-by: Markus Linnala <markus.linnala@gmail.com>
Cc: Dan Streetman <ddstreet@ieee.org>
Cc: Henry Burns <henrywolfeburns@gmail.com>
Cc: Shakeel Butt <shakeelb@google.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | mm/z3fold.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/mm/z3fold.c b/mm/z3fold.c index ddaa4f9848f8..8f87c05a27e1 100644 --- a/mm/z3fold.c +++ b/mm/z3fold.c @@ -297,14 +297,11 @@ static void z3fold_unregister_migration(struct z3fold_pool *pool) } /* Initializes the z3fold header of a newly allocated z3fold page */ -static struct z3fold_header *init_z3fold_page(struct page *page, +static struct z3fold_header *init_z3fold_page(struct page *page, bool headless, struct z3fold_pool *pool, gfp_t gfp) { struct z3fold_header *zhdr = page_address(page); - struct z3fold_buddy_slots *slots = alloc_slots(pool, gfp); - - if (!slots) - return NULL; + struct z3fold_buddy_slots *slots; INIT_LIST_HEAD(&page->lru); clear_bit(PAGE_HEADLESS, &page->private); @@ -312,6 +309,12 @@ static struct z3fold_header *init_z3fold_page(struct page *page, clear_bit(NEEDS_COMPACTING, &page->private); clear_bit(PAGE_STALE, &page->private); clear_bit(PAGE_CLAIMED, &page->private); + if (headless) + return zhdr; + + slots = alloc_slots(pool, gfp); + if (!slots) + return NULL; spin_lock_init(&zhdr->page_lock); kref_init(&zhdr->refcount); @@ -932,7 +935,7 @@ retry: if (!page) return -ENOMEM; - zhdr = init_z3fold_page(page, pool, gfp); + zhdr = init_z3fold_page(page, bud == HEADLESS, pool, gfp); if (!zhdr) { __free_page(page); return -ENOMEM; |