When subpool max_hpages accounting is not enabled, used_hpages is always 0
and might lead to release subpool prematurely because it indicates no pages
are used now while there might be.

In order to fix this issue, we should check used_hpages == 0 iff max_hpages
accounting is enabled. As max_hpages accounting should be enabled in most
common case, this is not worth a Cc stable.

Signed-off-by: Hongxiang Lou <[email protected]>
Signed-off-by: Miaohe Lin <[email protected]>
---
 mm/hugetlb.c | 16 +++++++++++++---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 777bc0e45bf3..53ea65d1c5ab 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -97,16 +97,26 @@ static inline void ClearPageHugeFreed(struct page *head)
 /* Forward declaration */
 static int hugetlb_acct_memory(struct hstate *h, long delta);
 
-static inline void unlock_or_release_subpool(struct hugepage_subpool *spool)
+static inline bool subpool_is_free(struct hugepage_subpool *spool)
 {
-       bool free = (spool->count == 0) && (spool->used_hpages == 0);
+       if (spool->count)
+               return false;
+       if (spool->max_hpages != -1)
+               return spool->used_hpages == 0;
+       if (spool->min_hpages != -1)
+               return spool->rsv_hpages == spool->min_hpages;
 
+       return true;
+}
+
+static inline void unlock_or_release_subpool(struct hugepage_subpool *spool)
+{
        spin_unlock(&spool->lock);
 
        /* If no pages are used, and no other handles to the subpool
         * remain, give up any reservations based on minimum size and
         * free the subpool */
-       if (free) {
+       if (subpool_is_free(spool)) {
                if (spool->min_hpages != -1)
                        hugetlb_acct_memory(spool->hstate,
                                                -spool->min_hpages);
-- 
2.19.1

Reply via email to