aboutsummaryrefslogtreecommitdiffstats
path: root/mm/hugetlb.c
diff options
context:
space:
mode:
Diffstat (limited to 'mm/hugetlb.c')
-rw-r--r--mm/hugetlb.c29
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 */
1517int dissolve_free_huge_page(struct page *page) 1521int 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;