Commit 35529357 authored by Vitaly Wool's avatar Vitaly Wool Committed by Linus Torvalds

z3fold: fix stale list handling

Fix the situation when clear_bit() is called for page->private before
the page pointer is actually assigned.  While at it, remove work_busy()
check because it is costly and does not give 100% guarantee anyway.
Signed-off-by: default avatarVitaly Wool <vitalywool@gmail.com>
Cc: Dan Streetman <ddstreet@ieee.org>
Cc: <Oleksiy.Avramchenko@sony.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 6818600f
...@@ -250,6 +250,7 @@ static void __release_z3fold_page(struct z3fold_header *zhdr, bool locked) ...@@ -250,6 +250,7 @@ static void __release_z3fold_page(struct z3fold_header *zhdr, bool locked)
WARN_ON(!list_empty(&zhdr->buddy)); WARN_ON(!list_empty(&zhdr->buddy));
set_bit(PAGE_STALE, &page->private); set_bit(PAGE_STALE, &page->private);
clear_bit(NEEDS_COMPACTING, &page->private);
spin_lock(&pool->lock); spin_lock(&pool->lock);
if (!list_empty(&page->lru)) if (!list_empty(&page->lru))
list_del(&page->lru); list_del(&page->lru);
...@@ -303,7 +304,6 @@ static void free_pages_work(struct work_struct *w) ...@@ -303,7 +304,6 @@ static void free_pages_work(struct work_struct *w)
list_del(&zhdr->buddy); list_del(&zhdr->buddy);
if (WARN_ON(!test_bit(PAGE_STALE, &page->private))) if (WARN_ON(!test_bit(PAGE_STALE, &page->private)))
continue; continue;
clear_bit(NEEDS_COMPACTING, &page->private);
spin_unlock(&pool->stale_lock); spin_unlock(&pool->stale_lock);
cancel_work_sync(&zhdr->work); cancel_work_sync(&zhdr->work);
free_z3fold_page(page); free_z3fold_page(page);
...@@ -624,10 +624,8 @@ static int z3fold_alloc(struct z3fold_pool *pool, size_t size, gfp_t gfp, ...@@ -624,10 +624,8 @@ static int z3fold_alloc(struct z3fold_pool *pool, size_t size, gfp_t gfp,
* stale pages list. cancel_work_sync() can sleep so we must make * stale pages list. cancel_work_sync() can sleep so we must make
* sure it won't be called in case we're in atomic context. * sure it won't be called in case we're in atomic context.
*/ */
if (zhdr && (can_sleep || !work_pending(&zhdr->work) || if (zhdr && (can_sleep || !work_pending(&zhdr->work))) {
!unlikely(work_busy(&zhdr->work)))) {
list_del(&zhdr->buddy); list_del(&zhdr->buddy);
clear_bit(NEEDS_COMPACTING, &page->private);
spin_unlock(&pool->stale_lock); spin_unlock(&pool->stale_lock);
if (can_sleep) if (can_sleep)
cancel_work_sync(&zhdr->work); cancel_work_sync(&zhdr->work);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment