diff options
Diffstat (limited to 'mm/hugetlb.c')
-rw-r--r-- | mm/hugetlb.c | 29 |
1 files changed, 20 insertions, 9 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c index ac843d32b019..ede7e7f5d1ab 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c | |||
@@ -1510,16 +1510,29 @@ static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed, | |||
1510 | 1510 | ||
1511 | /* | 1511 | /* |
1512 | * Dissolve a given free hugepage into free buddy pages. This function does | 1512 | * Dissolve a given free hugepage into free buddy pages. This function does |
1513 | * nothing for in-use (including surplus) hugepages. Returns -EBUSY if the | 1513 | * nothing for in-use hugepages and non-hugepages. |
1514 | * dissolution fails because a give page is not a free hugepage, or because | 1514 | * This function returns values like below: |
1515 | * free hugepages are fully reserved. | 1515 | * |
1516 | * -EBUSY: failed to dissolved free hugepages or the hugepage is in-use | ||
1517 | * (allocated or reserved.) | ||
1518 | * 0: successfully dissolved free hugepages or the page is not a | ||
1519 | * hugepage (considered as already dissolved) | ||
1516 | */ | 1520 | */ |
1517 | int dissolve_free_huge_page(struct page *page) | 1521 | int dissolve_free_huge_page(struct page *page) |
1518 | { | 1522 | { |
1519 | int rc = -EBUSY; | 1523 | int rc = -EBUSY; |
1520 | 1524 | ||
1525 | /* Not to disrupt normal path by vainly holding hugetlb_lock */ | ||
1526 | if (!PageHuge(page)) | ||
1527 | return 0; | ||
1528 | |||
1521 | spin_lock(&hugetlb_lock); | 1529 | spin_lock(&hugetlb_lock); |
1522 | if (PageHuge(page) && !page_count(page)) { | 1530 | if (!PageHuge(page)) { |
1531 | rc = 0; | ||
1532 | goto out; | ||
1533 | } | ||
1534 | |||
1535 | if (!page_count(page)) { | ||
1523 | struct page *head = compound_head(page); | 1536 | struct page *head = compound_head(page); |
1524 | struct hstate *h = page_hstate(head); | 1537 | struct hstate *h = page_hstate(head); |
1525 | int nid = page_to_nid(head); | 1538 | int nid = page_to_nid(head); |
@@ -1564,11 +1577,9 @@ int dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn) | |||
1564 | 1577 | ||
1565 | for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << minimum_order) { | 1578 | for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << minimum_order) { |
1566 | page = pfn_to_page(pfn); | 1579 | page = pfn_to_page(pfn); |
1567 | if (PageHuge(page) && !page_count(page)) { | 1580 | rc = dissolve_free_huge_page(page); |
1568 | rc = dissolve_free_huge_page(page); | 1581 | if (rc) |
1569 | if (rc) | 1582 | break; |
1570 | break; | ||
1571 | } | ||
1572 | } | 1583 | } |
1573 | 1584 | ||
1574 | return rc; | 1585 | return rc; |