On Thu 28-06-12 19:23:11, KAMEZAWA Hiroyuki wrote: > For handling many kinds of races, memcg adds an extra charge to > page's memcg at page migration. But this affects the page compaction > and make it fail if the memcg is under OOM. > > This patch uses res_counter_charge_nofail() in page migration path > and remove -ENOMEM. By this, page migration will not fail by the > status of memcg. Maybe we could add something like below to the changelog as well. " Even though res_counter_charge_nofail can silently go over the memcg limit mem_cgroup_usage compensates that and it doesn't tell the real truth to the userspace. Excessive charges are only temporal and done on a single page per-CPU in the worst case. This sounds tolerable and actually consumes less charges than the current per-cpu memcg_stock. " > Reported-by: David Rientjes <rientjes@xxxxxxxxxx> > Signed-off-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@xxxxxxxxxxxxxx> Acked-by: Michal Hocko <mhocko@xxxxxxx> Thanks! > --- > mm/memcontrol.c | 26 +++++++------------------- > 1 files changed, 7 insertions(+), 19 deletions(-) > > diff --git a/mm/memcontrol.c b/mm/memcontrol.c > index a2677e0..7424fab 100644 > --- a/mm/memcontrol.c > +++ b/mm/memcontrol.c > @@ -3168,6 +3168,7 @@ int mem_cgroup_prepare_migration(struct page *page, > struct page *newpage, struct mem_cgroup **memcgp, gfp_t gfp_mask) > { > struct mem_cgroup *memcg = NULL; > + struct res_counter *dummy; > struct page_cgroup *pc; > enum charge_type ctype; > int ret = 0; > @@ -3222,29 +3223,16 @@ int mem_cgroup_prepare_migration(struct page *page, > */ > if (!memcg) > return 0; > - > - *memcgp = memcg; > - ret = __mem_cgroup_try_charge(NULL, gfp_mask, 1, memcgp, false); > - css_put(&memcg->css);/* drop extra refcnt */ > - if (ret) { > - if (PageAnon(page)) { > - lock_page_cgroup(pc); > - ClearPageCgroupMigration(pc); > - unlock_page_cgroup(pc); > - /* > - * The old page may be fully unmapped while we kept it. > - */ > - mem_cgroup_uncharge_page(page); > - } > - /* we'll need to revisit this error code (we have -EINTR) */ > - return -ENOMEM; > - } > /* > * We charge new page before it's used/mapped. So, even if unlock_page() > * is called before end_migration, we can catch all events on this new > * page. In the case new page is migrated but not remapped, new page's > * mapcount will be finally 0 and we call uncharge in end_migration(). > */ > + res_counter_charge_nofail(&memcg->res, PAGE_SIZE, &dummy); > + if (do_swap_account) > + res_counter_charge_nofail(&memcg->memsw, PAGE_SIZE, &dummy); > + > if (PageAnon(page)) > ctype = MEM_CGROUP_CHARGE_TYPE_ANON; > else if (page_is_file_cache(page)) > @@ -3807,9 +3795,9 @@ static inline u64 mem_cgroup_usage(struct mem_cgroup *memcg, bool swap) > > if (!mem_cgroup_is_root(memcg)) { > if (!swap) > - return res_counter_read_u64(&memcg->res, RES_USAGE); > + return res_counter_usage_safe(&memcg->res); > else > - return res_counter_read_u64(&memcg->memsw, RES_USAGE); > + return res_counter_usage_safe(&memcg->memsw); > } > > val = mem_cgroup_recursive_stat(memcg, MEM_CGROUP_STAT_CACHE); > -- > 1.7.4.1 > > -- Michal Hocko SUSE Labs SUSE LINUX s.r.o. Lihovarska 1060/12 190 00 Praha 9 Czech Republic -- To unsubscribe, send a message with 'unsubscribe linux-mm' in the body to majordomo@xxxxxxxxx. For more info on Linux MM, see: http://www.linux-mm.org/ . Don't email: <a href=mailto:"dont@xxxxxxxxx"> email@xxxxxxxxx </a>