Minchan Kim <minchan.kim@xxxxxxxxx> writes: > On Sun, Oct 03, 2010 at 11:58:00PM -0700, Greg Thelen wrote: >> Add memcg routines to track dirty, writeback, and unstable_NFS pages. >> These routines are not yet used by the kernel to count such pages. >> A later change adds kernel calls to these new routines. >> >> Signed-off-by: Greg Thelen <gthelen@xxxxxxxxxx> >> Signed-off-by: Andrea Righi <arighi@xxxxxxxxxxx> >> --- >> include/linux/memcontrol.h | 3 + >> mm/memcontrol.c | 89 ++++++++++++++++++++++++++++++++++++++++---- >> 2 files changed, 84 insertions(+), 8 deletions(-) >> >> diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h >> index 7c7bec4..6303da1 100644 >> --- a/include/linux/memcontrol.h >> +++ b/include/linux/memcontrol.h >> @@ -28,6 +28,9 @@ struct mm_struct; >> /* Stats that can be updated by kernel. */ >> enum mem_cgroup_write_page_stat_item { >> MEMCG_NR_FILE_MAPPED, /* # of pages charged as file rss */ >> + MEMCG_NR_FILE_DIRTY, /* # of dirty pages in page cache */ >> + MEMCG_NR_FILE_WRITEBACK, /* # of pages under writeback */ >> + MEMCG_NR_FILE_UNSTABLE_NFS, /* # of NFS unstable pages */ >> }; >> >> extern unsigned long mem_cgroup_isolate_pages(unsigned long nr_to_scan, >> diff --git a/mm/memcontrol.c b/mm/memcontrol.c >> index 267d774..f40839f 100644 >> --- a/mm/memcontrol.c >> +++ b/mm/memcontrol.c >> @@ -85,10 +85,13 @@ enum mem_cgroup_stat_index { >> */ >> MEM_CGROUP_STAT_CACHE, /* # of pages charged as cache */ >> MEM_CGROUP_STAT_RSS, /* # of pages charged as anon rss */ >> - MEM_CGROUP_STAT_FILE_MAPPED, /* # of pages charged as file rss */ >> MEM_CGROUP_STAT_PGPGIN_COUNT, /* # of pages paged in */ >> MEM_CGROUP_STAT_PGPGOUT_COUNT, /* # of pages paged out */ >> MEM_CGROUP_STAT_SWAPOUT, /* # of pages, swapped out */ >> + MEM_CGROUP_STAT_FILE_MAPPED, /* # of pages charged as file rss */ >> + MEM_CGROUP_STAT_FILE_DIRTY, /* # of dirty pages in page cache */ >> + MEM_CGROUP_STAT_FILE_WRITEBACK, /* # of pages under writeback */ >> + MEM_CGROUP_STAT_FILE_UNSTABLE_NFS, /* # of NFS unstable pages */ >> MEM_CGROUP_STAT_DATA, /* end of data requires synchronization */ >> /* incremented at every pagein/pageout */ >> MEM_CGROUP_EVENTS = MEM_CGROUP_STAT_DATA, >> @@ -1626,6 +1629,48 @@ void mem_cgroup_update_page_stat(struct page *page, >> ClearPageCgroupFileMapped(pc); >> idx = MEM_CGROUP_STAT_FILE_MAPPED; >> break; >> + >> + case MEMCG_NR_FILE_DIRTY: >> + /* Use Test{Set,Clear} to only un/charge the memcg once. */ >> + if (val > 0) { >> + if (TestSetPageCgroupFileDirty(pc)) >> + /* already set */ > > Nitpick. > The comment doesn't give any useful information. > It looks like redundant. I agree. I removed the four redundant comments you referred to. Thanks for the feedback. >> + val = 0; >> + } else { >> + if (!TestClearPageCgroupFileDirty(pc)) >> + /* already cleared */ > > Ditto > >> + val = 0; >> + } >> + idx = MEM_CGROUP_STAT_FILE_DIRTY; >> + break; >> + >> + case MEMCG_NR_FILE_WRITEBACK: >> + /* >> + * This counter is adjusted while holding the mapping's >> + * tree_lock. Therefore there is no race between settings and >> + * clearing of this flag. >> + */ >> + if (val > 0) >> + SetPageCgroupFileWriteback(pc); >> + else >> + ClearPageCgroupFileWriteback(pc); >> + idx = MEM_CGROUP_STAT_FILE_WRITEBACK; >> + break; >> + >> + case MEMCG_NR_FILE_UNSTABLE_NFS: >> + /* Use Test{Set,Clear} to only un/charge the memcg once. */ >> + if (val > 0) { >> + if (TestSetPageCgroupFileUnstableNFS(pc)) >> + /* already set */ > > Ditto > >> + val = 0; >> + } else { >> + if (!TestClearPageCgroupFileUnstableNFS(pc)) >> + /* already cleared */ > > Ditto > >> + val = 0; >> + } >> + idx = MEM_CGROUP_STAT_FILE_UNSTABLE_NFS; >> + break; >> + >> default: >> BUG(); >> } >> @@ -2133,6 +2178,16 @@ static void __mem_cgroup_commit_charge(struct mem_cgroup *mem, >> memcg_check_events(mem, pc->page); >> } >> >> +static void mem_cgroup_move_account_page_stat(struct mem_cgroup *from, >> + struct mem_cgroup *to, >> + enum mem_cgroup_stat_index idx) >> +{ >> + preempt_disable(); >> + __this_cpu_dec(from->stat->count[idx]); >> + __this_cpu_inc(to->stat->count[idx]); >> + preempt_enable(); >> +} >> + >> /** >> * __mem_cgroup_move_account - move account of the page >> * @pc: page_cgroup of the page. >> @@ -2159,13 +2214,18 @@ static void __mem_cgroup_move_account(struct page_cgroup *pc, >> VM_BUG_ON(!PageCgroupUsed(pc)); >> VM_BUG_ON(pc->mem_cgroup != from); >> >> - if (PageCgroupFileMapped(pc)) { >> - /* Update mapped_file data for mem_cgroup */ >> - preempt_disable(); >> - __this_cpu_dec(from->stat->count[MEM_CGROUP_STAT_FILE_MAPPED]); >> - __this_cpu_inc(to->stat->count[MEM_CGROUP_STAT_FILE_MAPPED]); >> - preempt_enable(); >> - } >> + if (PageCgroupFileMapped(pc)) >> + mem_cgroup_move_account_page_stat(from, to, >> + MEM_CGROUP_STAT_FILE_MAPPED); >> + if (PageCgroupFileDirty(pc)) >> + mem_cgroup_move_account_page_stat(from, to, >> + MEM_CGROUP_STAT_FILE_DIRTY); >> + if (PageCgroupFileWriteback(pc)) >> + mem_cgroup_move_account_page_stat(from, to, >> + MEM_CGROUP_STAT_FILE_WRITEBACK); >> + if (PageCgroupFileUnstableNFS(pc)) >> + mem_cgroup_move_account_page_stat(from, to, >> + MEM_CGROUP_STAT_FILE_UNSTABLE_NFS); >> mem_cgroup_charge_statistics(from, pc, false); >> if (uncharge) >> /* This is not "cancel", but cancel_charge does all we need. */ >> @@ -3545,6 +3605,9 @@ enum { >> MCS_PGPGIN, >> MCS_PGPGOUT, >> MCS_SWAP, >> + MCS_FILE_DIRTY, >> + MCS_WRITEBACK, >> + MCS_UNSTABLE_NFS, >> MCS_INACTIVE_ANON, >> MCS_ACTIVE_ANON, >> MCS_INACTIVE_FILE, >> @@ -3567,6 +3630,9 @@ struct { >> {"pgpgin", "total_pgpgin"}, >> {"pgpgout", "total_pgpgout"}, >> {"swap", "total_swap"}, >> + {"dirty", "total_dirty"}, >> + {"writeback", "total_writeback"}, >> + {"nfs", "total_nfs"}, >> {"inactive_anon", "total_inactive_anon"}, >> {"active_anon", "total_active_anon"}, >> {"inactive_file", "total_inactive_file"}, >> @@ -3596,6 +3662,13 @@ mem_cgroup_get_local_stat(struct mem_cgroup *mem, struct mcs_total_stat *s) >> s->stat[MCS_SWAP] += val * PAGE_SIZE; >> } >> >> + val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_FILE_DIRTY); >> + s->stat[MCS_FILE_DIRTY] += val * PAGE_SIZE; >> + val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_FILE_WRITEBACK); >> + s->stat[MCS_WRITEBACK] += val * PAGE_SIZE; >> + val = mem_cgroup_read_stat(mem, MEM_CGROUP_STAT_FILE_UNSTABLE_NFS); >> + s->stat[MCS_UNSTABLE_NFS] += val * PAGE_SIZE; >> + >> /* per zone stat */ >> val = mem_cgroup_get_local_zonestat(mem, LRU_INACTIVE_ANON); >> s->stat[MCS_INACTIVE_ANON] += val * PAGE_SIZE; >> -- >> 1.7.1 >> >> -- >> To unsubscribe, send a message with 'unsubscribe linux-mm' in >> the body to majordomo@xxxxxxxxxx For more info on Linux MM, >> see: http://www.linux-mm.org/ . >> Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a> >> -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxxx For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>