On Mon, Apr 05, 2021 at 04:00:39PM -0700, Mike Kravetz wrote: > +static void remove_hugetlb_page(struct hstate *h, struct page *page, > + bool adjust_surplus) > +{ > + int nid = page_to_nid(page); > + > + if (hstate_is_gigantic(h) && !gigantic_page_runtime_supported()) > + return; > + > + list_del(&page->lru); > + > + if (HPageFreed(page)) { > + h->free_huge_pages--; > + h->free_huge_pages_node[nid]--; > + ClearHPageFreed(page); > + } > + if (adjust_surplus) { > + h->surplus_huge_pages--; > + h->surplus_huge_pages_node[nid]--; > + } > + > + VM_BUG_ON_PAGE(hugetlb_cgroup_from_page(page), page); > + VM_BUG_ON_PAGE(hugetlb_cgroup_from_page_rsvd(page), page); These checks feel a bit odd here. I would move them above, before we start messing with the counters? > + > + ClearHPageTemporary(page); Why clearing it unconditionally? I guess we do not really care, but someone might wonder why when reading the core. So I would either do as we used to do and only clear it in case of HPageTemporary(), or drop a comment. > + set_page_refcounted(page); > + set_compound_page_dtor(page, NULL_COMPOUND_DTOR); > + > + h->nr_huge_pages--; > + h->nr_huge_pages_node[nid]--; > +} As Michal pointed out, remove_hugetlb_page() from alloc_and_dissolve_huge_page() might be problematic in some cases because the new_page has not been enqueued yet. Now, I guess this might be easily fixed with checking list_empty() before going ahead with list_del() call, or with another bool parameter 'delete', with a fat comment explaining why we can get to call remove_huge_page() on a page that is not in any list. Another solution that comes to my mind is to split remove_huge_page() functionality in 1) delete from list + unaccount free and surplus pages and 2) reset page's state + unaccount nr_huge_pages But that might be just biased as would fit for my usecase. So maybe a list_empty() or the bool parameter might just do. -- Oscar Salvador SUSE L3