Commit 9cc7e96a authored by Liam Mark's avatar Liam Mark Committed by Linus Torvalds

mm/page_owner: record timestamp and pid

Collect the time for each allocation recorded in page owner so that
allocation "surges" can be measured.

Record the pid for each allocation recorded in page owner so that the
source of allocation "surges" can be better identified.

The above is very useful when doing memory analysis.  On a crash for
example, we can get this information from kdump (or ramdump) and parse it
to figure out memory allocation problems.

Please note that on x86_64 this increases the size of struct page_owner
from 16 bytes to 32.

Vlastimil: it's not a functionality intended for production, so unless
somebody says they need to enable page_owner for debugging and this
increase prevents them from fitting into available memory, let's not
complicate things with making this optional.

[lmark@codeaurora.org: v3]
  Link: https://lkml.kernel.org/r/20201210160357.27779-1-georgi.djakov@linaro.org

Link: https://lkml.kernel.org/r/20201209125153.10533-1-georgi.djakov@linaro.orgSigned-off-by: default avatarLiam Mark <lmark@codeaurora.org>
Signed-off-by: default avatarGeorgi Djakov <georgi.djakov@linaro.org>
Acked-by: default avatarVlastimil Babka <vbabka@suse.cz>
Acked-by: default avatarJoonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 7fb7ab6d
...@@ -41,17 +41,17 @@ size change due to this facility. ...@@ -41,17 +41,17 @@ size change due to this facility.
- Without page owner:: - Without page owner::
text data bss dec hex filename text data bss dec hex filename
40662 1493 644 42799 a72f mm/page_alloc.o 48392 2333 644 51369 c8a9 mm/page_alloc.o
- With page owner:: - With page owner::
text data bss dec hex filename text data bss dec hex filename
40892 1493 644 43029 a815 mm/page_alloc.o 48800 2445 644 51889 cab1 mm/page_alloc.o
1427 24 8 1459 5b3 mm/page_ext.o 6574 108 29 6711 1a37 mm/page_owner.o
2722 50 0 2772 ad4 mm/page_owner.o 1025 8 8 1041 411 mm/page_ext.o
Although, roughly, 4 KB code is added in total, page_alloc.o increase by Although, roughly, 8 KB code is added in total, page_alloc.o increase by
230 bytes and only half of it is in hotpath. Building the kernel with 520 bytes and less than half of it is in hotpath. Building the kernel with
page owner and turning it on if needed would be great option to debug page owner and turning it on if needed would be great option to debug
kernel memory problem. kernel memory problem.
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
#include <linux/migrate.h> #include <linux/migrate.h>
#include <linux/stackdepot.h> #include <linux/stackdepot.h>
#include <linux/seq_file.h> #include <linux/seq_file.h>
#include <linux/sched/clock.h>
#include "internal.h" #include "internal.h"
...@@ -25,6 +26,8 @@ struct page_owner { ...@@ -25,6 +26,8 @@ struct page_owner {
gfp_t gfp_mask; gfp_t gfp_mask;
depot_stack_handle_t handle; depot_stack_handle_t handle;
depot_stack_handle_t free_handle; depot_stack_handle_t free_handle;
u64 ts_nsec;
pid_t pid;
}; };
static bool page_owner_enabled = false; static bool page_owner_enabled = false;
...@@ -172,6 +175,8 @@ static inline void __set_page_owner_handle(struct page *page, ...@@ -172,6 +175,8 @@ static inline void __set_page_owner_handle(struct page *page,
page_owner->order = order; page_owner->order = order;
page_owner->gfp_mask = gfp_mask; page_owner->gfp_mask = gfp_mask;
page_owner->last_migrate_reason = -1; page_owner->last_migrate_reason = -1;
page_owner->pid = current->pid;
page_owner->ts_nsec = local_clock();
__set_bit(PAGE_EXT_OWNER, &page_ext->flags); __set_bit(PAGE_EXT_OWNER, &page_ext->flags);
__set_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags); __set_bit(PAGE_EXT_OWNER_ALLOCATED, &page_ext->flags);
...@@ -236,6 +241,8 @@ void __copy_page_owner(struct page *oldpage, struct page *newpage) ...@@ -236,6 +241,8 @@ void __copy_page_owner(struct page *oldpage, struct page *newpage)
new_page_owner->last_migrate_reason = new_page_owner->last_migrate_reason =
old_page_owner->last_migrate_reason; old_page_owner->last_migrate_reason;
new_page_owner->handle = old_page_owner->handle; new_page_owner->handle = old_page_owner->handle;
new_page_owner->pid = old_page_owner->pid;
new_page_owner->ts_nsec = old_page_owner->ts_nsec;
/* /*
* We don't clear the bit on the oldpage as it's going to be freed * We don't clear the bit on the oldpage as it's going to be freed
...@@ -349,9 +356,10 @@ print_page_owner(char __user *buf, size_t count, unsigned long pfn, ...@@ -349,9 +356,10 @@ print_page_owner(char __user *buf, size_t count, unsigned long pfn,
return -ENOMEM; return -ENOMEM;
ret = snprintf(kbuf, count, ret = snprintf(kbuf, count,
"Page allocated via order %u, mask %#x(%pGg)\n", "Page allocated via order %u, mask %#x(%pGg), pid %d, ts %llu ns\n",
page_owner->order, page_owner->gfp_mask, page_owner->order, page_owner->gfp_mask,
&page_owner->gfp_mask); &page_owner->gfp_mask, page_owner->pid,
page_owner->ts_nsec);
if (ret >= count) if (ret >= count)
goto err; goto err;
...@@ -427,8 +435,9 @@ void __dump_page_owner(struct page *page) ...@@ -427,8 +435,9 @@ void __dump_page_owner(struct page *page)
else else
pr_alert("page_owner tracks the page as freed\n"); pr_alert("page_owner tracks the page as freed\n");
pr_alert("page last allocated via order %u, migratetype %s, gfp_mask %#x(%pGg)\n", pr_alert("page last allocated via order %u, migratetype %s, gfp_mask %#x(%pGg), pid %d, ts %llu\n",
page_owner->order, migratetype_names[mt], gfp_mask, &gfp_mask); page_owner->order, migratetype_names[mt], gfp_mask, &gfp_mask,
page_owner->pid, page_owner->ts_nsec);
handle = READ_ONCE(page_owner->handle); handle = READ_ONCE(page_owner->handle);
if (!handle) { if (!handle) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment