From: Zhen Ni <zhen.ni@easystack.cn>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: David Hildenbrand <david@kernel.org>,
Lorenzo Stoakes <ljs@kernel.org>,
"Liam R . Howlett" <liam@infradead.org>,
Vlastimil Babka <vbabka@kernel.org>,
Mike Rapoport <rppt@kernel.org>,
Suren Baghdasaryan <surenb@google.com>,
Michal Hocko <mhocko@suse.com>, Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
Randy Dunlap <rdunlap@infradead.org>,
Brendan Jackman <brendan.jackman@linux.dev>,
Johannes Weiner <hannes@cmpxchg.org>, Zi Yan <ziy@nvidia.com>,
linux-mm@kvack.org, linux-doc@vger.kernel.org,
linux-kernel@vger.kernel.org, Zhen Ni <zhen.ni@easystack.cn>
Subject: [PATCH 1/8] mm/page_owner: Add PID filtering support
Date: Fri, 28 Aug 2026 11:13:32 +0800 [thread overview]
Message-ID: <20260828031339.1270699-2-zhen.ni@easystack.cn> (raw)
In-Reply-To: <20260828031339.1270699-1-zhen.ni@easystack.cn>
Add PID filtering support. Users can filter page_owner output by process
IDs using the "pid=<pid_list>" command format. The filter supports up to
16 PIDs specified as a comma-separated list. PIDs are stored in sorted
order for efficient binary search matching during page owner iteration.
Signed-off-by: Zhen Ni <zhen.ni@easystack.cn>
---
mm/page_owner.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 83 insertions(+), 2 deletions(-)
diff --git a/mm/page_owner.c b/mm/page_owner.c
index fbbda7ba914b..33b9e12a019b 100644
--- a/mm/page_owner.c
+++ b/mm/page_owner.c
@@ -12,6 +12,8 @@
#include <linux/seq_file.h>
#include <linux/memcontrol.h>
#include <linux/sched/clock.h>
+#include <linux/bsearch.h>
+#include <linux/sort.h>
#include "page_alloc.h"
@@ -66,12 +68,24 @@ static const char * const page_owner_print_mode_strings[] = {
[PAGE_OWNER_PRINT_STACK_HANDLE] = "stack_handle",
};
+/* PID_MAX_LIMIT = 4,194,304 (7 decimal digits) */
+#define PID_MAX_DIGITS 7
+#define MAX_FILTER_PIDS 16
+
struct page_owner_filter_state {
enum page_owner_print_mode print_mode;
- nodemask_t nid_filter;
bool nid_filter_enabled;
+ bool proc_filter_enabled;
+ nodemask_t nid_filter;
+ int pid_count;
+ pid_t pid_list[MAX_FILTER_PIDS];
};
+static int cmp_pid_t(const void *a, const void *b)
+{
+ return *(pid_t *)a - *(pid_t *)b;
+}
+
static bool page_owner_enabled __initdata;
DEFINE_STATIC_KEY_FALSE(page_owner_inited);
@@ -820,6 +834,19 @@ read_page_owner(struct file *file, char __user *buf, size_t count, loff_t *ppos)
goto ext_put_continue;
}
+ if (state->proc_filter_enabled) {
+ bool proc_match = false;
+
+ proc_match = bsearch(&page_owner->pid,
+ state->pid_list,
+ state->pid_count,
+ sizeof(pid_t),
+ cmp_pid_t) != NULL;
+
+ if (!proc_match)
+ goto ext_put_continue;
+ }
+
/* Record the next PFN to read in the file offset */
*ppos = pfn + 1;
@@ -927,6 +954,7 @@ static int page_owner_open(struct inode *inode, struct file *file)
state->print_mode = PAGE_OWNER_PRINT_STACK;
nodes_clear(state->nid_filter);
state->nid_filter_enabled = false;
+ state->proc_filter_enabled = false;
file->private_data = state;
return 0;
}
@@ -937,6 +965,37 @@ static int page_owner_release(struct inode *inode, struct file *file)
return 0;
}
+static int parse_pid_t_list(const char *str, pid_t *list, int *count)
+{
+ char *str_copy, *token;
+ int i = 0;
+ unsigned int pid;
+ int ret = 0;
+
+ str_copy = kstrdup(str, GFP_KERNEL);
+ if (!str_copy)
+ return -ENOMEM;
+
+ while ((token = strsep(&str_copy, ",")) != NULL) {
+ if (*token == '\0')
+ continue;
+ if (i >= MAX_FILTER_PIDS) {
+ ret = -E2BIG;
+ goto out_free;
+ }
+ if (kstrtouint(token, 10, &pid) != 0) {
+ ret = -EINVAL;
+ goto out_free;
+ }
+ list[i++] = (pid_t)pid;
+ }
+
+ *count = i;
+out_free:
+ kfree(str_copy);
+ return ret;
+}
+
static ssize_t page_owner_write(struct file *file,
const char __user *buf,
size_t count, loff_t *ppos)
@@ -949,6 +1008,9 @@ static ssize_t page_owner_write(struct file *file,
enum page_owner_print_mode new_print_mode;
nodemask_t new_nid_filter;
bool new_nid_filter_enabled;
+ bool new_proc_filter_enabled;
+ pid_t new_pid_list[MAX_FILTER_PIDS];
+ int new_pid_count = 0;
/*
* Maximum input length for filter commands:
@@ -956,8 +1018,10 @@ static ssize_t page_owner_write(struct file *file,
* with sufficient buffer
* - 6 * MAX_NUMNODES: worst case for nid list
* Worst case per node: ",NNNNN" (comma + 5-digit node number) = 6 bytes
+ * - For list filters: (digit+comma) * count + prefix
*/
- if (count > 32 + 6 * MAX_NUMNODES)
+ if (count > 32 + 6 * MAX_NUMNODES +
+ (PID_MAX_DIGITS + 1) * MAX_FILTER_PIDS + 4)
return -EINVAL;
kbuf = memdup_user_nul(buf, count);
@@ -969,6 +1033,11 @@ static ssize_t page_owner_write(struct file *file,
new_print_mode = state->print_mode;
new_nid_filter = state->nid_filter;
new_nid_filter_enabled = state->nid_filter_enabled;
+ new_proc_filter_enabled = state->proc_filter_enabled;
+ if (state->pid_count > 0) {
+ memcpy(new_pid_list, state->pid_list, sizeof(state->pid_list));
+ new_pid_count = state->pid_count;
+ }
while ((token = strsep(&kbuf, " \t\n")) != NULL) {
if (*token == '\0')
@@ -1000,6 +1069,10 @@ static ssize_t page_owner_write(struct file *file,
}
new_nid_filter_enabled = true;
+ } else if (!strncmp(token, "pid=", 4)) {
+ ret = parse_pid_t_list(token + 4, new_pid_list, &new_pid_count);
+ if (ret < 0)
+ goto out_free;
} else {
ret = -EINVAL;
goto out_free;
@@ -1010,6 +1083,14 @@ static ssize_t page_owner_write(struct file *file,
state->print_mode = new_print_mode;
state->nid_filter = new_nid_filter;
state->nid_filter_enabled = new_nid_filter_enabled;
+ state->proc_filter_enabled = new_pid_count > 0;
+ if (new_pid_count > 0) {
+ memcpy(state->pid_list, new_pid_list, sizeof(state->pid_list));
+ state->pid_count = new_pid_count;
+ }
+ if (state->pid_count > 1)
+ sort(state->pid_list, state->pid_count, sizeof(pid_t),
+ cmp_pid_t, NULL);
ret = count;
--
2.20.1
next prev parent reply other threads:[~2026-08-28 3:14 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-28 3:13 [PATCH 0/8] mm/page_owner: Add PID/TGID/COMM and cgroup filtering Zhen Ni
2026-08-28 3:13 ` Zhen Ni [this message]
2026-08-28 3:13 ` [PATCH 2/8] mm/page_owner: Add TGID filtering support Zhen Ni
2026-08-28 3:13 ` [PATCH 3/8] mm/page_owner: Add COMM filtering with wildcard support Zhen Ni
2026-08-28 3:13 ` [PATCH 4/8] mm/page_owner: Refactor memcg handling for cgroup filter support Zhen Ni
2026-08-28 3:13 ` [PATCH 5/8] mm/page_owner: Add memcg " Zhen Ni
2026-08-28 3:13 ` [PATCH 6/8] tools/mm: Add PID/TGID/COMM filtering support to page_owner_filter Zhen Ni
2026-08-28 3:13 ` [PATCH 7/8] tools/mm: Add memory cgroup " Zhen Ni
2026-08-28 3:13 ` [PATCH 8/8] Documentation: page_owner: Document PID/TGID/COMM and cgroup filters Zhen Ni
2026-08-28 7:03 ` [PATCH 0/8] mm/page_owner: Add PID/TGID/COMM and cgroup filtering Lorenzo Stoakes (ARM)
2026-08-28 18:36 ` Andrew Morton
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260828031339.1270699-2-zhen.ni@easystack.cn \
--to=zhen.ni@easystack.cn \
--cc=akpm@linux-foundation.org \
--cc=brendan.jackman@linux.dev \
--cc=corbet@lwn.net \
--cc=david@kernel.org \
--cc=hannes@cmpxchg.org \
--cc=liam@infradead.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=mhocko@suse.com \
--cc=rdunlap@infradead.org \
--cc=rppt@kernel.org \
--cc=skhan@linuxfoundation.org \
--cc=surenb@google.com \
--cc=vbabka@kernel.org \
--cc=ziy@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox