From: "zhen.ni" <zhen.ni@easystack.cn>
To: Andrew Morton <akpm@linux-foundation.org>
Cc: vbabka@kernel.org, surenb@google.com, mhocko@suse.com,
jackmanb@google.com, hannes@cmpxchg.org, ziy@nvidia.com,
linux-mm@kvack.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v8 0/4] mm/page_owner: add per-fd filter infrastructure for print_mode and NUMA filtering
Date: Fri, 22 May 2026 16:39:34 +0800 [thread overview]
Message-ID: <4cc3db44-66da-47f0-815a-4322d0d3df96@easystack.cn> (raw)
In-Reply-To: <20260521172057.84537783b60ff9cd0abadf76@linux-foundation.org>
在 2026/5/22 08:20, Andrew Morton 写道:
> On Wed, 20 May 2026 15:56:37 +0800 Zhen Ni <zhen.ni@easystack.cn> wrote:
>
>> This patch series introduces per-file-descriptor filtering capabilities to the
>> page_owner feature.
>
> Thanks. AI review appears to have found a bunch of new things to
> complain about. Can you please check?
>
> https://sashiko.dev/#/patchset/20260515091942.1535677-1-zhen.ni@easystack.cn
>
> I'm interested in learning how much of this is accurate, and how useful
> you're finding that review to be?
>
>
>
Thanks. This is a response to review feedback on patch 1/4
(mm/page_owner: add print_mode filter).
There's a race condition between
page_owner_write() and print_page_owner() when sharing the same
file descriptor. The sequential reads of state->print_mode can
indeed lead to inconsistent behavior if a concurrent write
changes the mode between the two checks.
Proposed solution: Add spinlock for proper protection
I'll add a spinlock to page_owner_filter_state to properly serialize
concurrent access:
struct page_owner_filter_state {
enum page_owner_print_mode print_mode;
nodemask_t nid_filter;
bool nid_filter_enabled;
spinlock_t lock; /* Protect concurrent access */
};
Write operation - atomic update:
static ssize_t page_owner_write(struct file *file,
const char __user *buf,
size_t count, loff_t *ppos)
{
struct page_owner_filter_state *state = file->private_data;
unsigned long flags;
// Parse input (without lock)
// ...
// Atomic commit
spin_lock_irqsave(&state->lock, flags);
state->print_mode = new_print_mode;
state->nid_filter = new_nid_filter;
state->nid_filter_enabled = new_nid_filter_enabled;
spin_unlock_irqrestore(&state->lock, flags);
return count;
}
Read operation - consistent snapshot:
print_page_owner(...) {
struct page_owner_filter_state *state = file->private_data;
enum page_owner_print_mode print_mode;
nodemask_t nid_filter;
bool nid_enabled;
unsigned long flags;
// Get consistent snapshot (cached once)
spin_lock_irqsave(&state->lock, flags);
print_mode = state->print_mode;
nid_filter = state->nid_filter;
nid_enabled = state->nid_filter_enabled;
spin_unlock_irqrestore(&state->lock, flags);
// Use snapshot for all checks
if (print_mode != PAGE_OWNER_PRINT_HANDLE) {
// Print stack
}
if (print_mode != PAGE_OWNER_PRINT_STACK) {
// Print handle
}
}
Why READ_ONCE/WRITE_ONCE is not sufficient:
While READ_ONCE/WRITE_ONCE can prevent data tears on individual
fields, they cannot guarantee atomic updates across multiple
fields.
I'll prepare a follow-up patch to add the spinlock protection.
-------------------------------------------------------------
This is a response to review feedback on patch 2/4
(mm/page_owner: add NUMA node filter).
Issue 1: page_to_nid() may trigger page poison check
Why page poison check can be triggered:
The root cause is the lockless page iteration. As noted in the comment
at line 741-746:
/*
* Some pages could be missed by concurrent allocation or free,
* because we don't hold the zone lock.
*/
Without holding the zone lock, there's a race window where a page may be
in an inconsistent state during concurrent allocation or free.
When page_to_nid(page) is called:
#define page_to_nid(page) memdesc_nid(PF_POISONED_CHECK(page)->flags)
PF_POISONED_CHECK checks if page->flags is in an inconsistent state
during this race window. If detected, it triggers VM_BUG_ON_PGFLAGS(),
causing a kernel crash.
Current problematic code (mm/page_owner.c:772-777):
if (state->nid_filter_enabled) {
int page_nid = page_to_nid(page); // May trigger VM_BUG_ON_PGFLAGS
if (!node_isset(page_nid, state->nid_filter))
goto ext_put_continue;
}
Fix: Use memdesc_nid(page->flags) to extract nid directly from flags,
bypassing PF_POISONED_CHECK:
if (state->nid_filter_enabled) {
int page_nid = memdesc_nid(page->flags); // Direct access, no check
if (!node_isset(page_nid, state->nid_filter))
goto ext_put_continue;
}
Why the suggested pfn_to_nid() doesn't work:
I checked the implementation in include/linux/mmzone.h:2377-2381:
#ifdef CONFIG_NUMA
#define pfn_to_nid(pfn) \
({ \
unsigned long __pfn_to_nid_pfn = (pfn); \
page_to_nid(pfn_to_page(__pfn_to_nid_pfn)); \
})
#endif
On NUMA systems, pfn_to_nid() internally calls page_to_nid(), which
still triggers PF_POISONED_CHECK. Therefore it doesn't solve the problem.
Issue 2: Concurrent access protection
This issue is already addressed in patch 1/4.
-------------------------------------------------------------
This is a response to review feedback on patch 3/4
Issue 1: isdigit() with potentially negative signed char Accepted.
I'll fix this by casting to unsigned char:
if (!isdigit((unsigned char)*p)) {
fprintf(stderr, "Error: Invalid character '%c' in nid_list\n",
*p);
return -1;
}
This ensures the value is in the valid range for ctype functions and
avoids undefined behavior with non-ASCII input.
Issue 2: NID validation allows values > 65535
No change planned. The kernel already validates NID values. If an
invalid NID is sent, the kernel will reject it with EINVAL.
Issue 3: Manual -h handling interferes with getopt
No change planned. This is intentional. The manual -h check at line
155-162 allows the usage message to be displayed even on older kernels
without page_owner support or per-fd filtering. This helps users
understand the tool's functionality without needing to consult separate
documentation, even when running on kernels that don't support these
features. The edge case of -o -h is extremely rare in practice (user
wanting to write to a file named "-h"), and the benefit of
always-showable help documentation outweighs this theoretical issue.
Issue 4: Error message doesn't distinguish permissions from kernel support
No change planned. Harmless.
Issue 5: Performance of fflush() and fprintf() in read loop
I'll change to use fwrite() instead of fprintf() and move the flush to
after the loop:
Current code:
while ((ret = read(fd, buf, sizeof(buf) - 1)) > 0) {
buf[ret] = '\0';
fprintf(output, "%s", buf);
fflush(output);
}
Changed to:
while ((ret = read(fd, buf, sizeof(buf))) > 0) {
fwrite(buf, 1, ret, output);
}
fflush(output);
This avoids the redundant strlen() scan from fprintf() and frequent
flush calls, while still ensuring all data is written before the program
continues.
Best regards,
Zhen Ni
next prev parent reply other threads:[~2026-05-22 8:55 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-20 7:56 Zhen Ni
2026-05-20 7:56 ` [PATCH v8 1/4] mm/page_owner: add print_mode filter Zhen Ni
2026-05-20 7:56 ` [PATCH v8 2/4] mm/page_owner: add NUMA node filter Zhen Ni
2026-05-20 7:56 ` [PATCH v8 3/4] tools/mm: add page_owner_filter userspace tool Zhen Ni
2026-05-20 7:56 ` [PATCH v8 4/4] mm/page_owner: document page_owner filter Zhen Ni
2026-05-22 0:20 ` [PATCH v8 0/4] mm/page_owner: add per-fd filter infrastructure for print_mode and NUMA filtering Andrew Morton
2026-05-22 8:39 ` zhen.ni [this message]
2026-05-23 3:04 ` 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=4cc3db44-66da-47f0-815a-4322d0d3df96@easystack.cn \
--to=zhen.ni@easystack.cn \
--cc=akpm@linux-foundation.org \
--cc=hannes@cmpxchg.org \
--cc=jackmanb@google.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=mhocko@suse.com \
--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
Powered by JetHome