On Fri, Jul 26, 2019 at 3:48 PM Henry Burns <henryburns@xxxxxxxxxx> wrote: > > The constraint from the zpool use of z3fold_destroy_pool() is there are no > outstanding handles to memory (so no active allocations), but it is possible > for there to be outstanding work on either of the two wqs in the pool. > > Calling z3fold_deregister_migration() before the workqueues are drained > means that there can be allocated pages referencing a freed inode, > causing any thread in compaction to be able to trip over the bad > pointer in PageMovable(). > > Fixes: 1f862989b04a ("mm/z3fold.c: support page migration") > > Signed-off-by: Henry Burns <henryburns@xxxxxxxxxx> Reviewed-by: Jonathan Adams <jwadams@xxxxxxxxxx> > Cc: <stable@xxxxxxxxxxxxxxx> > --- > mm/z3fold.c | 5 ++++- > 1 file changed, 4 insertions(+), 1 deletion(-) > > diff --git a/mm/z3fold.c b/mm/z3fold.c > index 43de92f52961..ed19d98c9dcd 100644 > --- a/mm/z3fold.c > +++ b/mm/z3fold.c > @@ -817,16 +817,19 @@ static struct z3fold_pool *z3fold_create_pool(const char *name, gfp_t gfp, > static void z3fold_destroy_pool(struct z3fold_pool *pool) > { > kmem_cache_destroy(pool->c_handle); > - z3fold_unregister_migration(pool); > > /* > * We need to destroy pool->compact_wq before pool->release_wq, > * as any pending work on pool->compact_wq will call > * queue_work(pool->release_wq, &pool->work). > + * > + * There are still outstanding pages until both workqueues are drained, > + * so we cannot unregister migration until then. > */ > > destroy_workqueue(pool->compact_wq); > destroy_workqueue(pool->release_wq); > + z3fold_unregister_migration(pool); > kfree(pool); > } > > -- > 2.22.0.709.g102302147b-goog >