diff options
Diffstat (limited to 'mm/sparse.c')
-rw-r--r-- | mm/sparse.c | 12 |
1 files changed, 8 insertions, 4 deletions
diff --git a/mm/sparse.c b/mm/sparse.c index 6b5fb762e2ca..7ca6dc847947 100644 --- a/mm/sparse.c +++ b/mm/sparse.c | |||
@@ -615,10 +615,11 @@ static inline struct page *kmalloc_section_memmap(unsigned long pnum, int nid, | |||
615 | } | 615 | } |
616 | static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages) | 616 | static void __kfree_section_memmap(struct page *memmap, unsigned long nr_pages) |
617 | { | 617 | { |
618 | return; /* XXX: Not implemented yet */ | 618 | vmemmap_free(memmap, nr_pages); |
619 | } | 619 | } |
620 | static void free_map_bootmem(struct page *memmap, unsigned long nr_pages) | 620 | static void free_map_bootmem(struct page *memmap, unsigned long nr_pages) |
621 | { | 621 | { |
622 | vmemmap_free(memmap, nr_pages); | ||
622 | } | 623 | } |
623 | #else | 624 | #else |
624 | static struct page *__kmalloc_section_memmap(unsigned long nr_pages) | 625 | static struct page *__kmalloc_section_memmap(unsigned long nr_pages) |
@@ -697,7 +698,7 @@ static void free_section_usemap(struct page *memmap, unsigned long *usemap) | |||
697 | /* | 698 | /* |
698 | * Check to see if allocation came from hot-plug-add | 699 | * Check to see if allocation came from hot-plug-add |
699 | */ | 700 | */ |
700 | if (PageSlab(usemap_page)) { | 701 | if (PageSlab(usemap_page) || PageCompound(usemap_page)) { |
701 | kfree(usemap); | 702 | kfree(usemap); |
702 | if (memmap) | 703 | if (memmap) |
703 | __kfree_section_memmap(memmap, PAGES_PER_SECTION); | 704 | __kfree_section_memmap(memmap, PAGES_PER_SECTION); |
@@ -782,7 +783,7 @@ static void clear_hwpoisoned_pages(struct page *memmap, int nr_pages) | |||
782 | 783 | ||
783 | for (i = 0; i < PAGES_PER_SECTION; i++) { | 784 | for (i = 0; i < PAGES_PER_SECTION; i++) { |
784 | if (PageHWPoison(&memmap[i])) { | 785 | if (PageHWPoison(&memmap[i])) { |
785 | atomic_long_sub(1, &mce_bad_pages); | 786 | atomic_long_sub(1, &num_poisoned_pages); |
786 | ClearPageHWPoison(&memmap[i]); | 787 | ClearPageHWPoison(&memmap[i]); |
787 | } | 788 | } |
788 | } | 789 | } |
@@ -796,8 +797,10 @@ static inline void clear_hwpoisoned_pages(struct page *memmap, int nr_pages) | |||
796 | void sparse_remove_one_section(struct zone *zone, struct mem_section *ms) | 797 | void sparse_remove_one_section(struct zone *zone, struct mem_section *ms) |
797 | { | 798 | { |
798 | struct page *memmap = NULL; | 799 | struct page *memmap = NULL; |
799 | unsigned long *usemap = NULL; | 800 | unsigned long *usemap = NULL, flags; |
801 | struct pglist_data *pgdat = zone->zone_pgdat; | ||
800 | 802 | ||
803 | pgdat_resize_lock(pgdat, &flags); | ||
801 | if (ms->section_mem_map) { | 804 | if (ms->section_mem_map) { |
802 | usemap = ms->pageblock_flags; | 805 | usemap = ms->pageblock_flags; |
803 | memmap = sparse_decode_mem_map(ms->section_mem_map, | 806 | memmap = sparse_decode_mem_map(ms->section_mem_map, |
@@ -805,6 +808,7 @@ void sparse_remove_one_section(struct zone *zone, struct mem_section *ms) | |||
805 | ms->section_mem_map = 0; | 808 | ms->section_mem_map = 0; |
806 | ms->pageblock_flags = NULL; | 809 | ms->pageblock_flags = NULL; |
807 | } | 810 | } |
811 | pgdat_resize_unlock(pgdat, &flags); | ||
808 | 812 | ||
809 | clear_hwpoisoned_pages(memmap, PAGES_PER_SECTION); | 813 | clear_hwpoisoned_pages(memmap, PAGES_PER_SECTION); |
810 | free_section_usemap(memmap, usemap); | 814 | free_section_usemap(memmap, usemap); |