Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1a87aa0

Browse files
HenryBurnstorvalds
authored andcommitted
mm/zsmalloc.c: migration can leave pages in ZS_EMPTY indefinitely
In zs_page_migrate() we call putback_zspage() after we have finished migrating all pages in this zspage. However, the return value is ignored. If a zs_free() races in between zs_page_isolate() and zs_page_migrate(), freeing the last object in the zspage, putback_zspage() will leave the page in ZS_EMPTY for potentially an unbounded amount of time. To fix this, we need to do the same thing as zs_page_putback() does: schedule free_work to occur. To avoid duplicated code, move the sequence to a new putback_zspage_deferred() function which both zs_page_migrate() and zs_page_putback() call. Link: http://lkml.kernel.org/r/[email protected] Fixes: 48b4800 ("zsmalloc: page migration support") Signed-off-by: Henry Burns <[email protected]> Reviewed-by: Sergey Senozhatsky <[email protected]> Cc: Henry Burns <[email protected]> Cc: Minchan Kim <[email protected]> Cc: Shakeel Butt <[email protected]> Cc: Jonathan Adams <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent f7da677 commit 1a87aa0

File tree

1 file changed

+15
-4
lines changed

1 file changed

+15
-4
lines changed

mm/zsmalloc.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1862,6 +1862,18 @@ static void dec_zspage_isolation(struct zspage *zspage)
18621862
zspage->isolated--;
18631863
}
18641864

1865+
static void putback_zspage_deferred(struct zs_pool *pool,
1866+
struct size_class *class,
1867+
struct zspage *zspage)
1868+
{
1869+
enum fullness_group fg;
1870+
1871+
fg = putback_zspage(class, zspage);
1872+
if (fg == ZS_EMPTY)
1873+
schedule_work(&pool->free_work);
1874+
1875+
}
1876+
18651877
static void replace_sub_page(struct size_class *class, struct zspage *zspage,
18661878
struct page *newpage, struct page *oldpage)
18671879
{
@@ -2031,7 +2043,7 @@ static int zs_page_migrate(struct address_space *mapping, struct page *newpage,
20312043
* the list if @page is final isolated subpage in the zspage.
20322044
*/
20332045
if (!is_zspage_isolated(zspage))
2034-
putback_zspage(class, zspage);
2046+
putback_zspage_deferred(pool, class, zspage);
20352047

20362048
reset_page(page);
20372049
put_page(page);
@@ -2077,14 +2089,13 @@ static void zs_page_putback(struct page *page)
20772089
spin_lock(&class->lock);
20782090
dec_zspage_isolation(zspage);
20792091
if (!is_zspage_isolated(zspage)) {
2080-
fg = putback_zspage(class, zspage);
20812092
/*
20822093
* Due to page_lock, we cannot free zspage immediately
20832094
* so let's defer.
20842095
*/
2085-
if (fg == ZS_EMPTY)
2086-
schedule_work(&pool->free_work);
2096+
putback_zspage_deferred(pool, class, zspage);
20872097
}
2098+
20882099
spin_unlock(&class->lock);
20892100
}
20902101

0 commit comments

Comments
 (0)