forked from Minki/linux
mm: add_to_swap_cache() does not return -EEXIST
After commit 355cfa73
("mm: modify swap_map and add SWAP_HAS_CACHE flag"),
only the context which have set SWAP_HAS_CACHE flag by swapcache_prepare()
or get_swap_page() would call add_to_swap_cache(). So add_to_swap_cache()
doesn't return -EEXIST any more.
Even though it doesn't return -EEXIST, it's not good behavior conceptually
to call swapcache_prepare() in the -EEXIST case, because it means clearing
SWAP_HAS_CACHE flag while the entry is on swap cache.
This patch removes redundant codes and comments from callers of it, and
adds VM_BUG_ON() in error path of add_to_swap_cache() and some comments.
Signed-off-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Cc: Balbir Singh <balbir@linux.vnet.ibm.com>
Cc: Hugh Dickins <hugh.dickins@tiscali.co.uk>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
31a5639623
commit
2ca4532a49
@ -1097,6 +1097,10 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
|
||||
shmem_swp_unmap(entry);
|
||||
unlock:
|
||||
spin_unlock(&info->lock);
|
||||
/*
|
||||
* add_to_swap_cache() doesn't return -EEXIST, so we can safely
|
||||
* clear SWAP_HAS_CACHE flag.
|
||||
*/
|
||||
swapcache_free(swap, NULL);
|
||||
redirty:
|
||||
set_page_dirty(page);
|
||||
|
@ -92,6 +92,12 @@ static int __add_to_swap_cache(struct page *page, swp_entry_t entry)
|
||||
spin_unlock_irq(&swapper_space.tree_lock);
|
||||
|
||||
if (unlikely(error)) {
|
||||
/*
|
||||
* Only the context which have set SWAP_HAS_CACHE flag
|
||||
* would call add_to_swap_cache().
|
||||
* So add_to_swap_cache() doesn't returns -EEXIST.
|
||||
*/
|
||||
VM_BUG_ON(error == -EEXIST);
|
||||
set_page_private(page, 0UL);
|
||||
ClearPageSwapCache(page);
|
||||
page_cache_release(page);
|
||||
@ -146,38 +152,34 @@ int add_to_swap(struct page *page)
|
||||
VM_BUG_ON(!PageLocked(page));
|
||||
VM_BUG_ON(!PageUptodate(page));
|
||||
|
||||
for (;;) {
|
||||
entry = get_swap_page();
|
||||
if (!entry.val)
|
||||
return 0;
|
||||
entry = get_swap_page();
|
||||
if (!entry.val)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* Radix-tree node allocations from PF_MEMALLOC contexts could
|
||||
* completely exhaust the page allocator. __GFP_NOMEMALLOC
|
||||
* stops emergency reserves from being allocated.
|
||||
*
|
||||
* TODO: this could cause a theoretical memory reclaim
|
||||
* deadlock in the swap out path.
|
||||
*/
|
||||
/*
|
||||
* Add it to the swap cache and mark it dirty
|
||||
*/
|
||||
err = add_to_swap_cache(page, entry,
|
||||
__GFP_HIGH|__GFP_NOMEMALLOC|__GFP_NOWARN);
|
||||
/*
|
||||
* Radix-tree node allocations from PF_MEMALLOC contexts could
|
||||
* completely exhaust the page allocator. __GFP_NOMEMALLOC
|
||||
* stops emergency reserves from being allocated.
|
||||
*
|
||||
* TODO: this could cause a theoretical memory reclaim
|
||||
* deadlock in the swap out path.
|
||||
*/
|
||||
/*
|
||||
* Add it to the swap cache and mark it dirty
|
||||
*/
|
||||
err = add_to_swap_cache(page, entry,
|
||||
__GFP_HIGH|__GFP_NOMEMALLOC|__GFP_NOWARN);
|
||||
|
||||
switch (err) {
|
||||
case 0: /* Success */
|
||||
SetPageDirty(page);
|
||||
return 1;
|
||||
case -EEXIST:
|
||||
/* Raced with "speculative" read_swap_cache_async */
|
||||
swapcache_free(entry, NULL);
|
||||
continue;
|
||||
default:
|
||||
/* -ENOMEM radix-tree allocation failure */
|
||||
swapcache_free(entry, NULL);
|
||||
return 0;
|
||||
}
|
||||
if (!err) { /* Success */
|
||||
SetPageDirty(page);
|
||||
return 1;
|
||||
} else { /* -ENOMEM radix-tree allocation failure */
|
||||
/*
|
||||
* add_to_swap_cache() doesn't return -EEXIST, so we can safely
|
||||
* clear SWAP_HAS_CACHE flag.
|
||||
*/
|
||||
swapcache_free(entry, NULL);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@ -318,14 +320,7 @@ struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Associate the page with swap entry in the swap cache.
|
||||
* May fail (-EEXIST) if there is already a page associated
|
||||
* with this entry in the swap cache: added by a racing
|
||||
* read_swap_cache_async, or add_to_swap or shmem_writepage
|
||||
* re-using the just freed swap entry for an existing page.
|
||||
* May fail (-ENOMEM) if radix-tree node allocation failed.
|
||||
*/
|
||||
/* May fail (-ENOMEM) if radix-tree node allocation failed. */
|
||||
__set_page_locked(new_page);
|
||||
SetPageSwapBacked(new_page);
|
||||
err = __add_to_swap_cache(new_page, entry);
|
||||
@ -341,6 +336,10 @@ struct page *read_swap_cache_async(swp_entry_t entry, gfp_t gfp_mask,
|
||||
radix_tree_preload_end();
|
||||
ClearPageSwapBacked(new_page);
|
||||
__clear_page_locked(new_page);
|
||||
/*
|
||||
* add_to_swap_cache() doesn't return -EEXIST, so we can safely
|
||||
* clear SWAP_HAS_CACHE flag.
|
||||
*/
|
||||
swapcache_free(entry, NULL);
|
||||
} while (err != -ENOMEM);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user