aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mm/hugetlb.c37
1 files changed, 28 insertions, 9 deletions
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 23aec01836aa..b6adedbafaf5 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -1773,23 +1773,32 @@ free:
1773} 1773}
1774 1774
1775/* 1775/*
1776 * When releasing a hugetlb pool reservation, any surplus pages that were 1776 * This routine has two main purposes:
1777 * allocated to satisfy the reservation must be explicitly freed if they were 1777 * 1) Decrement the reservation count (resv_huge_pages) by the value passed
1778 * never used. 1778 * in unused_resv_pages. This corresponds to the prior adjustments made
1779 * Called with hugetlb_lock held. 1779 * to the associated reservation map.
1780 * 2) Free any unused surplus pages that may have been allocated to satisfy
1781 * the reservation. As many as unused_resv_pages may be freed.
1782 *
1783 * Called with hugetlb_lock held. However, the lock could be dropped (and
1784 * reacquired) during calls to cond_resched_lock. Whenever dropping the lock,
1785 * we must make sure nobody else can claim pages we are in the process of
1786 * freeing. Do this by ensuring resv_huge_page always is greater than the
1787 * number of huge pages we plan to free when dropping the lock.
1780 */ 1788 */
1781static void return_unused_surplus_pages(struct hstate *h, 1789static void return_unused_surplus_pages(struct hstate *h,
1782 unsigned long unused_resv_pages) 1790 unsigned long unused_resv_pages)
1783{ 1791{
1784 unsigned long nr_pages; 1792 unsigned long nr_pages;
1785 1793
1786 /* Uncommit the reservation */
1787 h->resv_huge_pages -= unused_resv_pages;
1788
1789 /* Cannot return gigantic pages currently */ 1794 /* Cannot return gigantic pages currently */
1790 if (hstate_is_gigantic(h)) 1795 if (hstate_is_gigantic(h))
1791 return; 1796 goto out;
1792 1797
1798 /*
1799 * Part (or even all) of the reservation could have been backed
1800 * by pre-allocated pages. Only free surplus pages.
1801 */
1793 nr_pages = min(unused_resv_pages, h->surplus_huge_pages); 1802 nr_pages = min(unused_resv_pages, h->surplus_huge_pages);
1794 1803
1795 /* 1804 /*
@@ -1799,12 +1808,22 @@ static void return_unused_surplus_pages(struct hstate *h,
1799 * when the nodes with surplus pages have no free pages. 1808 * when the nodes with surplus pages have no free pages.
1800 * free_pool_huge_page() will balance the the freed pages across the 1809 * free_pool_huge_page() will balance the the freed pages across the
1801 * on-line nodes with memory and will handle the hstate accounting. 1810 * on-line nodes with memory and will handle the hstate accounting.
1811 *
1812 * Note that we decrement resv_huge_pages as we free the pages. If
1813 * we drop the lock, resv_huge_pages will still be sufficiently large
1814 * to cover subsequent pages we may free.
1802 */ 1815 */
1803 while (nr_pages--) { 1816 while (nr_pages--) {
1817 h->resv_huge_pages--;
1818 unused_resv_pages--;
1804 if (!free_pool_huge_page(h, &node_states[N_MEMORY], 1)) 1819 if (!free_pool_huge_page(h, &node_states[N_MEMORY], 1))
1805 break; 1820 goto out;
1806 cond_resched_lock(&hugetlb_lock); 1821 cond_resched_lock(&hugetlb_lock);
1807 } 1822 }
1823
1824out:
1825 /* Fully uncommit the reservation */
1826 h->resv_huge_pages -= unused_resv_pages;
1808} 1827}
1809 1828
1810 1829