On Wed, Jan 05, 2022 at 08:34:40PM -0300, Mauricio Faria de Oliveira wrote: > diff --git a/mm/rmap.c b/mm/rmap.c > index 163ac4e6bcee..8671de473c25 100644 > --- a/mm/rmap.c > +++ b/mm/rmap.c > @@ -1570,7 +1570,20 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma, > > /* MADV_FREE page check */ > if (!PageSwapBacked(page)) { > - if (!PageDirty(page)) { > + int ref_count = page_ref_count(page); > + int map_count = page_mapcount(page); > + > + /* > + * The only page refs must be from the isolation > + * (checked by the caller shrink_page_list() too) > + * and one or more rmap's (dropped by discard:). > + * > + * Check the reference count before dirty flag > + * with memory barrier; see __remove_mapping(). > + */ > + smp_rmb(); > + if ((ref_count - 1 == map_count) && > + !PageDirty(page)) { > /* Invalidate as we cleared the pte */ > mmu_notifier_invalidate_range(mm, > address, address + PAGE_SIZE); Out of curiosity, how does it work with COW in terms of reordering? Specifically, it seems to me get_page() and page_dup_rmap() in copy_present_pte() can happen in any order, and if page_dup_rmap() is seen first, and direct io is holding a refcnt, this check can still pass?