]>
Commit | Line | Data |
---|---|---|
59cd8bf3 GKH |
1 | From aca50bd3b4c4bb5528a1878158ba7abce41de534 Mon Sep 17 00:00:00 2001 |
2 | From: Hugh Dickins <hughd@google.com> | |
3 | Date: Mon, 23 Apr 2012 11:14:50 -0700 | |
4 | Subject: mm: fix s390 BUG by __set_page_dirty_no_writeback on swap | |
5 | ||
6 | From: Hugh Dickins <hughd@google.com> | |
7 | ||
8 | commit aca50bd3b4c4bb5528a1878158ba7abce41de534 upstream. | |
9 | ||
10 | Mel reports a BUG_ON(slot == NULL) in radix_tree_tag_set() on s390 | |
11 | 3.0.13: called from __set_page_dirty_nobuffers() when page_remove_rmap() | |
12 | tries to transfer dirty flag from s390 storage key to struct page and | |
13 | radix_tree. | |
14 | ||
15 | That would be because of reclaim's shrink_page_list() calling | |
16 | add_to_swap() on this page at the same time: first PageSwapCache is set | |
17 | (causing page_mapping(page) to appear as &swapper_space), then | |
18 | page->private set, then tree_lock taken, then page inserted into | |
19 | radix_tree - so there's an interval before taking the lock when the | |
20 | radix_tree slot is empty. | |
21 | ||
22 | We could fix this by moving __add_to_swap_cache()'s spin_lock_irq up | |
23 | before the SetPageSwapCache. But a better fix is simply to do what's | |
24 | five years overdue: Ken Chen introduced __set_page_dirty_no_writeback() | |
25 | (if !PageDirty TestSetPageDirty) for tmpfs to skip all the radix_tree | |
26 | overhead, and swap is just the same - it ignores the radix_tree tag, and | |
27 | does not participate in dirty page accounting, so should be using | |
28 | __set_page_dirty_no_writeback() too. | |
29 | ||
30 | s390 testing now confirms that this does indeed fix the problem. | |
31 | ||
32 | Reported-by: Mel Gorman <mgorman@suse.de> | |
33 | Signed-off-by: Hugh Dickins <hughd@google.com> | |
34 | Acked-by: Mel Gorman <mgorman@suse.de> | |
35 | Cc: Andrew Morton <akpm@linux-foundation.org> | |
36 | Cc: Martin Schwidefsky <schwidefsky@de.ibm.com> | |
37 | Cc: Heiko Carstens <heiko.carstens@de.ibm.com> | |
38 | Cc: Rik van Riel <riel@redhat.com> | |
39 | Cc: Ken Chen <kenchen@google.com> | |
40 | Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> | |
41 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
42 | ||
43 | --- | |
44 | mm/swap_state.c | 2 +- | |
45 | 1 file changed, 1 insertion(+), 1 deletion(-) | |
46 | ||
47 | --- a/mm/swap_state.c | |
48 | +++ b/mm/swap_state.c | |
49 | @@ -26,7 +26,7 @@ | |
50 | */ | |
51 | static const struct address_space_operations swap_aops = { | |
52 | .writepage = swap_writepage, | |
53 | - .set_page_dirty = __set_page_dirty_nobuffers, | |
54 | + .set_page_dirty = __set_page_dirty_no_writeback, | |
55 | .migratepage = migrate_page, | |
56 | }; | |
57 |