[Devel] [PATCH rh7 2/3] mm/workingset: fix workingset_activation() with memcgroups enabled
Andrey Ryabinin
aryabinin at virtuozzo.com
Fri May 17 16:08:01 MSK 2019
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 <aryabinin at 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
More information about the Devel
mailing list