memory-hotplug: skip HWPoisoned page when offlining pages
[deliverable/linux.git] / mm / page_alloc.c
index a49b0ea3cc2fc5acd6a096ec838f32a131474c8c..6f50cfe98a7b6dda0be18387f501c2458f362061 100644 (file)
@@ -5616,7 +5616,8 @@ void set_pageblock_flags_group(struct page *page, unsigned long flags,
  * MIGRATE_MOVABLE block might include unmovable pages. It means you can't
  * expect this function should be exact.
  */
-bool has_unmovable_pages(struct zone *zone, struct page *page, int count)
+bool has_unmovable_pages(struct zone *zone, struct page *page, int count,
+                        bool skip_hwpoisoned_pages)
 {
        unsigned long pfn, iter, found;
        int mt;
@@ -5651,6 +5652,13 @@ bool has_unmovable_pages(struct zone *zone, struct page *page, int count)
                        continue;
                }
 
+               /*
+                * The HWPoisoned page may be not in buddy system, and
+                * page_count() is not 0.
+                */
+               if (skip_hwpoisoned_pages && PageHWPoison(page))
+                       continue;
+
                if (!PageLRU(page))
                        found++;
                /*
@@ -5693,7 +5701,7 @@ bool is_pageblock_removable_nolock(struct page *page)
                        zone->zone_start_pfn + zone->spanned_pages <= pfn)
                return false;
 
-       return !has_unmovable_pages(zone, page, 0);
+       return !has_unmovable_pages(zone, page, 0, true);
 }
 
 #ifdef CONFIG_CMA
@@ -5864,7 +5872,8 @@ int alloc_contig_range(unsigned long start, unsigned long end,
         */
 
        ret = start_isolate_page_range(pfn_max_align_down(start),
-                                      pfn_max_align_up(end), migratetype);
+                                      pfn_max_align_up(end), migratetype,
+                                      false);
        if (ret)
                return ret;
 
@@ -5903,7 +5912,7 @@ int alloc_contig_range(unsigned long start, unsigned long end,
        }
 
        /* Make sure the range is really isolated. */
-       if (test_pages_isolated(outer_start, end)) {
+       if (test_pages_isolated(outer_start, end, false)) {
                pr_warn("alloc_contig_range test_pages_isolated(%lx, %lx) failed\n",
                       outer_start, end);
                ret = -EBUSY;
@@ -6018,6 +6027,16 @@ __offline_isolated_pages(unsigned long start_pfn, unsigned long end_pfn)
                        continue;
                }
                page = pfn_to_page(pfn);
+               /*
+                * The HWPoisoned page may be not in buddy system, and
+                * page_count() is not 0.
+                */
+               if (unlikely(!PageBuddy(page) && PageHWPoison(page))) {
+                       pfn++;
+                       SetPageReserved(page);
+                       continue;
+               }
+
                BUG_ON(page_count(page));
                BUG_ON(!PageBuddy(page));
                order = page_order(page);
This page took 0.025201 seconds and 5 git commands to generate.