On Thu, Jul 16, 2020 at 01:58:19PM -0700, David Rientjes wrote: > @@ -1350,6 +1350,32 @@ static bool mem_cgroup_wait_acct_move(struct mem_cgroup *memcg) > return false; > } > > +/* > + * Returns the amount of anon memory that is charged to the memcg that is > + * reclaimable under memory pressure without swap, in pages. > + */ > +static unsigned long memcg_anon_reclaimable(struct mem_cgroup *memcg) > +{ > + long deferred, lazyfree; > + > + /* > + * Deferred pages are charged anonymous pages that are on the LRU but > + * are unmapped. These compound pages are split under memory pressure. > + */ > + deferred = max_t(long, memcg_page_state(memcg, NR_ACTIVE_ANON) + > + memcg_page_state(memcg, NR_INACTIVE_ANON) - > + memcg_page_state(memcg, NR_ANON_MAPPED), 0); > + /* > + * Lazyfree pages are charged clean anonymous pages that are on the file > + * LRU and can be reclaimed under memory pressure. > + */ > + lazyfree = max_t(long, memcg_page_state(memcg, NR_ACTIVE_FILE) + > + memcg_page_state(memcg, NR_INACTIVE_FILE) - > + memcg_page_state(memcg, NR_FILE_PAGES), 0); Unfortunately, we don't know if these have been reused after the madvise until we actually do the rmap walk in page reclaim. All of these could have dirty ptes and require swapout after all. The MADV_FREE tradeoff was that the freed pages can get reused by userspace without another context switch and tlb flush in the common case, by exploiting the fact that the MMU sets the dirty bit for us. The downside is that the kernel doesn't know what state these pages are in until it takes a close-up look at them one by one.