mirror of
https://github.com/adulau/aha.git
synced 2024-12-27 11:16:11 +00:00
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
2 changed files with 41 additions and 38 deletions
|
@ -1097,6 +1097,10 @@ static int shmem_writepage(struct page *page, struct writeback_control *wbc)
|
||||||
shmem_swp_unmap(entry);
|
shmem_swp_unmap(entry);
|
||||||
unlock:
|
unlock:
|
||||||
spin_unlock(&info->lock);
|
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);
|
swapcache_free(swap, NULL);
|
||||||
redirty:
|
redirty:
|
||||||
set_page_dirty(page);
|
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);
|
spin_unlock_irq(&swapper_space.tree_lock);
|
||||||
|
|
||||||
if (unlikely(error)) {
|
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);
|
set_page_private(page, 0UL);
|
||||||
ClearPageSwapCache(page);
|
ClearPageSwapCache(page);
|
||||||
page_cache_release(page);
|
page_cache_release(page);
|
||||||
|
@ -146,38 +152,34 @@ int add_to_swap(struct page *page)
|
||||||
VM_BUG_ON(!PageLocked(page));
|
VM_BUG_ON(!PageLocked(page));
|
||||||
VM_BUG_ON(!PageUptodate(page));
|
VM_BUG_ON(!PageUptodate(page));
|
||||||
|
|
||||||
for (;;) {
|
entry = get_swap_page();
|
||||||
entry = get_swap_page();
|
if (!entry.val)
|
||||||
if (!entry.val)
|
return 0;
|
||||||
return 0;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Radix-tree node allocations from PF_MEMALLOC contexts could
|
* Radix-tree node allocations from PF_MEMALLOC contexts could
|
||||||
* completely exhaust the page allocator. __GFP_NOMEMALLOC
|
* completely exhaust the page allocator. __GFP_NOMEMALLOC
|
||||||
* stops emergency reserves from being allocated.
|
* stops emergency reserves from being allocated.
|
||||||
*
|
*
|
||||||
* TODO: this could cause a theoretical memory reclaim
|
* TODO: this could cause a theoretical memory reclaim
|
||||||
* deadlock in the swap out path.
|
* deadlock in the swap out path.
|
||||||
*/
|
*/
|
||||||
/*
|
/*
|
||||||
* Add it to the swap cache and mark it dirty
|
* Add it to the swap cache and mark it dirty
|
||||||
*/
|
*/
|
||||||
err = add_to_swap_cache(page, entry,
|
err = add_to_swap_cache(page, entry,
|
||||||
__GFP_HIGH|__GFP_NOMEMALLOC|__GFP_NOWARN);
|
__GFP_HIGH|__GFP_NOMEMALLOC|__GFP_NOWARN);
|
||||||
|
|
||||||
switch (err) {
|
if (!err) { /* Success */
|
||||||
case 0: /* Success */
|
SetPageDirty(page);
|
||||||
SetPageDirty(page);
|
return 1;
|
||||||
return 1;
|
} else { /* -ENOMEM radix-tree allocation failure */
|
||||||
case -EEXIST:
|
/*
|
||||||
/* Raced with "speculative" read_swap_cache_async */
|
* add_to_swap_cache() doesn't return -EEXIST, so we can safely
|
||||||
swapcache_free(entry, NULL);
|
* clear SWAP_HAS_CACHE flag.
|
||||||
continue;
|
*/
|
||||||
default:
|
swapcache_free(entry, NULL);
|
||||||
/* -ENOMEM radix-tree allocation failure */
|
return 0;
|
||||||
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* May fail (-ENOMEM) if radix-tree node allocation failed. */
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
__set_page_locked(new_page);
|
__set_page_locked(new_page);
|
||||||
SetPageSwapBacked(new_page);
|
SetPageSwapBacked(new_page);
|
||||||
err = __add_to_swap_cache(new_page, entry);
|
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();
|
radix_tree_preload_end();
|
||||||
ClearPageSwapBacked(new_page);
|
ClearPageSwapBacked(new_page);
|
||||||
__clear_page_locked(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);
|
swapcache_free(entry, NULL);
|
||||||
} while (err != -ENOMEM);
|
} while (err != -ENOMEM);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue