| From: Sergey Senozhatsky <senozhatsky@chromium.org> |
| Subject: zsmalloc: reset compaction source zspage pointer after putback_zspage() |
| Date: Mon, 17 Apr 2023 22:08:50 +0900 |
| |
| The current implementation of the compaction loop fails to set the source |
| zspage pointer to NULL in all cases, leading to a potential issue where |
| __zs_compact() could use a stale zspage pointer. This pointer could even |
| point to a previously freed zspage, causing unexpected behavior in the |
| putback_zspage() and migrate_write_unlock() functions after returning from |
| the compaction loop. |
| |
| Address the issue by ensuring that the source zspage pointer is always set |
| to NULL when it should be. |
| |
| Link: https://lkml.kernel.org/r/20230417130850.1784777-1-senozhatsky@chromium.org |
| Fixes: 5a845e9f2d66 ("zsmalloc: rework compaction algorithm") |
| Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org> |
| Reported-by: Yu Zhao <yuzhao@google.com> |
| Tested-by: Yu Zhao <yuzhao@google.com> |
| Reviewed-by: Yosry Ahmed <yosryahmed@google.com> |
| Signed-off-by: Andrew Morton <akpm@linux-foundation.org> |
| --- |
| |
| mm/zsmalloc.c | 2 +- |
| 1 file changed, 1 insertion(+), 1 deletion(-) |
| |
| --- a/mm/zsmalloc.c~zsmalloc-reset-compaction-source-zspage-pointer-after-putback_zspage |
| +++ a/mm/zsmalloc.c |
| @@ -2239,8 +2239,8 @@ static unsigned long __zs_compact(struct |
| if (fg == ZS_INUSE_RATIO_0) { |
| free_zspage(pool, class, src_zspage); |
| pages_freed += class->pages_per_zspage; |
| - src_zspage = NULL; |
| } |
| + src_zspage = NULL; |
| |
| if (get_fullness_group(class, dst_zspage) == ZS_INUSE_RATIO_100 |
| || spin_is_contended(&pool->lock)) { |
| _ |