1
0
Fork 0
mirror of synced 2025-03-06 20:59:54 +01:00

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.com
Signed-off-by: Kassey Li <quic_yingangl@quicinc.com>
Suggested-by: Vlastimil Babka <vbabka@suse.cz>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Cc: Joonsoo Kim <iamjoonsoo.kim@lge.com>
Cc: Minchan Kim <minchan@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Kassey Li 2022-08-18 10:24:25 +08:00 committed by Andrew Morton
parent 72c33ef4c0
commit 8f0efa81df
2 changed files with 26 additions and 3 deletions

View file

@ -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

View file

@ -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)
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 @@ ext_put_continue:
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)
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)