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

Reply via email to