diff options
author | Andrea Arcangeli <aarcange@redhat.com> | 2011-01-13 18:46:33 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-13 20:32:39 -0500 |
commit | a95a82e96c48270980dd248ccd5546f1b49e6f8a (patch) | |
tree | 35f10c2a8d2cd0e1aa9d33f7a4f55332c0733ee6 /mm/swap.c | |
parent | 9180706344487700b40da9eca5dedd3d11cb33b4 (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.c | 8 |
1 files changed, 6 insertions, 2 deletions
@@ -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)); |