aboutsummaryrefslogtreecommitdiffstats
path: root/mm/swap.c
diff options
context:
space:
mode:
authorAndrea Arcangeli <aarcange@redhat.com>2011-01-13 18:46:33 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 20:32:39 -0500
commita95a82e96c48270980dd248ccd5546f1b49e6f8a (patch)
tree35f10c2a8d2cd0e1aa9d33f7a4f55332c0733ee6 /mm/swap.c
parent9180706344487700b40da9eca5dedd3d11cb33b4 (diff)
thp: put_page: recheck PageHead after releasing the compound_lock
After releasing the compound_lock split_huge_page can still run and release the page before put_page_testzero runs. Signed-off-by: Andrea Arcangeli <aarcange@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/swap.c')
-rw-r--r--mm/swap.c8
1 files changed, 6 insertions, 2 deletions
diff --git a/mm/swap.c b/mm/swap.c
index 33f5292fe132..e0eeef940886 100644
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -131,8 +131,12 @@ static void put_compound_page(struct page *page)
131 atomic_dec(&page->_count); 131 atomic_dec(&page->_count);
132 VM_BUG_ON(atomic_read(&page_head->_count) <= 0); 132 VM_BUG_ON(atomic_read(&page_head->_count) <= 0);
133 compound_unlock_irqrestore(page_head, flags); 133 compound_unlock_irqrestore(page_head, flags);
134 if (put_page_testzero(page_head)) 134 if (put_page_testzero(page_head)) {
135 __put_compound_page(page_head); 135 if (PageHead(page_head))
136 __put_compound_page(page_head);
137 else
138 __put_single_page(page_head);
139 }
136 } else { 140 } else {
137 /* page_head is a dangling pointer */ 141 /* page_head is a dangling pointer */
138 VM_BUG_ON(PageTail(page)); 142 VM_BUG_ON(PageTail(page));