]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - mm/hugetlb.c
mm: hugetlb: soft-offline: dissolve_free_huge_page() return zero on !PageHuge
[linux.git] / mm / hugetlb.c
index ac843d32b0193924bd90dc96afc5aae6d35b4102..ede7e7f5d1ab2fec113507b5dabe78a7cdad8256 100644 (file)
@@ -1510,16 +1510,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
- * 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 rc = -EBUSY;
 
+       /* Not to disrupt normal path by vainly holding hugetlb_lock */
+       if (!PageHuge(page))
+               return 0;
+
        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 hstate *h = page_hstate(head);
                int nid = page_to_nid(head);
@@ -1564,11 +1577,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) {
                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;