Skip to content

Commit

Permalink
mm/page_owner: print memcg information
Browse files Browse the repository at this point in the history
It was found that a number of offline 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
offline 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 offline
memcgs, the page_owner feature is extended to print memory cgroup
information especially whether the cgroup is offline or not.  RCU read
lock is taken when memcg is being accessed to make sure that it won't be
freed.

Link: https://lkml.kernel.org/r/[email protected]
Signed-off-by: Waiman Long <[email protected]>
Acked-by: David Rientjes <[email protected]>
Acked-by: Roman Gushchin <[email protected]>
Acked-by: Rafael Aquini <[email protected]>
Acked-by: Mike Rapoport <[email protected]>
Cc: Roman Gushchin <[email protected]>
Cc: Andy Shevchenko <[email protected]>
Cc: Ira Weiny <[email protected]>
Cc: Johannes Weiner <[email protected]>
Cc: Michal Hocko <[email protected]>
Cc: Petr Mladek <[email protected]>
Cc: Rasmus Villemoes <[email protected]>
Cc: Sergey Senozhatsky <[email protected]>
Cc: Steven Rostedt (Google) <[email protected]>
Cc: Vladimir Davydov <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Waiman-Long authored and torvalds committed Mar 25, 2022
1 parent 3ebc439 commit fcf8935
Showing 1 changed file with 42 additions and 0 deletions.
42 changes: 42 additions & 0 deletions mm/page_owner.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -325,6 +326,45 @@ 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 online;
char name[80];

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;

online = (memcg->css.flags & CSS_ONLINE);
cgroup_name(memcg->css.cgroup, name, sizeof(name));
ret += scnprintf(kbuf + ret, count - ret,
"Charged %sto %smemcg %s\n",
PageMemcgKmem(page) ? "(via objcg) " : "",
online ? "" : "offline ",
name);
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,
Expand Down Expand Up @@ -365,6 +405,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;
Expand Down

0 comments on commit fcf8935

Please sign in to comment.