Commit 8f0efa81 authored by Kassey Li's avatar Kassey Li Committed by Andrew Morton

mm/page_owner.c: add llseek for page_owner

It is too slow to dump all the pages, in some usage we just want to dump a
given start pfn, for example: a CMA range or a single page.

To speed up and save time, this change allows specifying of a start pfn by
adding llseek for page_owner.

Link: https://lkml.kernel.org/r/20220818022425.31056-1-quic_yingangl@quicinc.comSigned-off-by: default avatarKassey Li <quic_yingangl@quicinc.com>
Suggested-by: default avatarVlastimil Babka <vbabka@suse.cz>
Acked-by: default avatarVlastimil Babka <vbabka@suse.cz>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Minchan Kim <minchan@kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 72c33ef4
...@@ -94,6 +94,11 @@ Usage ...@@ -94,6 +94,11 @@ Usage
Page allocated via order XXX, ... Page allocated via order XXX, ...
PFN XXX ... PFN XXX ...
// Detailed stack // Detailed stack
By default, it will do full pfn dump, to start with a given pfn,
page_owner supports fseek.
FILE *fp = fopen("/sys/kernel/debug/page_owner", "r");
fseek(fp, pfn_start, SEEK_SET);
The ``page_owner_sort`` tool ignores ``PFN`` rows, puts the remaining rows The ``page_owner_sort`` tool ignores ``PFN`` rows, puts the remaining rows
in buf, uses regexp to extract the page order value, counts the times in buf, uses regexp to extract the page order value, counts the times
......
...@@ -516,8 +516,10 @@ read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos) ...@@ -516,8 +516,10 @@ read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos)
return -EINVAL; return -EINVAL;
page = NULL; page = NULL;
pfn = min_low_pfn + *ppos; if (*ppos == 0)
pfn = min_low_pfn;
else
pfn = *ppos;
/* Find a valid PFN or the start of a MAX_ORDER_NR_PAGES area */ /* Find a valid PFN or the start of a MAX_ORDER_NR_PAGES area */
while (!pfn_valid(pfn) && (pfn & (MAX_ORDER_NR_PAGES - 1)) != 0) while (!pfn_valid(pfn) && (pfn & (MAX_ORDER_NR_PAGES - 1)) != 0)
pfn++; pfn++;
...@@ -588,7 +590,7 @@ read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos) ...@@ -588,7 +590,7 @@ read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos)
goto ext_put_continue; goto ext_put_continue;
/* Record the next PFN to read in the file offset */ /* Record the next PFN to read in the file offset */
*ppos = (pfn - min_low_pfn) + 1; *ppos = pfn + 1;
page_owner_tmp = *page_owner; page_owner_tmp = *page_owner;
page_ext_put(page_ext); page_ext_put(page_ext);
...@@ -601,6 +603,21 @@ read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos) ...@@ -601,6 +603,21 @@ read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos)
return 0; return 0;
} }
static loff_t lseek_page_owner(struct file *file, loff_t offset, int orig)
{
switch (orig) {
case SEEK_SET:
file->f_pos = offset;
break;
case SEEK_CUR:
file->f_pos += offset;
break;
default:
return -EINVAL;
}
return file->f_pos;
}
static void init_pages_in_zone(pg_data_t *pgdat, struct zone *zone) static void init_pages_in_zone(pg_data_t *pgdat, struct zone *zone)
{ {
unsigned long pfn = zone->zone_start_pfn; unsigned long pfn = zone->zone_start_pfn;
...@@ -693,6 +710,7 @@ static void init_early_allocated_pages(void) ...@@ -693,6 +710,7 @@ static void init_early_allocated_pages(void)
static const struct file_operations proc_page_owner_operations = { static const struct file_operations proc_page_owner_operations = {
.read = read_page_owner, .read = read_page_owner,
.llseek = lseek_page_owner,
}; };
static int __init pageowner_init(void) static int __init pageowner_init(void)
......
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