__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.
[hugh@veritas.com: locking fix]
Signed-off-by: Nick Piggin <npiggin@suse.de>
Signed-off-by: Hugh Dickins <hugh@veritas.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
 {
        int error;
 
+       BUG_ON(!PageLocked(page));
        BUG_ON(PageSwapCache(page));
        BUG_ON(PagePrivate(page));
        error = radix_tree_preload(gfp_mask);
                                                entry.val, page);
                if (!error) {
                        page_cache_get(page);
-                       SetPageLocked(page);
                        SetPageSwapCache(page);
                        set_page_private(page, entry.val);
                        total_swapcache_pages++;
 {
        int error;
 
+       BUG_ON(PageLocked(page));
        if (!swap_duplicate(entry)) {
                INC_CACHE_INFO(noent_race);
                return -ENOENT;
        }
+       SetPageLocked(page);
        error = __add_to_swap_cache(page, entry, GFP_KERNEL);
        /*
         * Anon pages are already on the LRU, we don't run lru_cache_add here.
         */
        if (error) {
+               ClearPageLocked(page);
                swap_free(entry);
                if (error == -EEXIST)
                        INC_CACHE_INFO(exist_race);