From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id D5FBBC5B572 for ; Thu, 20 Aug 2026 02:05:28 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id AC0E66B008C; Wed, 19 Aug 2026 22:05:27 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id A71C56B0092; Wed, 19 Aug 2026 22:05:27 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 9AE3A6B0095; Wed, 19 Aug 2026 22:05:27 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0011.hostedemail.com [216.40.44.11]) by kanga.kvack.org (Postfix) with ESMTP id 753F26B008C for ; Wed, 19 Aug 2026 22:05:27 -0400 (EDT) Received: from smtpin18.hostedemail.com (lb01a-stub [10.200.18.249]) by unirelay04.hostedemail.com (Postfix) with ESMTP id E3E981A0317 for ; Thu, 20 Aug 2026 02:05:26 +0000 (UTC) X-FDA: 85120005852.18.D858F8D Received: from mta0.migadu.com (out-145.mta0.migadu.com [91.218.175.145]) by imf18.hostedemail.com (Postfix) with ESMTP id C24071C0002 for ; Thu, 20 Aug 2026 02:05:24 +0000 (UTC) Authentication-Results: imf18.hostedemail.com; dkim=pass header.d=linux.dev header.s=key1 header.b="n1dhm/K7"; spf=pass (imf18.hostedemail.com: domain of ridong.chen@linux.dev designates 91.218.175.145 as permitted sender) smtp.mailfrom=ridong.chen@linux.dev; dmarc=pass (policy=none) header.from=linux.dev ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1787191525; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=/jDDYXSbRaW8PhcOhBWb7QQ0tBcYH7mTzy2znvbWhto=; b=3bGQDVtB/mWklhVOJYDaQaEsbijxrik6Ilq5oYeIplnuG1OvK1ku2wfaKoqf46n9EWB+oO wcIOqt1CGkuovx73luqCnhC4rOoaAg/efduO/u2ugBIy1Az7b2CPgqFII2RzcBmloss0y9 FnMYZIqt7WcGFLQRIqCDA8dO8dLjwx8= ARC-Seal: i=1; a=rsa-sha256; d=hostedemail.com; s=arc-20220608; cv=none; t=1787191525; b=Vmbk2qSj7wEEXMRZ52m10wNesexPOpY/FR07kaGoZAOzk5hUtLTqh63hmcY8gZnMbgR6Dn r+6T9dS+P0a6XmV/HNN8Hex5Dl6r67XTn75MUueOMWN4mXIiEVF6jl55pkRsnqPuST3Bly 63loDg5Ddy1nkCCNKY/Z2dSj39g/hSw= ARC-Authentication-Results: i=1; imf18.hostedemail.com; dkim=pass header.d=linux.dev header.s=key1 header.b="n1dhm/K7"; spf=pass (imf18.hostedemail.com: domain of ridong.chen@linux.dev designates 91.218.175.145 as permitted sender) smtp.mailfrom=ridong.chen@linux.dev; dmarc=pass (policy=none) header.from=linux.dev X-Envelope-To: linux-mm@kvack.org DKIM-Signature: a=rsa-sha256; bh=GC5cAHTmrsC6CuFnURxYXv5THmItmLPch05Dbxb7Vgc=; c=simple/simple; d=linux.dev; h=from:to:subject:date:message-id:mime-version:content-type; s=key1; t=1787191523; v=1; x=1787796323; b=n1dhm/K7ypyoCvIGPu4Rvv2RXnj2Oj0zxeDdnxSvQ3RmTvRaBuSgaDZv89lLE00lkeOCCDo8 jTrSmsSmM8jSCisZXlGyfMBNLqLKYtXnNjbH66/DWLVXq+/ivI79xwNQjeYZFjXlfufY9+WURGU 44kSYVCkcWbDu2jGmE70NA7I= X-Envelope-To: linux-mm@kvack.org Received: from [10.63.107.123] (14.29.108.92) by smtp.migadu.com with ESMTPS id 59725e7d187116bb; Thu, 20 Aug 2026 02:05:23 +0000 X-Mizu-Trace-ID: 59725e7d187116bb X-Migadu-Flow: FLOW_OUT Message-ID: Date: Thu, 20 Aug 2026 10:05:15 +0800 MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH 2/7] mm/mglru: introduce helpers for manipulating gen and refs flags From: Ridong Chen To: kasong@tencent.com, linux-mm@kvack.org Cc: Andrew Morton , Barry Song , Axel Rasmussen , Yuanchu Xie , Wei Xu , Baoquan He , Shakeel Butt , Johannes Weiner , Michal Hocko , Roman Gushchin , Muchun Song , Chris Li , Baolin Wang , David Hildenbrand , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Yu Zhao , Zi Yan , Qi Zheng , cgroups@vger.kernel.org, linux-kernel@vger.kernel.org, Kairui Song References: <20260818-mglru-flags-cleanup-v1-0-8dbbdac0d28c@tencent.com> <20260818-mglru-flags-cleanup-v1-2-8dbbdac0d28c@tencent.com> In-Reply-To: Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-Rspam-User: X-Stat-Signature: 3pdazhfgjyerggi4mdo5i6sirerxwhu9 X-Rspamd-Server: rspam01 X-Rspamd-Queue-Id: C24071C0002 X-HE-Tag: 1787191524-493980 X-HE-Meta: U2FsdGVkX19SFqjI0d7niTI3c0bOiUnDEMkHVIutC6M9z8GfmZPtyMwswdSmqq+MZMR/RvewEvDs1J3LKWfAWBeC+vfgpUvTUgowscx2VjD+5famPOzApX0gLLyTFPYz988yZOuUEYN6AgYwy/twzVZqZNJANDbAuBiYOlkIt+Yprzgo1eTu89ac/Qj7Jd1/mCRjjC7CVJLTr3VvCgD5xP9mkfq3/YPHQAhgrc3ZRCqOyCOT+ke62UPZpCX7af7EdOQKvK8q6YyYFOIM/mkUM4jx9Us7vbo9+dZhABR8OCQlmIHfVehlFMkfrRHFQ3QRmhC5lWWfGWYBS1hhcnm/yxjdDRNMBf8pwFeKB3txGcw/QcAsoTA+oKS8NdXwHoU6ZD48kJmi1nkQqJptPE/cUGaAPtFgon2UjQg9D8aW6qAq7/OSaN16Z9f1fHJZlVmWQwCBeRfXTTHr2d3r+1RYtzy5KYm4oZCY28WlFY2AgARtuKHnUuhl8DABt7ICDFvmlFb1MmTcxUKtzMUD4TPCOf0kXnUmIS/vLvnJgsM7jniIdPTqLJOK1tYcIeWqt+zXCo0VKcfAXd5unAW8N5juWf9zEaZG8Jh+wym7+D1FrgxJRJUEhI/cofnFEAntI2Eg0q9Ai9cBW6WWORBAzABPGUGYl6s41JsA6/Y0CD0DkwhcfCgQWsbl5EKAw3QqsNIDA7MpPW1M/uasFy+psgOftzNRIqakaX8yWKSgWP+Xttw/mGwvCmGdOIi5q87k4PRbZOVJF1SNQ0ocJYsrQFgCgVmvHdjHpcUsbCQf8eery/W6JvniKDohT6mF2n5ORHgz4OzK2v6kIhhZw2090siiMaY6vD2zyCzEipQlrLETYcQ3ajTT+fKJe23MdLZK6VfEjfIE+ZlXrGyVmBlUBabu7qR/TIUcP/WKqss36Sdr/pVWM2yDVCzg85X1AI3biomIPA1v5RZHE+Img3ZfnbC ToIC1n8G TFUrrSNcYVoW98XgiIb77EjaBQB+NCJ5Tur7njM4VkGgEtVmZwN7BaC7yx/1JvivvmjLAMtdzW13MJbcErJvchyA73QOEbgBDFJiw9tOCXqh/a0tE4ap5afRke9YaNbBuVynD5wnmemIkRc6/v/fX1b+RDF+VQUwfk/NmQp/PSVdWEhN47vDaL+YKomWJixLW525qfMDj/a1YEw2qJnbAJVez2u4PZwlTvFt0fF/Vcs/atBdINt/g4uuZeEMbT/bbwOzhhpV3IKIe5G1Njgtta92wJqFDpAEKpZ0vEyifz6UPCYErVgXXZOFuGSkvpGN8NvFY53/qSM8R/T0= Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: On 8/20/2026 9:43 AM, Ridong Chen wrote: > > > On 8/18/2026 1:38 PM, Kairui Song via B4 Relay wrote: >> From: Kairui Song >> >> Instead of doing bit ops on folio->flags.f, introduce helpers for >> adjusting folio's refs and gen info, make 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. >> >> Signed-off-by: Kairui Song >> --- >>   include/linux/mm_inline.h | 79 +++++++++++++++++++++++++++++++++++++++++------ >>   include/linux/mmzone.h    |  2 ++ >>   mm/folio.c                | 19 +++++++----- >>   mm/vmscan.c               | 61 ++++++++++++++++++++---------------- >>   4 files changed, 117 insertions(+), 44 deletions(-) >> >> diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h >> index 621c8653d8f7..93bf3fa221f8 100644 >> --- a/include/linux/mm_inline.h >> +++ b/include/linux/mm_inline.h >> @@ -142,10 +142,43 @@ 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 LRU_GEN_MAX, 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 > LRU_GEN_MAX); > > Perhaps we could define a macro such as GEN_OFF = -1 to make the code more self- > explanatory, I found this warning a bit confusing at first glance. > > LRU_GEN_MAX already bears some resemblance to MAX_NR_GENS, so introducing yet > another macro may add some clutter. > Ah, I just noticed Baolin already mentioned that, sorry for the noise. > Just my two cents. > >> +    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 LRU_GEN_MAX, 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 > LRU_GEN_MAX || gen < 0); >> +    BUILD_BUG_ON((LRU_GEN_MAX + 1) != MAX_NR_GENS); >> + >> +    *flags &= ~LRU_GEN_MASK; >> +    *flags |= (gen + 1UL) << LRU_GEN_PGOFF; >> +} >> +/** >> + * 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,18 +188,47 @@ 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)); >> +} >> + >> +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; >> +static inline int folio_lru_gen(const struct folio *folio) >> +{ >> +    return lru_gen_from_flags(READ_ONCE(*const_folio_flags(folio, 0))); >>   } >>   static inline bool lru_gen_is_active(const struct lruvec *lruvec, int gen) >>   { >>       unsigned long max_seq = lruvec->lrugen.max_seq; >> -    VM_WARN_ON_ONCE(gen >= MAX_NR_GENS); >> +    VM_WARN_ON_ONCE(gen > LRU_GEN_MAX); >>       /* see the comment on MIN_NR_GENS */ >>       return gen == lru_gen_from_seq(max_seq) || gen == >> lru_gen_from_seq(max_seq - 1); >> @@ -270,7 +332,7 @@ static inline bool lru_gen_add_folio(struct lruvec >> *lruvec, struct folio *folio, >>       gen = lru_gen_from_seq(seq); >>       flags = (gen + 1UL) << LRU_GEN_PGOFF; >>       /* see the comment on MIN_NR_GENS about PG_active */ >> -    set_mask_bits(&folio->flags.f, LRU_GEN_MASK | BIT(PG_active), flags); >> +    set_mask_bits(folio_flags(folio, 0), LRU_GEN_MASK | BIT(PG_active), flags); >>       lru_gen_update_size(lruvec, folio, -1, gen); >>       /* for folio_rotate_reclaimable() */ >> @@ -295,7 +357,7 @@ static inline bool lru_gen_del_folio(struct lruvec >> *lruvec, struct folio *folio, >>       /* for folio_migrate_flags() */ >>       flags = !reclaiming && lru_gen_is_active(lruvec, gen) ? BIT(PG_active) : 0; >> -    flags = set_mask_bits(&folio->flags.f, LRU_GEN_MASK, flags); >> +    flags = set_mask_bits(folio_flags(folio, 0), LRU_GEN_MASK, flags); >>       gen = ((flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1; >>       lru_gen_update_size(lruvec, folio, gen, -1); >> @@ -339,7 +401,6 @@ static inline bool lru_gen_del_folio(struct lruvec >> *lruvec, struct folio *folio, >>   static inline void folio_migrate_refs(struct folio *new, const struct folio >> *old) >>   { >> - >>   } >>   #endif /* CONFIG_LRU_GEN */ >> diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h >> index 94f9c3ff5416..32d9354a754f 100644 >> --- a/include/linux/mmzone.h >> +++ b/include/linux/mmzone.h >> @@ -496,7 +496,9 @@ enum lruvec_flags { >>   #ifndef __GENERATING_BOUNDS_H >>   #define LRU_GEN_MASK        ((BIT(LRU_GEN_WIDTH) - 1) << LRU_GEN_PGOFF) >> +#define LRU_GEN_MAX        (BIT(LRU_GEN_WIDTH - 1) - 1) >>   #define LRU_REFS_MASK        ((BIT(LRU_REFS_WIDTH) - 1) << LRU_REFS_PGOFF) >> +#define LRU_REFS_MAX        BIT(LRU_REFS_WIDTH) >>   /* >>    * For folios accessed multiple times through file descriptors, >> diff --git a/mm/folio.c b/mm/folio.c >> index 59c477120b9a..0adfe4f5ef72 100644 >> --- a/mm/folio.c >> +++ b/mm/folio.c >> @@ -353,26 +353,28 @@ static void __lru_cache_activate_folio(struct folio *folio) >>   static void lru_gen_inc_refs(struct folio *folio) >>   { >> -    unsigned long new_flags, old_flags = READ_ONCE(folio->flags.f); >> +    unsigned long new_flags, old_flags = READ_ONCE(*folio_flags(folio, 0)); >> +    int refs; >>       if (folio_test_unevictable(folio)) >>           return; >>       /* see the comment on LRU_REFS_FLAGS */ >> -    if (!folio_test_referenced(folio)) { >> -        set_mask_bits(&folio->flags.f, LRU_REFS_MASK, BIT(PG_referenced)); >> +    if (!folio_lru_refs(folio)) { >> +        folio_set_lru_refs(folio, 1); >>           return; >>       } >>       do { >> -        if ((old_flags & LRU_REFS_MASK) == LRU_REFS_MASK) { >> +        new_flags = old_flags; >> +        refs = lru_refs_from_flags(old_flags); >> +        if (refs == LRU_REFS_MAX) { >>               if (!folio_test_workingset(folio)) >>                   folio_set_workingset(folio); >>               return; >>           } >> - >> -        new_flags = old_flags + BIT(LRU_REFS_PGOFF); >> -    } while (!try_cmpxchg(&folio->flags.f, &old_flags, new_flags)); >> +        lru_refs_set_flags(&new_flags, refs + 1); >> +    } while (!try_cmpxchg(folio_flags(folio, 0), &old_flags, new_flags)); >>   } >>   static bool lru_gen_clear_refs(struct folio *folio) >> @@ -384,7 +386,8 @@ static bool lru_gen_clear_refs(struct folio *folio) >>       if (gen < 0) >>           return true; >> -    set_mask_bits(&folio->flags.f, LRU_REFS_FLAGS | BIT(PG_workingset), 0); >> +    folio_set_lru_refs(folio, 0); >> +    folio_clear_workingset(folio); >>       rcu_read_lock(); >>       seq = READ_ONCE(folio_lruvec(folio)->lrugen.min_seq[type]); >> diff --git a/mm/vmscan.c b/mm/vmscan.c >> index c1404a59523d..080132997d87 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_lru_refs(folio, 0); >> +            folio_set_workingset(folio); >>               return true; >>           } >> -        set_mask_bits(&folio->flags.f, LRU_REFS_MASK, BIT(PG_referenced)); >> +        folio_set_lru_refs(folio, 1); >>           return false; >>       } >>       /* Promote on second access */ >> -    if (folio_lru_refs(folio) > 1) >> -        set_mask_bits(&folio->flags.f, LRU_REFS_FLAGS, BIT(PG_workingset)); >> -    else >> +    if (folio_lru_refs(folio) > 1) { >> +        folio_set_lru_refs(folio, 0); >> +        folio_set_workingset(folio); >> +    } else { >>           folio_mark_accessed(folio); >> +    } >>       return true; >>   } >>   #else >> @@ -3266,11 +3269,10 @@ static bool positive_ctrl_err(struct ctrl_pos *sp, >> struct ctrl_pos *pv) >> >> ******************************************************************************/ >>   /* promote pages accessed through page tables */ >> -static int folio_update_gen(struct folio *folio, int gen, const vma_flags_t >> *vma_flags) >> +static int folio_update_gen(struct folio *folio, int new_gen, const >> vma_flags_t *vma_flags) >>   { >> -    unsigned long new_flags, old_flags = READ_ONCE(folio->flags.f); >> - >> -    VM_WARN_ON_ONCE(gen >= MAX_NR_GENS); >> +    unsigned long new_flags, old_flags = READ_ONCE(*folio_flags(folio, 0)); >> +    int old_gen; >>       /* >>        * See the comment on LRU_REFS_FLAGS, and activate file-backed >> @@ -3279,20 +3281,24 @@ static int folio_update_gen(struct folio *folio, int >> gen, const vma_flags_t *vma >>        */ >>       if (!folio_test_referenced(folio) && !folio_test_workingset(folio) && >>           !is_exec_file_folio(folio, vma_flags)) { >> -        set_mask_bits(&folio->flags.f, LRU_REFS_MASK, BIT(PG_referenced)); >> +        folio_set_lru_refs(folio, 1); >>           return -1; >>       } >>       do { >> +        old_gen = lru_gen_from_flags(old_flags); >> +        new_flags = old_flags; >> + >>           /* lru_gen_del_folio() has isolated this page? */ >> -        if (!(old_flags & LRU_GEN_MASK)) >> -            return -1; >> +        if (old_gen < 0) >> +            break; >> -        new_flags = old_flags & ~(LRU_GEN_MASK | LRU_REFS_FLAGS); >> -        new_flags |= ((gen + 1UL) << LRU_GEN_PGOFF) | BIT(PG_workingset); >> -    } while (!try_cmpxchg(&folio->flags.f, &old_flags, new_flags)); >> +        lru_gen_set_flags(&new_flags, new_gen); >> +        lru_refs_set_flags(&new_flags, 0); >> +        new_flags |= BIT(PG_workingset); >> +    } while (!try_cmpxchg(folio_flags(folio, 0), &old_flags, new_flags)); >> -    return ((old_flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1; >> +    return old_gen; >>   } >>   /* protect pages accessed multiple times through file descriptors */ >> @@ -3301,21 +3307,20 @@ static int folio_inc_gen(struct lruvec *lruvec, struct >> folio *folio) >>       int type = folio_is_file_lru(folio); >>       struct lru_gen_folio *lrugen = &lruvec->lrugen; >>       int new_gen, old_gen = lru_gen_from_seq(lrugen->min_seq[type]); >> -    unsigned long new_flags, old_flags = READ_ONCE(folio->flags.f); >> - >> -    VM_WARN_ON_ONCE_FOLIO(!(old_flags & LRU_GEN_MASK), folio); >> +    unsigned long new_flags, old_flags = READ_ONCE(*folio_flags(folio, 0)); >>       do { >> -        new_gen = ((old_flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1; >> +        new_gen = lru_gen_from_flags(old_flags); >> + >>           /* folio_update_gen() has promoted this page? */ >>           if (new_gen >= 0 && new_gen != old_gen) >>               return new_gen; >> +        new_flags = old_flags; >>           new_gen = (old_gen + 1) % MAX_NR_GENS; >> - >> -        new_flags = old_flags & ~(LRU_GEN_MASK | LRU_REFS_FLAGS); >> -        new_flags |= (new_gen + 1UL) << LRU_GEN_PGOFF; >> -    } while (!try_cmpxchg(&folio->flags.f, &old_flags, new_flags)); >> +        lru_gen_set_flags(&new_flags, new_gen); >> +        lru_refs_set_flags(&new_flags, 0); >> +    } while (!try_cmpxchg(folio_flags(folio, 0), &old_flags, new_flags)); >>       lru_gen_update_size(lruvec, folio, old_gen, new_gen); >> @@ -4711,7 +4716,7 @@ static bool isolate_folio(struct lruvec *lruvec, struct >> folio *folio, struct sca >>       /* see the comment on LRU_REFS_FLAGS */ >>       if (!folio_test_referenced(folio)) >> -        set_mask_bits(&folio->flags.f, LRU_REFS_MASK, 0); >> +        folio_set_lru_refs(folio, 0); >>       success = lru_gen_del_folio(lruvec, folio, true); >>       VM_WARN_ON_ONCE_FOLIO(!success, folio); >> @@ -4927,8 +4932,10 @@ static int evict_folios(unsigned long nr_to_scan, >> struct lruvec *lruvec, >>           } >>           /* don't add rejected folios to the oldest generation */ >> -        if (lru_gen_folio_seq(lruvec, folio, false) == min_seq[type]) >> -            set_mask_bits(&folio->flags.f, LRU_REFS_FLAGS, BIT(PG_active)); >> +        if (lru_gen_folio_seq(lruvec, folio, false) == min_seq[type]) { >> +            folio_set_lru_refs(folio, 0); >> +            folio_set_active(folio); >> +        } >>       } >>       move_folios_to_lru(&list); >> > -- Best regards Ridong