]> git.karo-electronics.de Git - mv-sheeva.git/commitdiff
thp: fix memory-failure hugetlbfs vs THP collision
authorAndrea Arcangeli <aarcange@redhat.com>
Thu, 13 Jan 2011 23:47:16 +0000 (15:47 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 14 Jan 2011 01:32:47 +0000 (17:32 -0800)
hugetlbfs was changed to allow memory failure to migrate the hugetlbfs
pages and that broke THP as split_huge_page was then called on hugetlbfs
pages too.

compound_head/order was also run unsafe on THP pages that can be splitted
at any time.

All compound_head() invocations in memory-failure.c that are run on pages
that aren't pinned and that can be freed and reused from under us (while
compound_head is running) are buggy because compound_head can return a
dangling pointer, but I'm not fixing this as this is a generic
memory-failure bug not specific to THP but it applies to hugetlbfs too, so
I can fix it later after THP is merged upstream.

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>
mm/memory-failure.c
mm/rmap.c

index 6a283cc9317c52053e16a2bcf8ebaabb23634ad8..1b43d0ffff6523626d04253afa66d32c6781df92 100644 (file)
@@ -386,7 +386,7 @@ static void collect_procs_anon(struct page *page, struct list_head *to_kill,
        struct task_struct *tsk;
        struct anon_vma *av;
 
-       if (unlikely(split_huge_page(page)))
+       if (!PageHuge(page) && unlikely(split_huge_page(page)))
                return;
        read_lock(&tasklist_lock);
        av = page_lock_anon_vma(page);
index 3825ae4bc32f971be5c2c3536f145f200036a0f0..c30f33854f9751ff27dac942bbcdbbdfb30bd200 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -1430,7 +1430,7 @@ int try_to_unmap(struct page *page, enum ttu_flags flags)
        int ret;
 
        BUG_ON(!PageLocked(page));
-       BUG_ON(PageTransHuge(page));
+       VM_BUG_ON(!PageHuge(page) && PageTransHuge(page));
 
        if (unlikely(PageKsm(page)))
                ret = try_to_unmap_ksm(page, flags);