From: Ridong Chen <ridong.chen@linux.dev>
To: Barry Song <baohua@kernel.org>, kasong@tencent.com
Cc: linux-mm@kvack.org, Andrew Morton <akpm@linux-foundation.org>,
Axel Rasmussen <axelrasmussen@google.com>,
Yuanchu Xie <yuanchu@google.com>, Wei Xu <weixugc@google.com>,
Baoquan He <baoquan.he@linux.dev>,
Shakeel Butt <shakeel.butt@linux.dev>,
Johannes Weiner <hannes@cmpxchg.org>,
Michal Hocko <mhocko@kernel.org>,
Roman Gushchin <roman.gushchin@linux.dev>,
Muchun Song <muchun.song@linux.dev>, Chris Li <chrisl@kernel.org>,
Baolin Wang <baolin.wang@linux.alibaba.com>,
David Hildenbrand <david@kernel.org>,
Lorenzo Stoakes <ljs@kernel.org>,
"Liam R. Howlett" <liam@infradead.org>,
Vlastimil Babka <vbabka@kernel.org>, Yu Zhao <yuzhao@google.com>,
Zi Yan <ziy@nvidia.com>, Qi Zheng <qi.zheng@linux.dev>,
cgroups@vger.kernel.org, linux-kernel@vger.kernel.org,
Kairui Song <ryncsn@gmail.com>
Subject: Re: [PATCH v3 2/6] mm/mglru: introduce helpers for manipulating gen and refs flags
Date: Sun, 30 Aug 2026 17:08:04 +0800 [thread overview]
Message-ID: <d270d063-027a-4297-bd0c-8f4a1eaf3f40@linux.dev> (raw)
In-Reply-To: <CAGsJ_4yasRXO52K-13dx9ZXPw95wEyn2bpnf0NiQ2z56dxf-vQ@mail.gmail.com>
On 8/29/2026 12:21 PM, Barry Song wrote:
> On Wed, Aug 26, 2026 at 1:53 AM Kairui Song via B4 Relay
> <devnull+kasong.tencent.com@kernel.org> wrote:
>>
>> From: Kairui Song <kasong@tencent.com>
>>
>> Instead of doing bit ops on folio->flags.f, introduce helpers for
>> adjusting a folio's refs and generation info, making the code easier
>> to debug and understand.
>>
>> No functional change is intended: some combined atomic operations are
>> split into two, which only creates harmless transient states. There is
>> no measurable performance impact, and some paths even look slightly
>> better in the generated assembly.
>
> Hi Kairui,
>
> I like your idea. Overall, it looks good to me. With some cleanup,
> we might have the following:
>
>>
>> Signed-off-by: Kairui Song <kasong@tencent.com>
>> ---
>> include/linux/mm_inline.h | 76 ++++++++++++++++++++++++++++++++++++++++++-----
>> include/linux/mmzone.h | 1 +
>> mm/folio.c | 19 +++++++-----
>> mm/vmscan.c | 61 ++++++++++++++++++++-----------------
>> 4 files changed, 114 insertions(+), 43 deletions(-)
>>
>> diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h
>> index 621c8653d8f7..edfaf2661812 100644
>> --- a/include/linux/mm_inline.h
>> +++ b/include/linux/mm_inline.h
>> @@ -142,10 +142,42 @@ static inline int lru_tier_from_refs(int refs, bool workingset)
>> return workingset ? MAX_NR_TIERS - 1 : order_base_2(refs);
>> }
>>
>> -static inline int folio_lru_refs(const struct folio *folio)
>> +/**
>> + * lru_gen_from_flags - Return the LRU generation number from folio flags.
>> + * @flags: folio flags
>> + *
>> + * Returns: A number between 0 and (MAX_NR_GENS - 1), inclusive. Returns
>> + * -1 if the flags indicate the folio is off the list (e.g., isolated).
>> + */
>> +static inline int lru_gen_from_flags(unsigned long flags)
>> +{
>> + int gen = ((flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF);
>> +
>> + BUILD_BUG_ON(LRU_GEN_MASK & LRU_REFS_MASK);
>> + gen -= 1;
>> + VM_WARN_ON_ONCE(gen != -1 && gen >= MAX_NR_GENS);
>
> Since `gen` is an `int`, it seems a bit odd to have
> `gen != -1 && gen >= MAX_NR_GENS` combined here.
>
Agreed. Especially with the gen -= 1 right above, it took me a while to figure
out what that actually meant.
> Do you actually mean the following instead?
>
> VM_WARN_ON_ONCE(gen < -1 || gen >= MAX_NR_GENS);
>
Maybe we could add a macro like the one I mentioned in my earlier reply:
GENS_UNREF -1
>> + return gen;
>> +}
>> +
>> +/**
>> + * lru_gen_set_flags - Set the LRU generation number to specified folio flags.
>> + * @flags: pointer to the folio flags
>> + * @gen: generation number, between 0 and (MAX_NR_GENS - 1), inclusive.
>> + */
>> +static inline void lru_gen_set_flags(unsigned long *flags, int gen)
>> {
>> - unsigned long flags = READ_ONCE(folio->flags.f);
>> + VM_WARN_ON_ONCE(gen >= MAX_NR_GENS || gen < 0);
>> +
>> + *flags &= ~LRU_GEN_MASK;
>> + *flags |= (gen + 1UL) << LRU_GEN_PGOFF;
>> +}
>
> It seems that we are setting the gen in the flags, rather than
> setting the flags themselves.
>
> The current name makes me think that the function is setting the
> entire flags field, especially since `lru_gen` is used as the
> namespace for various MGLRU functions, e.g.:
>
> void lru_gen_add_mm(struct mm_struct *mm);
> void lru_gen_del_mm(struct mm_struct *mm);
> void lru_gen_migrate_mm(struct mm_struct *mm);
> struct lru_gen_folio;
> lru_gen_update_size(lruvec, folio, old_gen, new_gen);
>
> However, this function only sets the gen bits in the flags.
> Maybe we could use a name that makes this distinction clearer?
>
> Could they be named as below, or is there a better naming option?
>
> set_gen_to_flags(unsigned long *flags, int gen);
> get_gen_from_flags(unsigned long flags);
>
> Or something like flags_to_gen() or gen_from_flags()?
>
>>
>> +/**
>> + * lru_refs_from_flags - Return LRU referenced / access count from folio flags.
>> + * @flags: folio flags
>> + */
>> +static inline int lru_refs_from_flags(unsigned long flags)
>> +{
>> if (!(flags & BIT(PG_referenced)))
>> return 0;
>> /*
>> @@ -155,11 +187,40 @@ static inline int folio_lru_refs(const struct folio *folio)
>> return ((flags & LRU_REFS_MASK) >> LRU_REFS_PGOFF) + 1;
>> }
>>
>> -static inline int folio_lru_gen(const struct folio *folio)
>> +/**
>> + * lru_refs_set_flags - Set the LRU referenced / access count to specified folio flags.
>> + * @flags: pointer to the folio flags
>> + * @refs: referenced / access count number, between 0 and LRU_REFS_MAX, inclusive.
>> + */
>> +static inline void lru_refs_set_flags(unsigned long *flags, unsigned int refs)
>> +{
>> + VM_WARN_ON_ONCE(refs > LRU_REFS_MAX);
>> + BUILD_BUG_ON(LRU_REFS_MAX != (LRU_REFS_MASK >> LRU_REFS_PGOFF) + 1);
>> +
>> + *flags &= ~LRU_REFS_FLAGS;
>> + if (!refs)
>> + return;
>> + *flags |= (BIT(PG_referenced) | ((refs - 1UL) << LRU_REFS_PGOFF));
>> +}
>
> Similar to the above, maybe we could use more descriptive names?
>
>> +
>> +static inline int folio_lru_refs(const struct folio *folio)
>> {
>> - unsigned long flags = READ_ONCE(folio->flags.f);
>> + return lru_refs_from_flags(READ_ONCE(*const_folio_flags(folio, 0)));
>> +}
>> +
>> +static inline void folio_set_lru_refs(struct folio *folio, unsigned int refs)
>> +{
>> + unsigned long new_flags, old_flags = READ_ONCE(*folio_flags(folio, 0));
>> +
>> + do {
>> + new_flags = old_flags;
>> + lru_refs_set_flags(&new_flags, refs);
>> + } while (!try_cmpxchg(folio_flags(folio, 0), &old_flags, new_flags));
>> +}
>>
>> - return ((flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1;
>
> [...]
>
>> diff --git a/mm/vmscan.c b/mm/vmscan.c
>> index 73a81b4a3e16..9ee9f8dc6805 100644
>> --- a/mm/vmscan.c
>> +++ b/mm/vmscan.c
>> @@ -843,19 +843,22 @@ static bool lru_gen_set_refs(struct folio *folio, const vma_flags_t *vma_flags)
>> if (!folio_test_referenced(folio) && !folio_test_workingset(folio)) {
>> /* Activate file-backed executable folios after first usage. */
>> if (is_exec_file_folio(folio, vma_flags)) {
>> - set_mask_bits(&folio->flags.f, LRU_REFS_FLAGS, BIT(PG_workingset));
>> + folio_set_workingset(folio);
>> + folio_set_lru_refs(folio, 0);
>> return true;
>> }
>>
>> - set_mask_bits(&folio->flags.f, LRU_REFS_MASK, BIT(PG_referenced));
>> + folio_set_lru_refs(folio, 1);
>
> We have quite a few instances of folio_set_lru_refs(folio, 1) and
> folio_set_lru_refs(folio, 0). Do these values have any special
> meaning? Could we add wrapper helpers to make the code more readable?
>
> `1` just means `PG_referenced`, right? Could we add a comment or
> changelog description to clarify that `1` actually means `refs = 0`,
> but `PG_referenced` is set?
>
> Thanks
> Barry
--
Best regards
Ridong
next prev parent reply other threads:[~2026-08-30 9:08 UTC|newest]
Thread overview: 37+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-25 17:53 [PATCH v3 0/6] mm/mglru: clean up folio counters and flag usage Kairui Song via B4 Relay
2026-08-25 17:53 ` Kairui Song
2026-08-25 17:53 ` [PATCH v3 1/6] mm/memcontrol: make lru_zone_size atomic and simplify sanity check Kairui Song via B4 Relay
2026-08-25 17:53 ` Kairui Song
2026-08-29 3:34 ` Barry Song
2026-08-25 17:53 ` [PATCH v3 2/6] mm/mglru: introduce helpers for manipulating gen and refs flags Kairui Song via B4 Relay
2026-08-25 17:53 ` Kairui Song
2026-08-25 18:20 ` Kairui Song
2026-08-26 10:48 ` Qi Zheng
2026-08-27 7:32 ` Baolin Wang
[not found] ` <apRx-xd0csgBU4sL@KASONG-MC4>
2026-08-31 8:52 ` Baolin Wang
2026-08-29 4:21 ` Barry Song
2026-08-29 7:47 ` Kairui Song
2026-08-29 8:26 ` Barry Song
2026-08-30 18:34 ` Kairui Song
2026-08-30 9:08 ` Ridong Chen [this message]
2026-08-30 8:39 ` Ridong Chen
2026-08-30 17:19 ` Kairui Song
2026-08-25 17:53 ` [PATCH v3 3/6] mm/migrate: copy all referenced state via folio_migrate_lru_refs Kairui Song via B4 Relay
2026-08-25 17:53 ` Kairui Song
2026-08-27 7:33 ` Baolin Wang
2026-08-27 10:55 ` David Hildenbrand (Arm)
2026-08-28 5:26 ` Lian Wang
2026-08-29 9:56 ` Barry Song
2026-08-30 9:23 ` Ridong Chen
2026-08-25 17:53 ` [PATCH v3 4/6] mm/mglru: move max_seq read into walk_update_folio Kairui Song via B4 Relay
2026-08-25 17:53 ` Kairui Song
2026-08-28 5:28 ` Lian Wang
2026-08-29 10:04 ` Barry Song
2026-08-25 17:53 ` [PATCH v3 5/6] mm/mglru: use explicit tier range in read_ctrl_pos() Kairui Song via B4 Relay
2026-08-25 17:53 ` Kairui Song
2026-08-28 5:29 ` Lian Wang
2026-08-29 14:31 ` Kairui Song
2026-08-30 9:43 ` Ridong Chen
2026-08-25 17:53 ` [PATCH v3 6/6] mm/mglru: fix potential generation folio number leak Kairui Song via B4 Relay
2026-08-25 17:53 ` Kairui Song
2026-08-28 23:19 ` [PATCH v3 0/6] mm/mglru: clean up folio counters and flag usage 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=d270d063-027a-4297-bd0c-8f4a1eaf3f40@linux.dev \
--to=ridong.chen@linux.dev \
--cc=akpm@linux-foundation.org \
--cc=axelrasmussen@google.com \
--cc=baohua@kernel.org \
--cc=baolin.wang@linux.alibaba.com \
--cc=baoquan.he@linux.dev \
--cc=cgroups@vger.kernel.org \
--cc=chrisl@kernel.org \
--cc=david@kernel.org \
--cc=hannes@cmpxchg.org \
--cc=kasong@tencent.com \
--cc=liam@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=mhocko@kernel.org \
--cc=muchun.song@linux.dev \
--cc=qi.zheng@linux.dev \
--cc=roman.gushchin@linux.dev \
--cc=ryncsn@gmail.com \
--cc=shakeel.butt@linux.dev \
--cc=vbabka@kernel.org \
--cc=weixugc@google.com \
--cc=yuanchu@google.com \
--cc=yuzhao@google.com \
--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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.