diff options
author | Pravin B Shelar <pshelar@nicira.com> | 2012-05-29 18:06:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-29 19:22:24 -0400 |
commit | 5bf5f03c271907978489868a4c72aeb42b5127d2 (patch) | |
tree | 2d6b283fa5ee83b723fd4b4a8f070ae53c60ebe9 /include/linux/mm.h | |
parent | dbda591d920b4c7692725b13e3f68ecb251e9080 (diff) |
mm: fix slab->page flags corruption
Transparent huge pages can change page->flags (PG_compound_lock) without
taking Slab lock. Since THP can not break slab pages we can safely access
compound page without taking compound lock.
Specifically this patch fixes a race between compound_unlock() and slab
functions which perform page-flags updates. This can occur when
get_page()/put_page() is called on a page from slab.
[akpm@linux-foundation.org: tweak comment text, fix comment layout, fix label indenting]
Reported-by: Amey Bhide <abhide@nicira.com>
Signed-off-by: Pravin B Shelar <pshelar@nicira.com>
Reviewed-by: Christoph Lameter <cl@linux.com>
Acked-by: Andrea Arcangeli <aarcange@redhat.com>
Cc: Pekka Enberg <penberg@cs.helsinki.fi>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include/linux/mm.h')
-rw-r--r-- | include/linux/mm.h | 2 |
1 files changed, 2 insertions, 0 deletions
diff --git a/include/linux/mm.h b/include/linux/mm.h index aa20bafa40f6..ce26716238c3 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -321,6 +321,7 @@ static inline int is_vmalloc_or_module_addr(const void *x) | |||
321 | static inline void compound_lock(struct page *page) | 321 | static inline void compound_lock(struct page *page) |
322 | { | 322 | { |
323 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 323 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
324 | VM_BUG_ON(PageSlab(page)); | ||
324 | bit_spin_lock(PG_compound_lock, &page->flags); | 325 | bit_spin_lock(PG_compound_lock, &page->flags); |
325 | #endif | 326 | #endif |
326 | } | 327 | } |
@@ -328,6 +329,7 @@ static inline void compound_lock(struct page *page) | |||
328 | static inline void compound_unlock(struct page *page) | 329 | static inline void compound_unlock(struct page *page) |
329 | { | 330 | { |
330 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | 331 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE |
332 | VM_BUG_ON(PageSlab(page)); | ||
331 | bit_spin_unlock(PG_compound_lock, &page->flags); | 333 | bit_spin_unlock(PG_compound_lock, &page->flags); |
332 | #endif | 334 | #endif |
333 | } | 335 | } |