Skip to content

Commit 5a31741

Browse files
mjkravetztorvalds
authored andcommitted
hugetlb: do not demote poisoned hugetlb pages
It is possible for poisoned hugetlb pages to reside on the free lists. The huge page allocation routines which dequeue entries from the free lists make a point of avoiding poisoned pages. There is no such check and avoidance in the demote code path. If a hugetlb page on the is on a free list, poison will only be set in the head page rather then the page with the actual error. If such a page is demoted, then the poison flag may follow the wrong page. A page without error could have poison set, and a page with poison could not have the flag set. Check for poison before attempting to demote a hugetlb page. Also, return -EBUSY to the caller if only poisoned pages are on the free list. Link: https://lkml.kernel.org/r/[email protected] Fixes: 8531fc6 ("hugetlb: add hugetlb demote page support") Signed-off-by: Mike Kravetz <[email protected]> Reviewed-by: Naoya Horiguchi <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 31ca72f commit 5a31741

File tree

1 file changed

+10
-7
lines changed

1 file changed

+10
-7
lines changed

mm/hugetlb.c

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3475,7 +3475,6 @@ static int demote_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed)
34753475
{
34763476
int nr_nodes, node;
34773477
struct page *page;
3478-
int rc = 0;
34793478

34803479
lockdep_assert_held(&hugetlb_lock);
34813480

@@ -3486,15 +3485,19 @@ static int demote_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed)
34863485
}
34873486

34883487
for_each_node_mask_to_free(h, nr_nodes, node, nodes_allowed) {
3489-
if (!list_empty(&h->hugepage_freelists[node])) {
3490-
page = list_entry(h->hugepage_freelists[node].next,
3491-
struct page, lru);
3492-
rc = demote_free_huge_page(h, page);
3493-
break;
3488+
list_for_each_entry(page, &h->hugepage_freelists[node], lru) {
3489+
if (PageHWPoison(page))
3490+
continue;
3491+
3492+
return demote_free_huge_page(h, page);
34943493
}
34953494
}
34963495

3497-
return rc;
3496+
/*
3497+
* Only way to get here is if all pages on free lists are poisoned.
3498+
* Return -EBUSY so that caller will not retry.
3499+
*/
3500+
return -EBUSY;
34983501
}
34993502

35003503
#define HSTATE_ATTR_RO(_name) \

0 commit comments

Comments
 (0)