|
@@ -1489,16 +1489,29 @@ static int free_pool_huge_page(struct hstate *h, nodemask_t *nodes_allowed,
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
|
* Dissolve a given free hugepage into free buddy pages. This function does
|
|
* Dissolve a given free hugepage into free buddy pages. This function does
|
|
|
- * nothing for in-use (including surplus) hugepages. Returns -EBUSY if the
|
|
|
|
|
- * dissolution fails because a give page is not a free hugepage, or because
|
|
|
|
|
- * free hugepages are fully reserved.
|
|
|
|
|
|
|
+ * nothing for in-use hugepages and non-hugepages.
|
|
|
|
|
+ * This function returns values like below:
|
|
|
|
|
+ *
|
|
|
|
|
+ * -EBUSY: failed to dissolved free hugepages or the hugepage is in-use
|
|
|
|
|
+ * (allocated or reserved.)
|
|
|
|
|
+ * 0: successfully dissolved free hugepages or the page is not a
|
|
|
|
|
+ * hugepage (considered as already dissolved)
|
|
|
*/
|
|
*/
|
|
|
int dissolve_free_huge_page(struct page *page)
|
|
int dissolve_free_huge_page(struct page *page)
|
|
|
{
|
|
{
|
|
|
int rc = -EBUSY;
|
|
int rc = -EBUSY;
|
|
|
|
|
|
|
|
|
|
+ /* Not to disrupt normal path by vainly holding hugetlb_lock */
|
|
|
|
|
+ if (!PageHuge(page))
|
|
|
|
|
+ return 0;
|
|
|
|
|
+
|
|
|
spin_lock(&hugetlb_lock);
|
|
spin_lock(&hugetlb_lock);
|
|
|
- if (PageHuge(page) && !page_count(page)) {
|
|
|
|
|
|
|
+ if (!PageHuge(page)) {
|
|
|
|
|
+ rc = 0;
|
|
|
|
|
+ goto out;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!page_count(page)) {
|
|
|
struct page *head = compound_head(page);
|
|
struct page *head = compound_head(page);
|
|
|
struct hstate *h = page_hstate(head);
|
|
struct hstate *h = page_hstate(head);
|
|
|
int nid = page_to_nid(head);
|
|
int nid = page_to_nid(head);
|
|
@@ -1543,11 +1556,9 @@ int dissolve_free_huge_pages(unsigned long start_pfn, unsigned long end_pfn)
|
|
|
|
|
|
|
|
for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << minimum_order) {
|
|
for (pfn = start_pfn; pfn < end_pfn; pfn += 1 << minimum_order) {
|
|
|
page = pfn_to_page(pfn);
|
|
page = pfn_to_page(pfn);
|
|
|
- if (PageHuge(page) && !page_count(page)) {
|
|
|
|
|
- rc = dissolve_free_huge_page(page);
|
|
|
|
|
- if (rc)
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ rc = dissolve_free_huge_page(page);
|
|
|
|
|
+ if (rc)
|
|
|
|
|
+ break;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return rc;
|
|
return rc;
|