On Mon, Nov 08, 2021 at 03:27:55PM -0800, Yang Shi wrote: > On Thu, Nov 4, 2021 at 10:52 PM Naoya Horiguchi > <naoya.horiguchi@xxxxxxxxx> wrote: ... > > @@ -1942,6 +1987,26 @@ core_initcall(memory_failure_init); > > pr_info(fmt, pfn); \ > > }) > > > > +static inline int clear_page_hwpoison(struct ratelimit_state *rs, struct page *p) > > +{ > > + if (TestClearPageHWPoison(p)) { > > + unpoison_pr_info("Unpoison: Software-unpoisoned page %#lx\n", > > + page_to_pfn(p), rs); > > + num_poisoned_pages_dec(); > > + return 1; > > + } > > + return 0; > > +} > > + > > +static inline int unpoison_taken_off_page(struct ratelimit_state *rs, > > + struct page *p) > > +{ > > + if (put_page_back_buddy(p) && clear_page_hwpoison(rs, p)) > > It seems there might be race condition between free and allocation to > kick the page out of buddy before the hwpoisoned flag is cleared IIUC? > > CPU A CPU B > Free: Allocation: > acquire zone lock > put back to buddy > release zone lock > acquire zone lock > try to allocate this page > if it is hwpoisoned then reset > PageBuddy (not buddy page anymore) > release zone lock > > Did I miss something? No, this is a nice catch. CPU B finds hwpoisoned page on free list then calling bad_page(). So doing "put back to buddy" and clear_page_hwpoison inside a single zone lock should prevent this race. Thanks, Naoya Horiguchi