On Fri 26-02-21 10:45:14, Oscar Salvador wrote: > On Fri, Feb 26, 2021 at 09:35:09AM +0100, Michal Hocko wrote: > > I think it would be helpful to call out that specific case explicitly > > here. I can see only one scenario (are there more?) > > __free_huge_page() isolate_or_dissolve_huge_page > > PageHuge() == T > > alloc_and_dissolve_huge_page > > alloc_fresh_huge_page() > > spin_lock(hugetlb_lock) > > // PageHuge() && !PageHugeFreed && > > // !PageCount() > > spin_unlock(hugetlb_lock) > > spin_lock(hugetlb_lock) > > 1) update_and_free_page > > PageHuge() == F > > __free_pages() > > 2) enqueue_huge_page > > SetPageHugeFreed() > > spin_unlock(&hugetlb_lock) > > I do not think there are more scenarios. The thing is to find a !page_count && > !PageHugeFreed. > AFAICS, this can only happen after: > put_page->put_page_test_zero->..->_free_huge_page gets called but __free_huge_page > has not reached enqueue_huge_page yet (as you just described above) > > By calling out this case, you meant to describe it in the changelog? Yes. [...] > > struct hstate *h; > > > > /* > > * The page might have been dissloved from under our feet > > * so make sure to carefully check the state under the lock. > > * Return success on when racing as if we dissloved the page > > * ourselves. > > */ > > spin_lock(&hugetlb_lock); > > if (PageHuge(page)) { > > head = compound_head(page); > > h = page_hstate(head); > > } else { > > spin_unlock(&hugetlb_lock); > > return true; > > } > > spin_unlock(&hugetlb_lock); > > Yes, I find this less eyesore. > > I will fix it up in v4. Thanks! -- Michal Hocko SUSE Labs