On Wed 13-01-21 13:22:06, Muchun Song wrote: > There is a race condition between __free_huge_page() > and dissolve_free_huge_page(). > > CPU0: CPU1: > > // page_count(page) == 1 > put_page(page) > __free_huge_page(page) > dissolve_free_huge_page(page) > spin_lock(&hugetlb_lock) > // PageHuge(page) && !page_count(page) > update_and_free_page(page) > // page is freed to the buddy > spin_unlock(&hugetlb_lock) > spin_lock(&hugetlb_lock) > clear_page_huge_active(page) > enqueue_huge_page(page) > // It is wrong, the page is already freed > spin_unlock(&hugetlb_lock) > > The race windows is between put_page() and dissolve_free_huge_page(). > > We should make sure that the page is already on the free list > when it is dissolved. Please describe the effect of the bug. " As a result __free_huge_page would corrupt page(s) already in the buddy allocator. " > > Fixes: c8721bbbdd36 ("mm: memory-hotplug: enable memory hotplug to handle hugepage") > Signed-off-by: Muchun Song <songmuchun@xxxxxxxxxxxxx> > Reviewed-by: Mike Kravetz <mike.kravetz@xxxxxxxxxx> > Cc: stable@xxxxxxxxxxxxxxx [...] > @@ -1770,6 +1788,14 @@ int dissolve_free_huge_page(struct page *page) > int nid = page_to_nid(head); > if (h->free_huge_pages - h->resv_huge_pages == 0) > goto out; > + > + /* > + * We should make sure that the page is already on the free list > + * when it is dissolved. > + */ > + if (unlikely(!PageHugeFreed(head))) > + goto out; I believe we have agreed to retry for this temporary state. > + > /* > * Move PageHWPoison flag from head page to the raw error page, > * which makes any subpages rather than the error page reusable. > -- > 2.11.0 -- Michal Hocko SUSE Labs