[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220208000532.1054311-4-longman@redhat.com>
Date: Mon, 7 Feb 2022 19:05:31 -0500
From: Waiman Long <longman@...hat.com>
To: Johannes Weiner <hannes@...xchg.org>,
Michal Hocko <mhocko@...nel.org>,
Vladimir Davydov <vdavydov.dev@...il.com>,
Andrew Morton <akpm@...ux-foundation.org>,
Petr Mladek <pmladek@...e.com>,
Steven Rostedt <rostedt@...dmis.org>,
Sergey Senozhatsky <senozhatsky@...omium.org>,
Andy Shevchenko <andriy.shevchenko@...ux.intel.com>,
Rasmus Villemoes <linux@...musvillemoes.dk>
Cc: linux-kernel@...r.kernel.org, cgroups@...r.kernel.org,
linux-mm@...ck.org, Ira Weiny <ira.weiny@...el.com>,
Mike Rapoport <rppt@...nel.org>,
David Rientjes <rientjes@...gle.com>,
Roman Gushchin <guro@...com>,
Rafael Aquini <aquini@...hat.com>,
Waiman Long <longman@...hat.com>,
Mike Rapoport <rppt@...ux.ibm.com>
Subject: [PATCH v5 3/4] mm/page_owner: Print memcg information
It was found that a number of dying memcgs were not freed because
they were pinned by some charged pages that were present. Even "echo 1 >
/proc/sys/vm/drop_caches" wasn't able to free those pages. These dying
but not freed memcgs tend to increase in number over time with the side
effect that percpu memory consumption as shown in /proc/meminfo also
increases over time.
In order to find out more information about those pages that pin
dying memcgs, the page_owner feature is extended to print memory
cgroup information especially whether the cgroup is dying or not.
RCU read lock is taken when memcg is being accessed to make sure
that it won't be freed.
Signed-off-by: Waiman Long <longman@...hat.com>
Acked-by: David Rientjes <rientjes@...gle.com>
Acked-by: Roman Gushchin <guro@...com>
Acked-by: Mike Rapoport <rppt@...ux.ibm.com>
---
mm/page_owner.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/mm/page_owner.c b/mm/page_owner.c
index 28dac73e0542..d4c311455753 100644
--- a/mm/page_owner.c
+++ b/mm/page_owner.c
@@ -10,6 +10,7 @@
#include <linux/migrate.h>
#include <linux/stackdepot.h>
#include <linux/seq_file.h>
+#include <linux/memcontrol.h>
#include <linux/sched/clock.h>
#include "internal.h"
@@ -325,6 +326,47 @@ void pagetypeinfo_showmixedcount_print(struct seq_file *m,
seq_putc(m, '\n');
}
+/*
+ * Looking for memcg information and print it out
+ */
+static inline int print_page_owner_memcg(char *kbuf, size_t count, int ret,
+ struct page *page)
+{
+#ifdef CONFIG_MEMCG
+ unsigned long memcg_data;
+ struct mem_cgroup *memcg;
+ bool dying;
+
+ rcu_read_lock();
+ memcg_data = READ_ONCE(page->memcg_data);
+ if (!memcg_data)
+ goto out_unlock;
+
+ if (memcg_data & MEMCG_DATA_OBJCGS)
+ ret += scnprintf(kbuf + ret, count - ret,
+ "Slab cache page\n");
+
+ memcg = page_memcg_check(page);
+ if (!memcg)
+ goto out_unlock;
+
+ dying = (memcg->css.flags & CSS_DYING);
+ ret += scnprintf(kbuf + ret, count - ret,
+ "Charged %sto %smemcg ",
+ PageMemcgKmem(page) ? "(via objcg) " : "",
+ dying ? "dying " : "");
+
+ /* Write cgroup name directly into kbuf */
+ cgroup_name(memcg->css.cgroup, kbuf + ret, count - ret);
+ ret += strlen(kbuf + ret);
+ ret += scnprintf(kbuf + ret, count - ret, "\n");
+out_unlock:
+ rcu_read_unlock();
+#endif /* CONFIG_MEMCG */
+
+ return ret;
+}
+
static ssize_t
print_page_owner(char __user *buf, size_t count, unsigned long pfn,
struct page *page, struct page_owner *page_owner,
@@ -365,6 +407,8 @@ print_page_owner(char __user *buf, size_t count, unsigned long pfn,
migrate_reason_names[page_owner->last_migrate_reason]);
}
+ ret = print_page_owner_memcg(kbuf, count, ret, page);
+
ret += snprintf(kbuf + ret, count - ret, "\n");
if (ret >= count)
goto err;
--
2.27.0
Powered by blists - more mailing lists