diff options
Diffstat (limited to 'mm/memory-failure.c')
| -rw-r--r-- | mm/memory-failure.c | 28 |
1 files changed, 20 insertions, 8 deletions
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 473f15a3356d..d0b420aba726 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c | |||
| @@ -690,17 +690,29 @@ static int me_swapcache_clean(struct page *p, unsigned long pfn) | |||
| 690 | /* | 690 | /* |
| 691 | * Huge pages. Needs work. | 691 | * Huge pages. Needs work. |
| 692 | * Issues: | 692 | * Issues: |
| 693 | * No rmap support so we cannot find the original mapper. In theory could walk | 693 | * - Error on hugepage is contained in hugepage unit (not in raw page unit.) |
| 694 | * all MMs and look for the mappings, but that would be non atomic and racy. | 694 | * To narrow down kill region to one page, we need to break up pmd. |
| 695 | * Need rmap for hugepages for this. Alternatively we could employ a heuristic, | 695 | * - To support soft-offlining for hugepage, we need to support hugepage |
| 696 | * like just walking the current process and hoping it has it mapped (that | 696 | * migration. |
| 697 | * should be usually true for the common "shared database cache" case) | ||
| 698 | * Should handle free huge pages and dequeue them too, but this needs to | ||
| 699 | * handle huge page accounting correctly. | ||
| 700 | */ | 697 | */ |
| 701 | static int me_huge_page(struct page *p, unsigned long pfn) | 698 | static int me_huge_page(struct page *p, unsigned long pfn) |
| 702 | { | 699 | { |
| 703 | return FAILED; | 700 | struct page *hpage = compound_head(p); |
| 701 | /* | ||
| 702 | * We can safely recover from error on free or reserved (i.e. | ||
| 703 | * not in-use) hugepage by dequeuing it from freelist. | ||
| 704 | * To check whether a hugepage is in-use or not, we can't use | ||
| 705 | * page->lru because it can be used in other hugepage operations, | ||
| 706 | * such as __unmap_hugepage_range() and gather_surplus_pages(). | ||
| 707 | * So instead we use page_mapping() and PageAnon(). | ||
| 708 | * We assume that this function is called with page lock held, | ||
| 709 | * so there is no race between isolation and mapping/unmapping. | ||
| 710 | */ | ||
| 711 | if (!(page_mapping(hpage) || PageAnon(hpage))) { | ||
| 712 | __isolate_hwpoisoned_huge_page(hpage); | ||
| 713 | return RECOVERED; | ||
| 714 | } | ||
| 715 | return DELAYED; | ||
| 704 | } | 716 | } |
| 705 | 717 | ||
| 706 | /* | 718 | /* |
