From: Nick Piggin __add_to_swap_cache unconditionally sets the page locked, which can be a bit alarming to the unsuspecting reader: in the code paths where the page is visible to other CPUs, the page should be (and is) already locked. Instead, just add a check to ensure the page is locked here, and teach the one path relying on the old behaviour to call SetPageLocked itself. Signed-off-by: Nick Piggin Cc: Hugh Dickins Signed-off-by: Andrew Morton --- mm/swap_state.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff -puN mm/swap_state.c~mm-clarify-__add_to_swap_cache-locking mm/swap_state.c --- a/mm/swap_state.c~mm-clarify-__add_to_swap_cache-locking +++ a/mm/swap_state.c @@ -74,6 +74,7 @@ static int __add_to_swap_cache(struct pa { int error; + BUG_ON(!PageLocked(page)); BUG_ON(PageSwapCache(page)); BUG_ON(PagePrivate(page)); error = radix_tree_preload(gfp_mask); @@ -83,7 +84,6 @@ static int __add_to_swap_cache(struct pa entry.val, page); if (!error) { page_cache_get(page); - SetPageLocked(page); SetPageSwapCache(page); set_page_private(page, entry.val); total_swapcache_pages++; @@ -338,6 +338,7 @@ struct page *read_swap_cache_async(swp_e vma, addr); if (!new_page) break; /* Out of memory */ + SetPageLocked(new_page);/* could be non-atomic op */ } /* @@ -361,7 +362,9 @@ struct page *read_swap_cache_async(swp_e } } while (err != -ENOENT && err != -ENOMEM); - if (new_page) + if (new_page) { + ClearPageLocked(new_page); page_cache_release(new_page); + } return found_page; } _