Merge branch 'hwpoison-hugepages' into hwpoison
Andi Kleen [Fri, 22 Oct 2010 15:40:48 +0000 (17:40 +0200)]
Conflicts:
mm/memory-failure.c

1  2 
arch/x86/mm/fault.c
include/linux/mm.h
mm/memory-failure.c
mm/memory.c

Simple merge
Simple merge
@@@ -1145,9 -1175,19 +1166,19 @@@ int unpoison_memory(unsigned long pfn
        nr_pages = 1 << compound_order(page);
  
        if (!get_page_unless_zero(page)) {
+               /*
+                * Since HWPoisoned hugepage should have non-zero refcount,
+                * race between memory failure and unpoison seems to happen.
+                * In such case unpoison fails and memory failure runs
+                * to the end.
+                */
+               if (PageHuge(page)) {
+                       pr_debug("MCE: Memory failure is now running on free hugepage %#lx\n", pfn);
+                       return 0;
+               }
                if (TestClearPageHWPoison(p))
                        atomic_long_sub(nr_pages, &mce_bad_pages);
 -              pr_debug("MCE: Software-unpoisoned free page %#lx\n", pfn);
 +              pr_info("MCE: Software-unpoisoned free page %#lx\n", pfn);
                return 0;
        }
  
         * the free buddy page pool.
         */
        if (TestClearPageHWPoison(page)) {
 -              pr_debug("MCE: Software-unpoisoned page %#lx\n", pfn);
 +              pr_info("MCE: Software-unpoisoned page %#lx\n", pfn);
                atomic_long_sub(nr_pages, &mce_bad_pages);
                freeit = 1;
+               if (PageHuge(page))
+                       clear_page_hwpoison_huge_page(page);
        }
-       if (PageHuge(p))
-               clear_page_hwpoison_huge_page(page);
        unlock_page(page);
  
        put_page(page);
@@@ -1206,9 -1250,16 +1241,16 @@@ static int get_any_page(struct page *p
         * was free.
         */
        set_migratetype_isolate(p);
+       /*
+        * When the target page is a free hugepage, just remove it
+        * from free hugepage list.
+        */
        if (!get_page_unless_zero(compound_head(p))) {
-               if (is_free_buddy_page(p)) {
+               if (PageHuge(p)) {
 -                      pr_debug("get_any_page: %#lx free huge page\n", pfn);
++                      pr_info("get_any_page: %#lx free huge page\n", pfn);
+                       ret = dequeue_hwpoisoned_huge_page(compound_head(p));
+               } else if (is_free_buddy_page(p)) {
 -                      pr_debug("get_any_page: %#lx free buddy page\n", pfn);
 +                      pr_info("get_any_page: %#lx free buddy page\n", pfn);
                        /* Set hwpoison bit while page is still isolated */
                        SetPageHWPoison(p);
                        ret = 0;
diff --cc mm/memory.c
Simple merge