aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Piggin <npiggin@suse.de>2007-10-16 04:24:42 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-10-16 12:42:53 -0400
commitb55ed816235cf41c29159d22a4cdeec7deb5821c (patch)
tree73245c1da2c5352c526d4d25f02e69943b4b0b15
parent45726cb43d11b288c58243a26010f397054222f0 (diff)
mm: clarify __add_to_swap_cache locking
__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>
-rw-r--r--mm/swap_state.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/mm/swap_state.c b/mm/swap_state.c
index 67daecb6031a..b52635601dfe 100644
--- a/mm/swap_state.c
+++ b/mm/swap_state.c
@@ -74,6 +74,7 @@ static int __add_to_swap_cache(struct page *page, swp_entry_t entry,
74{ 74{
75 int error; 75 int error;
76 76
77 BUG_ON(!PageLocked(page));
77 BUG_ON(PageSwapCache(page)); 78 BUG_ON(PageSwapCache(page));
78 BUG_ON(PagePrivate(page)); 79 BUG_ON(PagePrivate(page));
79 error = radix_tree_preload(gfp_mask); 80 error = radix_tree_preload(gfp_mask);
@@ -83,7 +84,6 @@ static int __add_to_swap_cache(struct page *page, swp_entry_t entry,
83 entry.val, page); 84 entry.val, page);
84 if (!error) { 85 if (!error) {
85 page_cache_get(page); 86 page_cache_get(page);
86 SetPageLocked(page);
87 SetPageSwapCache(page); 87 SetPageSwapCache(page);
88 set_page_private(page, entry.val); 88 set_page_private(page, entry.val);
89 total_swapcache_pages++; 89 total_swapcache_pages++;
@@ -99,15 +99,18 @@ static int add_to_swap_cache(struct page *page, swp_entry_t entry)
99{ 99{
100 int error; 100 int error;
101 101
102 BUG_ON(PageLocked(page));
102 if (!swap_duplicate(entry)) { 103 if (!swap_duplicate(entry)) {
103 INC_CACHE_INFO(noent_race); 104 INC_CACHE_INFO(noent_race);
104 return -ENOENT; 105 return -ENOENT;
105 } 106 }
107 SetPageLocked(page);
106 error = __add_to_swap_cache(page, entry, GFP_KERNEL); 108 error = __add_to_swap_cache(page, entry, GFP_KERNEL);
107 /* 109 /*
108 * Anon pages are already on the LRU, we don't run lru_cache_add here. 110 * Anon pages are already on the LRU, we don't run lru_cache_add here.
109 */ 111 */
110 if (error) { 112 if (error) {
113 ClearPageLocked(page);
111 swap_free(entry); 114 swap_free(entry);
112 if (error == -EEXIST) 115 if (error == -EEXIST)
113 INC_CACHE_INFO(exist_race); 116 INC_CACHE_INFO(exist_race);