workingset_activation() mistakenly does nothing when memory cgroups are enabled. Commit f6a8b015027e ("ms/mm: workingset: per-cgroup cache thrash detection") also changed mem_cgroup_begin_update_page_stat() to return memcg. But commit didn't make it right, memcg return only when memcg is moving and NULL otherwise. Instead of mocking with mem_cgroup_begin_update_page_stat() obtain memcg from page in workingset_activation() directly.
Fixes: f6a8b015027e ("ms/mm: workingset: per-cgroup cache thrash detection") Signed-off-by: Andrey Ryabinin <aryabi...@virtuozzo.com> --- include/linux/memcontrol.h | 10 +++++----- mm/memcontrol.c | 9 +++++---- mm/workingset.c | 17 ++++++++++------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/include/linux/memcontrol.h b/include/linux/memcontrol.h index 575584dc1651..aa8cef097055 100644 --- a/include/linux/memcontrol.h +++ b/include/linux/memcontrol.h @@ -181,21 +181,21 @@ static inline void mem_cgroup_put(struct mem_cgroup *memcg) css_put(mem_cgroup_css(memcg)); } -struct mem_cgroup *__mem_cgroup_begin_update_page_stat(struct page *page, bool *locked, +void __mem_cgroup_begin_update_page_stat(struct page *page, bool *locked, unsigned long *flags); extern atomic_t memcg_moving; -static inline struct mem_cgroup *mem_cgroup_begin_update_page_stat(struct page *page, +static inline void mem_cgroup_begin_update_page_stat(struct page *page, bool *locked, unsigned long *flags) { if (mem_cgroup_disabled()) - return NULL; + return; + rcu_read_lock(); *locked = false; if (atomic_read(&memcg_moving)) - return __mem_cgroup_begin_update_page_stat(page, locked, flags); - return NULL; + __mem_cgroup_begin_update_page_stat(page, locked, flags); } void __mem_cgroup_end_update_page_stat(struct page *page, diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 869ea97c7fff..301fedcbc312 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -2703,7 +2703,7 @@ bool mem_cgroup_oom_synchronize(bool handle) * account and taking the move_lock in the slowpath. */ -struct mem_cgroup *__mem_cgroup_begin_update_page_stat(struct page *page, +void __mem_cgroup_begin_update_page_stat(struct page *page, bool *locked, unsigned long *flags) { struct mem_cgroup *memcg; @@ -2713,7 +2713,8 @@ struct mem_cgroup *__mem_cgroup_begin_update_page_stat(struct page *page, again: memcg = pc->mem_cgroup; if (unlikely(!memcg || !PageCgroupUsed(pc))) - return NULL; + return; + /* * If this memory cgroup is not under account moving, we don't * need to take move_lock_mem_cgroup(). Because we already hold @@ -2721,7 +2722,7 @@ struct mem_cgroup *__mem_cgroup_begin_update_page_stat(struct page *page, * rcu_read_unlock() if mem_cgroup_stolen() == true. */ if (!mem_cgroup_stolen(memcg)) - return NULL; + return; move_lock_mem_cgroup(memcg, flags); if (memcg != pc->mem_cgroup || !PageCgroupUsed(pc)) { @@ -2729,7 +2730,7 @@ struct mem_cgroup *__mem_cgroup_begin_update_page_stat(struct page *page, goto again; } *locked = true; - return memcg; + return; } void __mem_cgroup_end_update_page_stat(struct page *page, unsigned long *flags) diff --git a/mm/workingset.c b/mm/workingset.c index 1d7bdbf7a5d6..1598d2b02314 100644 --- a/mm/workingset.c +++ b/mm/workingset.c @@ -315,11 +315,17 @@ bool workingset_refault(void *shadow) */ void workingset_activation(struct page *page) { - struct mem_cgroup *memcg; + struct mem_cgroup *memcg = NULL; + struct page_cgroup *pc; struct lruvec *lruvec; bool locked; unsigned long flags; + mem_cgroup_begin_update_page_stat(page, &locked, &flags); + pc = lookup_page_cgroup(page); + if (likely(PageCgroupUsed(pc))) + memcg = pc->mem_cgroup; + /* * Filter non-memcg pages here, e.g. unmap can call * mark_page_accessed() on VDSO pages. @@ -327,15 +333,12 @@ void workingset_activation(struct page *page) * XXX: See workingset_refault() - this should return * root_mem_cgroup even for !CONFIG_MEMCG. */ - if (!mem_cgroup_disabled()) - return; - - memcg = mem_cgroup_begin_update_page_stat(page, &locked, &flags); - if (!memcg) - return; + if (!mem_cgroup_disabled() && !memcg) + goto out; lruvec = mem_cgroup_zone_lruvec(page_zone(page), memcg); atomic_long_inc(&lruvec->inactive_age); +out: mem_cgroup_end_update_page_stat(page, &locked, &flags); } -- 2.21.0 _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel