memory-hotplug: update mce_bad_pages when removing the memory
authorWen Congyang <[email protected]>
Wed, 12 Dec 2012 00:00:47 +0000 (16:00 -0800)
committerLinus Torvalds <[email protected]>
Wed, 12 Dec 2012 01:22:22 +0000 (17:22 -0800)
When we hotremove a memory device, we will free the memory to store struct
page.  If the page is hwpoisoned page, we should decrease mce_bad_pages.

[[email protected]: cleanup ifdefs]
Signed-off-by: Wen Congyang <[email protected]>
Cc: David Rientjes <[email protected]>
Cc: Jiang Liu <[email protected]>
Cc: Len Brown <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Christoph Lameter <[email protected]>
Cc: Minchan Kim <[email protected]>
Cc: KOSAKI Motohiro <[email protected]>
Cc: Yasuaki Ishimatsu <[email protected]>
Cc: Dave Hansen <[email protected]>
Cc: Mel Gorman <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
mm/sparse.c

index a83de2f72b3061ee541c3b74fc6ddc6cfb8e202d..c7be019069988e4cb0b11f3c77068212f3478970 100644 (file)
@@ -771,6 +771,27 @@ out:
        return ret;
 }
 
+#ifdef CONFIG_MEMORY_FAILURE
+static void clear_hwpoisoned_pages(struct page *memmap, int nr_pages)
+{
+       int i;
+
+       if (!memmap)
+               return;
+
+       for (i = 0; i < PAGES_PER_SECTION; i++) {
+               if (PageHWPoison(&memmap[i])) {
+                       atomic_long_sub(1, &mce_bad_pages);
+                       ClearPageHWPoison(&memmap[i]);
+               }
+       }
+}
+#else
+static inline void clear_hwpoisoned_pages(struct page *memmap, int nr_pages)
+{
+}
+#endif
+
 void sparse_remove_one_section(struct zone *zone, struct mem_section *ms)
 {
        struct page *memmap = NULL;
@@ -784,6 +805,7 @@ void sparse_remove_one_section(struct zone *zone, struct mem_section *ms)
                ms->pageblock_flags = NULL;
        }
 
+       clear_hwpoisoned_pages(memmap, PAGES_PER_SECTION);
        free_section_usemap(memmap, usemap);
 }
 #endif