From: "zhen.ni" <zhen.ni@easystack.cn>
To: Alexei Starovoitov <alexei.starovoitov@gmail.com>,
daniel@iogearbox.net, andrii@kernel.org, eddyz87@gmail.com,
memxor@gmail.com, martin.lau@linux.dev, song@kernel.org,
yonghong.song@linux.dev, jolsa@kernel.org, emil@etsalapatis.com,
ihor.solodrai@linux.dev, akpm@linux-foundation.org,
vbabka@kernel.org, surenb@google.com, mhocko@suse.com,
brendan.jackman@linux.dev, hannes@cmpxchg.org, ziy@nvidia.com,
shuah@kernel.org
Cc: bpf@vger.kernel.org, linux-mm@kvack.org,
linux-kselftest@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: Re: [PATCH v3 0/7] mm/page_owner: add bpf_iter and kfuncs
Date: Sun, 25 Oct 2026 10:16:54 +0800 [thread overview]
Message-ID: <7f9a9da5-1250-4be3-bfa2-70e4b6051197@easystack.cn> (raw)
In-Reply-To: <DMDAZW82I9LT.3FNX2WI80GNE2@gmail.com>
在 2026/10/25 03:08, Alexei Starovoitov 写道:
> On Sat, Oct 24, 2026 at 10:19 AM zhen.ni <zhen.ni@easystack.cn> wrote:
>> For this one node alone, about 97% of spanned is holes. With
>> bpf_for(pfn, start, end) plus a bpf_page_owner_read() per iteration,
>> that is at least 16,712,944 kfunc calls, and bpf_for has no scheduling
>> point inside, and all of them are wasted work. The gap grows with memory
>
> Right. spanned includes the holes. So don't pass them.
> /sys/devices/system/memory/ has memoryN only for present blocks.
> /sys/devices/system/node/nodeN/ links to the blocks of that node.
> /proc/iomem has "System RAM" ranges.
Thanks for taking the time to review this.
From /sys/devices/system/memory/ you get a discrete list of memory
blocks. The prog (or userspace) still has to walk those blocks, handle
boundaries, and track progress. That is traversal logic that an iterator
already absorbs into a single next() call. Pushing it out just moves the
complexity; it doesn't eliminate it.
Therefore, this only demonstrates feasibility, not superiority.
> 523024 pages in a 32G node looks like 64K pages.
> Then the whole 256G box is 4M pfns.
> When a hole is passed anyway the call ends at !online_section() in
> pfn_to_online_page(). /proc/kpageflags does that plus put_user()
> for every pfn, holes included.
True, the kernel safely returns an error for offline PFNs. But paying a
kfunc call just to learn that a PFN is ineligible is exactly the waste
the iterator eliminates — the kernel-side cursor skips holes and
ineligible pages before the prog ever sees them.
> Syscall progs run under migrate_disable() only.
Agreed, migrate_disable() pins the task to one CPU without disabling
preemption on PREEMPT_RT. But being preemptible doesn't mean the loop is
free — an 8M-iteration tight loop still consumes CPU, delays RCU grace
periods, and piles up softirq work. Skipping ineligible pages up front
reduces that pressure.
>
>> front. The spanned of this node is already 17.23M, so a single bpf_for
>> cannot cover it; you have to split it into N chunks and poll, with the
>> chunking state kept in a prog map, i.e. a loop nested in a loop.
>
> The loop over chunks is in user space. One bpf_prog_test_run_opts()
> per range with start and nr in ctx_in. No map, no nested loop.
>
The outer loop being in userspace doesn't remove the chunking burden —
it just relocates it. Userspace still has to parse sysfs, construct
ranges, issue one syscall per chunk, read the map, accumulate results
into a global aggregate, clear the map, and handle partial failures. And
in the snippet, i is an offset within the chunk while start and pfn are
64-bit — the chunking arithmetic itself is non-trivial. An iterator
absorbs all of this into next().
>> for 52-bit PA. A 32-bit PFN range will overflow here.
>
> The snippet was:
> bpf_for(i, 0, ctx->nr) {
> pfn = ctx->start + i;
> i is an offset within the chunk. start and pfn are 64-bit.
>
>> Solving all of this requires yet another, more complex kfunc—and it
>> looks increasingly like bpf iter. So why not just use the iter?
>
> Nothing of the above needs kernel code.
Feasibility isn't in question. The question is whether we want every
prog writer to reinvent this traversal plumbing, or let the kernel do
what iterators are designed for.
> v3 is +474 -83 lines on the kernel side. The diff I sent is +55 -1
> and it doesn't touch the debugfs path.
>
That diff includes my improvements to the page_owner infrastructure, so
the line count doesn't really establish that bpf_for is better than
iter. The iter approach only adds an exit on the debugfs path — thin
shells over the single page_owner_next_eligible() extracted from
read_page_owner(). It changes no logic on the debugfs path (aside from
the mem-hotplug locking fix, which addresses a pre-existing bug in the
debugfs interface).
And the fact that the bpf_for approach doesn't touch the debugfs path
is, if anything, a disadvantage: it means two sets of eligibility rules
would have to be maintained going forward.
With the iter approach, any future change only needs to be made in
page_owner_next_eligible().
Thanks,
Zhen
next prev parent reply other threads:[~2026-10-25 2:17 UTC|newest]
Thread overview: 23+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-21 11:24 [PATCH v3 0/7] mm/page_owner: add bpf_iter and kfuncs Zhen Ni
2026-10-21 11:24 ` [PATCH v3 1/7] mm/page_owner: extract page_owner_next_eligible() from read loop Zhen Ni
2026-10-21 11:51 ` bot+bpf-ci
2026-10-21 11:24 ` [PATCH v3 2/7] mm/page_owner: protect page access with mem-hotplug read lock Zhen Ni
2026-10-21 12:02 ` bot+bpf-ci
2026-10-21 11:24 ` [PATCH v3 3/7] mm/page_owner: add bpf_iter target "page_owner" Zhen Ni
2026-10-21 11:40 ` sashiko-bot
2026-10-21 11:24 ` [PATCH v3 4/7] mm/page_owner: add open-coded page_owner iterator Zhen Ni
2026-10-21 11:49 ` sashiko-bot
2026-10-21 11:24 ` [PATCH v3 5/7] mm/page_owner: record the NUMA node in the scan cursor Zhen Ni
2026-10-21 11:24 ` [PATCH v3 6/7] mm/page_owner: add bpf_page_owner_get_memcg_info() kfunc Zhen Ni
2026-10-21 11:49 ` sashiko-bot
2026-10-21 11:24 ` [PATCH v3 7/7] selftests/bpf: add tests for the page_owner bpf_iter target Zhen Ni
2026-10-21 11:38 ` sashiko-bot
2026-10-21 18:52 ` [PATCH v3 0/7] mm/page_owner: add bpf_iter and kfuncs Andrew Morton
2026-10-22 11:40 ` zhen.ni
2026-10-21 22:00 ` Alexei Starovoitov
2026-10-23 14:51 ` zhen.ni
2026-10-23 15:58 ` Alexei Starovoitov
2026-10-24 17:19 ` zhen.ni
2026-10-24 19:08 ` Alexei Starovoitov
2026-10-25 2:16 ` zhen.ni [this message]
2026-10-25 4:04 ` Alexei Starovoitov
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=7f9a9da5-1250-4be3-bfa2-70e4b6051197@easystack.cn \
--to=zhen.ni@easystack.cn \
--cc=akpm@linux-foundation.org \
--cc=alexei.starovoitov@gmail.com \
--cc=andrii@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=brendan.jackman@linux.dev \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=hannes@cmpxchg.org \
--cc=ihor.solodrai@linux.dev \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=martin.lau@linux.dev \
--cc=memxor@gmail.com \
--cc=mhocko@suse.com \
--cc=shuah@kernel.org \
--cc=song@kernel.org \
--cc=surenb@google.com \
--cc=vbabka@kernel.org \
--cc=yonghong.song@linux.dev \
--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