On Thu, Feb 20, 2020 at 02:11:46PM +0900, js1304@xxxxxxxxx wrote: > @@ -1010,8 +1010,15 @@ static enum page_references page_check_references(struct page *page, > return PAGEREF_RECLAIM; > > if (referenced_ptes) { > - if (PageSwapBacked(page)) > - return PAGEREF_ACTIVATE; > + if (PageSwapBacked(page)) { > + if (referenced_page) { > + ClearPageReferenced(page); > + return PAGEREF_ACTIVATE; > + } This looks odd to me. referenced_page = TestClearPageReferenced() above, so it's already be clear. Why clear it again? > + > + SetPageReferenced(page); > + return PAGEREF_KEEP; > + } The existing file code already does: SetPageReferenced(page); if (referenced_page || referenced_ptes > 1) return PAGEREF_ACTIVATE; if (vm_flags & VM_EXEC) return PAGEREF_ACTIVATE; return PAGEREF_KEEP; The differences are: 1) referenced_ptes > 1. We did this so that heavily shared file mappings are protected a bit better than others. Arguably the same could apply for anon pages when we put them on the inactive list. 2) vm_flags & VM_EXEC. This mostly doesn't apply to anon pages. The exception would be jit code pages, but if we put anon pages on the inactive list we should protect jit code the same way we protect file executables. Seems to me you don't need to add anything. Just remove the PageSwapBacked branch and apply equal treatment to both types. > @@ -2056,6 +2063,15 @@ static void shrink_active_list(unsigned long nr_to_scan, > } > } > > + /* > + * Now, newly created anonymous page isn't appened to the > + * active list. We don't need to clear the reference bit here. > + */ > + if (PageSwapBacked(page)) { > + ClearPageReferenced(page); > + goto deactivate; > + } I don't understand this. If you don't clear the pte references, you're leaving behind stale data. You already decide here that we consider the page referenced when it reaches the end of the inactive list, regardless of what happens in between. That makes the deactivation kind of useless. And it blurs the lines between the inactive and active list. shrink_page_list() (and page_check_references()) are written with the notion that any references they look at are from the inactive list. If you carry over stale data, this can cause more subtle bugs later on. And again, I don't quite understand why anon would need different treatment here than file. > + > if (page_referenced(page, 0, sc->target_mem_cgroup, > &vm_flags)) { > nr_rotated += hpage_nr_pages(page); > @@ -2074,6 +2090,7 @@ static void shrink_active_list(unsigned long nr_to_scan, > } > } > > +deactivate: > ClearPageActive(page); /* we are de-activating */ > SetPageWorkingset(page); > list_add(&page->lru, &l_inactive); > -- > 2.7.4 >