From: Jinjiang Tu <tujinjiang@huawei.com>
To: <linux-mm@kvack.org>, <akpm@linux-foundation.org>,
<wangkefeng.wang@huawei.com>, <sunnanyong@huawei.com>,
<liushixin2@huawei.com>
Cc: <tujinjiang@huawei.com>
Subject: [PATCH 1/6] mm/page_owner: support identifying pages allocated by modules
Date: Tue, 15 Aug 2023 20:52:46 +0800 [thread overview]
Message-ID: <20230815125251.2865852-2-tujinjiang@huawei.com> (raw)
In-Reply-To: <20230815125251.2865852-1-tujinjiang@huawei.com>
Identify if the pages are allocated by modules according to stackstrace.
By traversing the stacktrace and querying if the address of each entry is
located in a module, we gets the module who allocated/freed the page. If
several modules are found in stacktrace, we choose the one that is closet
to the allocation/free function. We record the module name in struct
page_owner and print it when a user reads from page_owner interface.
Signed-off-by: Jinjiang Tu <tujinjiang@huawei.com>
---
mm/page_owner.c | 86 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 86 insertions(+)
diff --git a/mm/page_owner.c b/mm/page_owner.c
index c93baef0148f..ef8fe1857d42 100644
--- a/mm/page_owner.c
+++ b/mm/page_owner.c
@@ -12,6 +12,7 @@
#include <linux/seq_file.h>
#include <linux/memcontrol.h>
#include <linux/sched/clock.h>
+#include <linux/module.h>
#include "internal.h"
@@ -32,6 +33,9 @@ struct page_owner {
char comm[TASK_COMM_LEN];
pid_t pid;
pid_t tgid;
+#ifdef CONFIG_MODULES
+ char module_name[MODULE_NAME_LEN];
+#endif
};
static bool page_owner_enabled __initdata;
@@ -134,6 +138,78 @@ static noinline depot_stack_handle_t save_stack(gfp_t flags)
return handle;
}
+#ifdef CONFIG_MODULES
+static char *find_module_name(depot_stack_handle_t handle)
+{
+ int i;
+ struct module *mod = NULL;
+ unsigned long *entries;
+ unsigned int nr_entries;
+
+ nr_entries = stack_depot_fetch(handle, &entries);
+ for (i = 0; i < nr_entries; i++) {
+ if (core_kernel_text(entries[i]))
+ continue;
+
+ preempt_disable();
+ mod = __module_address(entries[i]);
+ preempt_enable();
+
+ if (!mod)
+ continue;
+
+ return mod->name;
+ }
+
+ return NULL;
+}
+
+static void set_module_name(struct page_owner *page_owner, char *mod_name)
+{
+ if (mod_name)
+ strscpy(page_owner->module_name, mod_name, MODULE_NAME_LEN);
+ else
+ memset(page_owner->module_name, 0, MODULE_NAME_LEN);
+}
+
+static int module_name_snprint(struct page_owner *page_owner,
+ char *kbuf, size_t size)
+{
+ if (strlen(page_owner->module_name) != 0)
+ return scnprintf(kbuf, size, "Page allocated by module %s\n",
+ page_owner->module_name);
+
+ return 0;
+}
+
+static inline void copy_module_name(struct page_owner *old_page_owner,
+ struct page_owner *new_page_owner)
+{
+ set_module_name(new_page_owner, old_page_owner->module_name);
+}
+#else
+static inline char *find_module_name(depot_stack_handle_t handle)
+{
+ return NULL;
+}
+
+static inline void set_module_name(struct page_owner *page_owner,
+ char *mod_name)
+{
+}
+
+static inline int module_name_snprint(struct page_owner *page_owner,
+ char *kbuf, size_t size)
+{
+ return 0;
+}
+
+static inline void copy_module_name(struct page_owner *old_page_owner,
+ struct page_owner *new_page_owner)
+{
+}
+#endif
+
void __reset_page_owner(struct page *page, unsigned short order)
{
int i;
@@ -141,17 +217,20 @@ void __reset_page_owner(struct page *page, unsigned short order)
depot_stack_handle_t handle;
struct page_owner *page_owner;
u64 free_ts_nsec = local_clock();
+ char *mod_name;
page_ext = page_ext_get(page);
if (unlikely(!page_ext))
return;
handle = save_stack(GFP_NOWAIT | __GFP_NOWARN);
+ mod_name = find_module_name(handle);
for (i = 0; i < (1 << order); i++) {
__clear_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags);
page_owner = get_page_owner(page_ext);
page_owner->free_handle = handle;
page_owner->free_ts_nsec = free_ts_nsec;
+ set_module_name(page_owner, mod_name);
page_ext = page_ext_next(page_ext);
}
page_ext_put(page_ext);
@@ -164,6 +243,9 @@ static inline void __set_page_owner_handle(struct page_ext *page_ext,
struct page_owner *page_owner;
int i;
u64 ts_nsec = local_clock();
+ char *mod_name;
+
+ mod_name = find_module_name(handle);
for (i = 0; i < (1 << order); i++) {
page_owner = get_page_owner(page_ext);
@@ -176,6 +258,7 @@ static inline void __set_page_owner_handle(struct page_ext *page_ext,
page_owner->ts_nsec = ts_nsec;
strscpy(page_owner->comm, current->comm,
sizeof(page_owner->comm));
+ set_module_name(page_owner, mod_name);
__set_bit(PAGE_EXT_OWNER, &page_ext->flags);
__set_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags);
@@ -256,6 +339,7 @@ void __folio_copy_owner(struct folio *newfolio, struct folio *old)
new_page_owner->ts_nsec = old_page_owner->ts_nsec;
new_page_owner->free_ts_nsec = old_page_owner->ts_nsec;
strcpy(new_page_owner->comm, old_page_owner->comm);
+ copy_module_name(new_page_owner, old_page_owner);
/*
* We don't clear the bit on the old folio as it's going to be freed
@@ -425,6 +509,8 @@ print_page_owner(char __user *buf, size_t count, unsigned long pfn,
migratetype_names[pageblock_mt],
&page->flags);
+ ret += module_name_snprint(page_owner, kbuf + ret, count - ret);
+
ret += stack_depot_snprint(handle, kbuf + ret, count - ret, 0);
if (ret >= count)
goto err;
--
2.25.1
next prev parent reply other threads:[~2023-08-15 11:58 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-08-15 12:52 [PATCH 0/6] page_owner: support filtering by module Jinjiang Tu
2023-08-15 12:52 ` Jinjiang Tu [this message]
2023-08-15 12:52 ` [PATCH 2/6] mm/page_owner: show modules allocating pages when oom occurred Jinjiang Tu
2023-08-15 14:24 ` kernel test robot
2023-08-15 15:48 ` kernel test robot
2023-08-15 12:52 ` [PATCH 3/6] tools/vm/page_owner_sort: support for selecting by module name Jinjiang Tu
2023-08-15 12:52 ` [PATCH 4/6] tools/vm/page_owner_sort: support for culling " Jinjiang Tu
2023-08-15 12:52 ` [PATCH 5/6] tools/vm/page_owner_sort: support sorting " Jinjiang Tu
2023-08-15 12:52 ` [PATCH 6/6] Documentation: update document for page_owner Jinjiang Tu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20230815125251.2865852-2-tujinjiang@huawei.com \
--to=tujinjiang@huawei.com \
--cc=akpm@linux-foundation.org \
--cc=linux-mm@kvack.org \
--cc=liushixin2@huawei.com \
--cc=sunnanyong@huawei.com \
--cc=wangkefeng.wang@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox