Skip to content

Commit c3114a8

Browse files
Anshuman Khandualtorvalds
authored andcommitted
mm: hugetlb: soft-offline: dissolve source hugepage after successful migration
Currently hugepage migrated by soft-offline (i.e. due to correctable memory errors) is contained as a hugepage, which means many non-error pages in it are unreusable, i.e. wasted. This patch solves this issue by dissolving source hugepages into buddy. As done in previous patch, PageHWPoison is set only on a head page of the error hugepage. Then in dissoliving we move the PageHWPoison flag to the raw error page so that all healthy subpages return back to buddy. [[email protected]: fix warnings: replace some macros with inline functions] Link: http://lkml.kernel.org/r/[email protected] Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Anshuman Khandual <[email protected]> Signed-off-by: Naoya Horiguchi <[email protected]> Signed-off-by: Arnd Bergmann <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent b37ff71 commit c3114a8

File tree

4 files changed

+39
-9
lines changed

4 files changed

+39
-9
lines changed

include/linux/hugetlb.h

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,7 @@ static inline pgoff_t basepage_index(struct page *page)
472472
return __basepage_index(page);
473473
}
474474

475+
extern int dissolve_free_huge_page(struct page *page);
475476
extern int dissolve_free_huge_pages(unsigned long start_pfn,
476477
unsigned long end_pfn);
477478
static inline bool hugepage_migration_supported(struct hstate *h)
@@ -550,15 +551,37 @@ static inline unsigned int pages_per_huge_page(struct hstate *h)
550551
{
551552
return 1;
552553
}
553-
#define hstate_index_to_shift(index) 0
554-
#define hstate_index(h) 0
554+
555+
static inline unsigned hstate_index_to_shift(unsigned index)
556+
{
557+
return 0;
558+
}
559+
560+
static inline int hstate_index(struct hstate *h)
561+
{
562+
return 0;
563+
}
555564

556565
static inline pgoff_t basepage_index(struct page *page)
557566
{
558567
return page->index;
559568
}
560-
#define dissolve_free_huge_pages(s, e) 0
561-
#define hugepage_migration_supported(h) false
569+
570+
static inline int dissolve_free_huge_page(struct page *page)
571+
{
572+
return 0;
573+
}
574+
575+
static inline int dissolve_free_huge_pages(unsigned long start_pfn,
576+
unsigned long end_pfn)
577+
{
578+
return 0;
579+
}
580+
581+
static inline bool hugepage_migration_supported(struct hstate *h)
582+
{
583+
return false;
584+
}
562585

563586
static inline spinlock_t *huge_pte_lockptr(struct hstate *h,
564587
struct mm_struct *mm, pte_t *pte)

mm/hugetlb.c

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1459,7 +1459,7 @@ static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed,
14591459
* number of free hugepages would be reduced below the number of reserved
14601460
* hugepages.
14611461
*/
1462-
static int dissolve_free_huge_page(struct page *page)
1462+
int dissolve_free_huge_page(struct page *page)
14631463
{
14641464
int rc = 0;
14651465

@@ -1472,6 +1472,14 @@ static int dissolve_free_huge_page(struct page *page)
14721472
rc = -EBUSY;
14731473
goto out;
14741474
}
1475+
/*
1476+
* Move PageHWPoison flag from head page to the raw error page,
1477+
* which makes any subpages rather than the error page reusable.
1478+
*/
1479+
if (PageHWPoison(head) && page != head) {
1480+
SetPageHWPoison(page);
1481+
ClearPageHWPoison(head);
1482+
}
14751483
list_del(&head->lru);
14761484
h->free_huge_pages--;
14771485
h->free_huge_pages_node[nid]--;

mm/memory-failure.c

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1575,11 +1575,8 @@ static int soft_offline_huge_page(struct page *page, int flags)
15751575
if (ret > 0)
15761576
ret = -EIO;
15771577
} else {
1578-
/* overcommit hugetlb page will be freed to buddy */
1579-
SetPageHWPoison(page);
15801578
if (PageHuge(page))
1581-
dequeue_hwpoisoned_huge_page(hpage);
1582-
num_poisoned_pages_inc();
1579+
dissolve_free_huge_page(page);
15831580
}
15841581
return ret;
15851582
}

mm/migrate.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1252,6 +1252,8 @@ static int unmap_and_move_huge_page(new_page_t get_new_page,
12521252
out:
12531253
if (rc != -EAGAIN)
12541254
putback_active_hugepage(hpage);
1255+
if (reason == MR_MEMORY_FAILURE && !test_set_page_hwpoison(hpage))
1256+
num_poisoned_pages_inc();
12551257

12561258
/*
12571259
* If migration was not successful and there's a freeing callback, use

0 commit comments

Comments
 (0)