2022-08-16 07:24:58

by Kassey Li

[permalink] [raw]
Subject: [PATCH v8] mm/page_owner.c: add llseek for page_owner

There is usage to dump a given cma region page_owner
instead of all page's.

This change allows to specify a ppos as start_pfn
by fseek.

Any invalid ppos will be skipped, so it did not
broken the origin dump feature.

Suggested-by: Vlastimil Babka <[email protected]>
Signed-off-by: Kassey Li <[email protected]>
---
Documentation/mm/page_owner.rst | 5 +++++
mm/page_owner.c | 24 +++++++++++++++++++++---
2 files changed, 26 insertions(+), 3 deletions(-)

diff --git a/Documentation/mm/page_owner.rst b/Documentation/mm/page_owner.rst
index f5c954afe97c..f18fd8907049 100644
--- a/Documentation/mm/page_owner.rst
+++ b/Documentation/mm/page_owner.rst
@@ -94,6 +94,11 @@ Usage
Page allocated via order XXX, ...
PFN XXX ...
// 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
in buf, uses regexp to extract the page order value, counts the times
diff --git a/mm/page_owner.c b/mm/page_owner.c
index e4c6f3f1695b..25720d81bc26 100644
--- a/mm/page_owner.c
+++ b/mm/page_owner.c
@@ -497,8 +497,10 @@ read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos)
return -EINVAL;

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 */
while (!pfn_valid(pfn) && (pfn & (MAX_ORDER_NR_PAGES - 1)) != 0)
pfn++;
@@ -561,7 +563,7 @@ read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos)
continue;

/* Record the next PFN to read in the file offset */
- *ppos = (pfn - min_low_pfn) + 1;
+ *ppos = pfn + 1;

return print_page_owner(buf, count, pfn, page,
page_owner, handle);
@@ -570,6 +572,21 @@ read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos)
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)
{
unsigned long pfn = zone->zone_start_pfn;
@@ -660,6 +677,7 @@ static void init_early_allocated_pages(void)

static const struct file_operations proc_page_owner_operations = {
.read = read_page_owner,
+ .llseek = lseek_page_owner,
};

static int __init pageowner_init(void)
--
2.17.1


2022-08-17 16:29:11

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH v8] mm/page_owner.c: add llseek for page_owner

On Tue, 16 Aug 2022 10:07:48 +0800 Kassey Li <[email protected]> wrote:

> There is usage to dump a given cma region page_owner
> instead of all page's.

So... dump all the pages and then parse out the ones you're interested in?

Presumably this is too slow and presumably you have a use case in which
this operation needs speeding up? If so, please fully describe all of
this in the changelog. If not then please fully still describe the
reasons for making this change.

2022-08-18 05:10:26

by Kassey Li

[permalink] [raw]
Subject: Re: [PATCH v8] mm/page_owner.c: add llseek for page_owner



On 8/18/2022 12:13 AM, Andrew Morton wrote:
> On Tue, 16 Aug 2022 10:07:48 +0800 Kassey Li <[email protected]> wrote:
>
>> There is usage to dump a given cma region page_owner
>> instead of all page's.
>
> So... dump all the pages and then parse out the ones you're interested in?
>
> Presumably this is too slow and presumably you have a use case in which
> this operation needs speeding up? If so, please fully describe all of
> this in the changelog. If not then please fully still describe the
> reasons for making this change.
>
that is correct, I will update the change log for detail make it easy to
know why we need this change.