diff options
author | KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> | 2010-04-06 14:35:05 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-04-07 08:38:05 -0700 |
commit | 8725d5416213a145ccc9c236dbd26830ba409e00 (patch) | |
tree | aff10fc98874adfcb7755ec8bc1f2627036e8dc2 /include | |
parent | 116354d177ba2da37e91cf884e3d11e67f825efd (diff) | |
download | op-kernel-dev-8725d5416213a145ccc9c236dbd26830ba409e00.zip op-kernel-dev-8725d5416213a145ccc9c236dbd26830ba409e00.tar.gz |
memcg: fix race in file_mapped accounting
Presently, memcg's FILE_MAPPED accounting has following race with
move_account (happens at rmdir()).
increment page->mapcount (rmap.c)
mem_cgroup_update_file_mapped() move_account()
lock_page_cgroup()
check page_mapped() if
page_mapped(page)>1 {
FILE_MAPPED -1 from old memcg
FILE_MAPPED +1 to old memcg
}
.....
overwrite pc->mem_cgroup
unlock_page_cgroup()
lock_page_cgroup()
FILE_MAPPED + 1 to pc->mem_cgroup
unlock_page_cgroup()
Then,
old memcg (-1 file mapped)
new memcg (+2 file mapped)
This happens because move_account see page_mapped() which is not guarded
by lock_page_cgroup(). This patch adds FILE_MAPPED flag to page_cgroup
and move account information based on it. Now, all checks are synchronous
with lock_page_cgroup().
Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Reviewed-by: Balbir Singh <balbir@in.ibm.com>
Reviewed-by: Daisuke Nishimura <nishimura@mxp.nes.nec.co.jp>
Cc: Andrea Righi <arighi@develer.com>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/page_cgroup.h | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/include/linux/page_cgroup.h b/include/linux/page_cgroup.h index 30b0813..aef22ae 100644 --- a/include/linux/page_cgroup.h +++ b/include/linux/page_cgroup.h @@ -39,6 +39,7 @@ enum { PCG_CACHE, /* charged as cache */ PCG_USED, /* this object is in use. */ PCG_ACCT_LRU, /* page has been accounted for */ + PCG_FILE_MAPPED, /* page is accounted as "mapped" */ }; #define TESTPCGFLAG(uname, lname) \ @@ -73,6 +74,11 @@ CLEARPCGFLAG(AcctLRU, ACCT_LRU) TESTPCGFLAG(AcctLRU, ACCT_LRU) TESTCLEARPCGFLAG(AcctLRU, ACCT_LRU) + +SETPCGFLAG(FileMapped, FILE_MAPPED) +CLEARPCGFLAG(FileMapped, FILE_MAPPED) +TESTPCGFLAG(FileMapped, FILE_MAPPED) + static inline int page_cgroup_nid(struct page_cgroup *pc) { return page_to_nid(pc->page); |