On 1/26/21 3:55 AM, Miaohe Lin wrote: > 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. It might be good to say that you need min_hpages accounting (min_size mount option) enabled for this issue to occur. Or, perhaps say this is possible if a hugetlbfs filesystem is created with the min_size option and without the size option. That might better explain the conditions in which a user could see the issue. > 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. I agree that such a combination of mount options is very uncommon. > > Signed-off-by: Hongxiang Lou <louhongxiang@xxxxxxxxxx> > Signed-off-by: Miaohe Lin <linmiaohe@xxxxxxxxxx> > --- > mm/hugetlb.c | 16 +++++++++++++--- > 1 file changed, 13 insertions(+), 3 deletions(-) Thanks, Reviewed-by: Mike Kravetz <mike.kravetz@xxxxxxxxxx> -- Mike Kravetz > > 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); >