diff mbox series

[v8] mm/page_owner.c: add llseek for page_owner

Message ID 20220816020748.18040-1-quic_yingangl@quicinc.com (mailing list archive)
State New
Headers show
Series [v8] mm/page_owner.c: add llseek for page_owner | expand

Commit Message

Kassey Li quic Aug. 16, 2022, 2:07 a.m. UTC
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 <vbabka@suse.cz>
Signed-off-by: Kassey Li <quic_yingangl@quicinc.com>
---
 Documentation/mm/page_owner.rst |  5 +++++
 mm/page_owner.c                 | 24 +++++++++++++++++++++---
 2 files changed, 26 insertions(+), 3 deletions(-)

Comments

Andrew Morton Aug. 17, 2022, 4:13 p.m. UTC | #1
On Tue, 16 Aug 2022 10:07:48 +0800 Kassey Li <quic_yingangl@quicinc.com> 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.
Kassey Li quic Aug. 18, 2022, 2:25 a.m. UTC | #2
On 8/18/2022 12:13 AM, Andrew Morton wrote:
> On Tue, 16 Aug 2022 10:07:48 +0800 Kassey Li <quic_yingangl@quicinc.com> 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.
diff mbox series

Patch

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)