Message ID | 20190926104844.4f0c6efa1366b8f5741eaba9@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | z3fold: claim page in the beginning of free | expand |
On Thu, 26 Sep 2019 10:48:44 +0200 Vitaly Wool <vitalywool@gmail.com> wrote: > There's a really hard to reproduce race in z3fold between > z3fold_free() and z3fold_reclaim_page(). z3fold_reclaim_page() > can claim the page after z3fold_free() has checked if the page > was claimed and z3fold_free() will then schedule this page for > compaction which may in turn lead to random page faults (since > that page would have been reclaimed by then). Fix that by > claiming page in the beginning of z3fold_free(). > I take it from the email headers that a Cc: <stable@vger.kernel.org> was intended?
Den fre 27 sep. 2019 00:48Andrew Morton <akpm@linux-foundation.org> skrev: > On Thu, 26 Sep 2019 10:48:44 +0200 Vitaly Wool <vitalywool@gmail.com> > wrote: > > > There's a really hard to reproduce race in z3fold between > > z3fold_free() and z3fold_reclaim_page(). z3fold_reclaim_page() > > can claim the page after z3fold_free() has checked if the page > > was claimed and z3fold_free() will then schedule this page for > > compaction which may in turn lead to random page faults (since > > that page would have been reclaimed by then). Fix that by > > claiming page in the beginning of z3fold_free(). > > > > I take it from the email headers that a > > Cc: <stable@vger.kernel.org> > > was intended? > Oh yes, thanks! ~Vitaly >
diff --git a/mm/z3fold.c b/mm/z3fold.c index 05bdf90646e7..01b87c78b984 100644 --- a/mm/z3fold.c +++ b/mm/z3fold.c @@ -998,9 +998,11 @@ static void z3fold_free(struct z3fold_pool *pool, unsigned long handle) struct z3fold_header *zhdr; struct page *page; enum buddy bud; + bool page_claimed; zhdr = handle_to_z3fold_header(handle); page = virt_to_page(zhdr); + page_claimed = test_and_set_bit(PAGE_CLAIMED, &page->private); if (test_bit(PAGE_HEADLESS, &page->private)) { /* if a headless page is under reclaim, just leave. @@ -1008,7 +1010,7 @@ static void z3fold_free(struct z3fold_pool *pool, unsigned long handle) * has not been set before, we release this page * immediately so we don't care about its value any more. */ - if (!test_and_set_bit(PAGE_CLAIMED, &page->private)) { + if (!page_claimed) { spin_lock(&pool->lock); list_del(&page->lru); spin_unlock(&pool->lock); @@ -1044,7 +1046,7 @@ static void z3fold_free(struct z3fold_pool *pool, unsigned long handle) atomic64_dec(&pool->pages_nr); return; } - if (test_bit(PAGE_CLAIMED, &page->private)) { + if (page_claimed) { z3fold_page_unlock(zhdr); return; }
There's a really hard to reproduce race in z3fold between z3fold_free() and z3fold_reclaim_page(). z3fold_reclaim_page() can claim the page after z3fold_free() has checked if the page was claimed and z3fold_free() will then schedule this page for compaction which may in turn lead to random page faults (since that page would have been reclaimed by then). Fix that by claiming page in the beginning of z3fold_free(). Reported-by: Markus Linnala <markus.linnala@gmail.com> Signed-off-by: Vitaly Wool <vitalywool@gmail.com> --- mm/z3fold.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)