]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
mm: introduce memdesc_flags_t
authorMatthew Wilcox (Oracle) <willy@infradead.org>
Tue, 5 Aug 2025 17:22:51 +0000 (18:22 +0100)
committerAndrew Morton <akpm@linux-foundation.org>
Fri, 12 Sep 2025 00:25:06 +0000 (17:25 -0700)
Patch series "Add and use memdesc_flags_t".

At some point struct page will be separated from struct slab and struct
folio.  This is a step towards that by introducing a type for the 'flags'
word of all three structures.  This gives us a certain amount of type
safety by establishing that some of these unsigned longs are different
from other unsigned longs in that they contain things like node ID,
section number and zone number in the upper bits.  That lets us have
functions that can be easily called by anyone who has a slab, folio or
page (but not easily by anyone else) to get the node or zone.

There's going to be some unusual merge problems with this as some odd bits
of the kernel decide they want to print out the flags value or something
similar by writing page->flags and now they'll need to write page->flags.f
instead.  That's most of the churn here.  Maybe we should be removing
these things from the debug output?

This patch (of 11):

Wrap the unsigned long flags in a typedef.  In upcoming patches, this will
provide a strong hint that you can't just pass a random unsigned long to
functions which take this as an argument.

Link: https://lkml.kernel.org/r/20250805172307.1302730-1-willy@infradead.org
Link: https://lkml.kernel.org/r/20250805172307.1302730-2-willy@infradead.org
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Acked-by: Zi Yan <ziy@nvidia.com>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
22 files changed:
arch/x86/mm/pat/memtype.c
fs/fuse/dev.c
fs/gfs2/glops.c
fs/jffs2/file.c
fs/nilfs2/page.c
fs/proc/page.c
fs/ubifs/file.c
include/linux/mm.h
include/linux/mm_inline.h
include/linux/mm_types.h
include/linux/mmzone.h
include/linux/page-flags.h
include/linux/pgalloc_tag.h
include/trace/events/page_ref.h
mm/filemap.c
mm/huge_memory.c
mm/memory-failure.c
mm/mmzone.c
mm/page_alloc.c
mm/swap.c
mm/vmscan.c
mm/workingset.c

index c09284302dd3cd042ce02758efe5388bc4432fe6..b68200a0e0c6faad6da54ec017c3d11b343a51b5 100644 (file)
@@ -126,7 +126,7 @@ __setup("debugpat", pat_debug_setup);
 
 static inline enum page_cache_mode get_page_memtype(struct page *pg)
 {
-       unsigned long pg_flags = pg->flags & _PGMT_MASK;
+       unsigned long pg_flags = pg->flags.f & _PGMT_MASK;
 
        if (pg_flags == _PGMT_WB)
                return _PAGE_CACHE_MODE_WB;
@@ -161,10 +161,10 @@ static inline void set_page_memtype(struct page *pg,
                break;
        }
 
-       old_flags = READ_ONCE(pg->flags);
+       old_flags = READ_ONCE(pg->flags.f);
        do {
                new_flags = (old_flags & _PGMT_CLEAR_MASK) | memtype_flags;
-       } while (!try_cmpxchg(&pg->flags, &old_flags, new_flags));
+       } while (!try_cmpxchg(&pg->flags.f, &old_flags, new_flags));
 }
 #else
 static inline enum page_cache_mode get_page_memtype(struct page *pg)
index e80cd8f2c049f9abd584f35922e6c0aeffad2913..8a89f0aa1d4d5e60920270290ac8250549728f01 100644 (file)
@@ -935,7 +935,7 @@ static int fuse_check_folio(struct folio *folio)
 {
        if (folio_mapped(folio) ||
            folio->mapping != NULL ||
-           (folio->flags & PAGE_FLAGS_CHECK_AT_PREP &
+           (folio->flags.f & PAGE_FLAGS_CHECK_AT_PREP &
             ~(1 << PG_locked |
               1 << PG_referenced |
               1 << PG_lru |
index fe0faad4892f8b97530c25e6390d52e840872e9a..0c0a80b3bacab29c0eff2f4f5b749245ca57c615 100644 (file)
@@ -40,7 +40,7 @@ static void gfs2_ail_error(struct gfs2_glock *gl, const struct buffer_head *bh)
               "AIL buffer %p: blocknr %llu state 0x%08lx mapping %p page "
               "state 0x%lx\n",
               bh, (unsigned long long)bh->b_blocknr, bh->b_state,
-              bh->b_folio->mapping, bh->b_folio->flags);
+              bh->b_folio->mapping, bh->b_folio->flags.f);
        fs_err(sdp, "AIL glock %u:%llu mapping %p\n",
               gl->gl_name.ln_type, gl->gl_name.ln_number,
               gfs2_glock2aspace(gl));
index dd3dff95cb24fdab8de19505c2e6a4ee3219d047..b697f3c259ef25171ce30785d4584d5a53751a0d 100644 (file)
@@ -230,7 +230,7 @@ static int jffs2_write_begin(const struct kiocb *iocb,
                        goto release_sem;
                }
        }
-       jffs2_dbg(1, "end write_begin(). folio->flags %lx\n", folio->flags);
+       jffs2_dbg(1, "end write_begin(). folio->flags %lx\n", folio->flags.f);
 
 release_sem:
        mutex_unlock(&c->alloc_sem);
@@ -259,7 +259,7 @@ static int jffs2_write_end(const struct kiocb *iocb,
 
        jffs2_dbg(1, "%s(): ino #%lu, page at 0x%llx, range %d-%d, flags %lx\n",
                  __func__, inode->i_ino, folio_pos(folio),
-                 start, end, folio->flags);
+                 start, end, folio->flags.f);
 
        /* We need to avoid deadlock with page_cache_read() in
           jffs2_garbage_collect_pass(). So the folio must be
index 806b056d2260783b5945dcd74df521d2491fdab5..56c4da417b6a1f0043b9c8763fab3d260fb8a871 100644 (file)
@@ -167,7 +167,7 @@ void nilfs_folio_bug(struct folio *folio)
        printk(KERN_CRIT "NILFS_FOLIO_BUG(%p): cnt=%d index#=%llu flags=0x%lx "
               "mapping=%p ino=%lu\n",
               folio, folio_ref_count(folio),
-              (unsigned long long)folio->index, folio->flags, m, ino);
+              (unsigned long long)folio->index, folio->flags.f, m, ino);
 
        head = folio_buffers(folio);
        if (head) {
index ba3568e97fd18e1574c834609a95f753f2d4bffb..771e0b6bc6302075c6ccd56979255e9ab9c80199 100644 (file)
@@ -163,7 +163,7 @@ u64 stable_page_flags(const struct page *page)
        snapshot_page(&ps, page);
        folio = &ps.folio_snapshot;
 
-       k = folio->flags;
+       k = folio->flags.f;
        mapping = (unsigned long)folio->mapping;
        is_anon = mapping & FOLIO_MAPPING_ANON;
 
@@ -238,7 +238,7 @@ u64 stable_page_flags(const struct page *page)
        if (u & (1 << KPF_HUGE))
                u |= kpf_copy_bit(k, KPF_HWPOISON,      PG_hwpoison);
        else
-               u |= kpf_copy_bit(ps.page_snapshot.flags, KPF_HWPOISON, PG_hwpoison);
+               u |= kpf_copy_bit(ps.page_snapshot.flags.f, KPF_HWPOISON, PG_hwpoison);
 #endif
 
        u |= kpf_copy_bit(k, KPF_RESERVED,      PG_reserved);
index e75a6cec67bef9ac464d6411e15325ee73255034..ca41ce8208c461b3a509761c271fd8e41f87f337 100644 (file)
@@ -107,7 +107,7 @@ static int do_readpage(struct folio *folio)
        size_t offset = 0;
 
        dbg_gen("ino %lu, pg %lu, i_size %lld, flags %#lx",
-               inode->i_ino, folio->index, i_size, folio->flags);
+               inode->i_ino, folio->index, i_size, folio->flags.f);
        ubifs_assert(c, !folio_test_checked(folio));
        ubifs_assert(c, !folio->private);
 
@@ -600,7 +600,7 @@ static int populate_page(struct ubifs_info *c, struct folio *folio,
        pgoff_t end_index;
 
        dbg_gen("ino %lu, pg %lu, i_size %lld, flags %#lx",
-               inode->i_ino, folio->index, i_size, folio->flags);
+               inode->i_ino, folio->index, i_size, folio->flags.f);
 
        end_index = (i_size - 1) >> PAGE_SHIFT;
        if (!i_size || folio->index > end_index) {
@@ -988,7 +988,7 @@ static int ubifs_writepage(struct folio *folio, struct writeback_control *wbc)
        int err, len = folio_size(folio);
 
        dbg_gen("ino %lu, pg %lu, pg flags %#lx",
-               inode->i_ino, folio->index, folio->flags);
+               inode->i_ino, folio->index, folio->flags.f);
        ubifs_assert(c, folio->private != NULL);
 
        /* Is the folio fully outside @i_size? (truncate in progress) */
index b61e2d4858cffaed21729fc119cc3e66c207a2e8..da562f23f50ce3e08b20222c241d8fc97d8b0854 100644 (file)
@@ -1024,7 +1024,7 @@ static inline unsigned int compound_order(struct page *page)
 {
        struct folio *folio = (struct folio *)page;
 
-       if (!test_bit(PG_head, &folio->flags))
+       if (!test_bit(PG_head, &folio->flags.f))
                return 0;
        return folio_large_order(folio);
 }
@@ -1554,7 +1554,7 @@ static inline bool is_nommu_shared_mapping(vm_flags_t flags)
  */
 static inline int page_zone_id(struct page *page)
 {
-       return (page->flags >> ZONEID_PGSHIFT) & ZONEID_MASK;
+       return (page->flags.f >> ZONEID_PGSHIFT) & ZONEID_MASK;
 }
 
 #ifdef NODE_NOT_IN_PAGE_FLAGS
@@ -1562,7 +1562,7 @@ int page_to_nid(const struct page *page);
 #else
 static inline int page_to_nid(const struct page *page)
 {
-       return (PF_POISONED_CHECK(page)->flags >> NODES_PGSHIFT) & NODES_MASK;
+       return (PF_POISONED_CHECK(page)->flags.f >> NODES_PGSHIFT) & NODES_MASK;
 }
 #endif
 
@@ -1637,14 +1637,14 @@ static inline void page_cpupid_reset_last(struct page *page)
 #else
 static inline int folio_last_cpupid(struct folio *folio)
 {
-       return (folio->flags >> LAST_CPUPID_PGSHIFT) & LAST_CPUPID_MASK;
+       return (folio->flags.f >> LAST_CPUPID_PGSHIFT) & LAST_CPUPID_MASK;
 }
 
 int folio_xchg_last_cpupid(struct folio *folio, int cpupid);
 
 static inline void page_cpupid_reset_last(struct page *page)
 {
-       page->flags |= LAST_CPUPID_MASK << LAST_CPUPID_PGSHIFT;
+       page->flags.f |= LAST_CPUPID_MASK << LAST_CPUPID_PGSHIFT;
 }
 #endif /* LAST_CPUPID_NOT_IN_PAGE_FLAGS */
 
@@ -1740,7 +1740,7 @@ static inline u8 page_kasan_tag(const struct page *page)
        u8 tag = KASAN_TAG_KERNEL;
 
        if (kasan_enabled()) {
-               tag = (page->flags >> KASAN_TAG_PGSHIFT) & KASAN_TAG_MASK;
+               tag = (page->flags.f >> KASAN_TAG_PGSHIFT) & KASAN_TAG_MASK;
                tag ^= 0xff;
        }
 
@@ -1755,12 +1755,12 @@ static inline void page_kasan_tag_set(struct page *page, u8 tag)
                return;
 
        tag ^= 0xff;
-       old_flags = READ_ONCE(page->flags);
+       old_flags = READ_ONCE(page->flags.f);
        do {
                flags = old_flags;
                flags &= ~(KASAN_TAG_MASK << KASAN_TAG_PGSHIFT);
                flags |= (tag & KASAN_TAG_MASK) << KASAN_TAG_PGSHIFT;
-       } while (unlikely(!try_cmpxchg(&page->flags, &old_flags, flags)));
+       } while (unlikely(!try_cmpxchg(&page->flags.f, &old_flags, flags)));
 }
 
 static inline void page_kasan_tag_reset(struct page *page)
@@ -1804,13 +1804,13 @@ static inline pg_data_t *folio_pgdat(const struct folio *folio)
 #ifdef SECTION_IN_PAGE_FLAGS
 static inline void set_page_section(struct page *page, unsigned long section)
 {
-       page->flags &= ~(SECTIONS_MASK << SECTIONS_PGSHIFT);
-       page->flags |= (section & SECTIONS_MASK) << SECTIONS_PGSHIFT;
+       page->flags.f &= ~(SECTIONS_MASK << SECTIONS_PGSHIFT);
+       page->flags.f |= (section & SECTIONS_MASK) << SECTIONS_PGSHIFT;
 }
 
 static inline unsigned long page_to_section(const struct page *page)
 {
-       return (page->flags >> SECTIONS_PGSHIFT) & SECTIONS_MASK;
+       return (page->flags.f >> SECTIONS_PGSHIFT) & SECTIONS_MASK;
 }
 #endif
 
@@ -2015,14 +2015,14 @@ static inline bool folio_is_longterm_pinnable(struct folio *folio)
 
 static inline void set_page_zone(struct page *page, enum zone_type zone)
 {
-       page->flags &= ~(ZONES_MASK << ZONES_PGSHIFT);
-       page->flags |= (zone & ZONES_MASK) << ZONES_PGSHIFT;
+       page->flags.f &= ~(ZONES_MASK << ZONES_PGSHIFT);
+       page->flags.f |= (zone & ZONES_MASK) << ZONES_PGSHIFT;
 }
 
 static inline void set_page_node(struct page *page, unsigned long node)
 {
-       page->flags &= ~(NODES_MASK << NODES_PGSHIFT);
-       page->flags |= (node & NODES_MASK) << NODES_PGSHIFT;
+       page->flags.f &= ~(NODES_MASK << NODES_PGSHIFT);
+       page->flags.f |= (node & NODES_MASK) << NODES_PGSHIFT;
 }
 
 static inline void set_page_links(struct page *page, enum zone_type zone,
@@ -2064,7 +2064,7 @@ static inline long compound_nr(struct page *page)
 {
        struct folio *folio = (struct folio *)page;
 
-       if (!test_bit(PG_head, &folio->flags))
+       if (!test_bit(PG_head, &folio->flags.f))
                return 1;
        return folio_large_nr_pages(folio);
 }
index 89b518ff097e6bbd720a76f88adb94421c571cae..150302b4a9050f227553e261f8853cc342a06312 100644 (file)
@@ -143,7 +143,7 @@ static inline int lru_tier_from_refs(int refs, bool workingset)
 
 static inline int folio_lru_refs(struct folio *folio)
 {
-       unsigned long flags = READ_ONCE(folio->flags);
+       unsigned long flags = READ_ONCE(folio->flags.f);
 
        if (!(flags & BIT(PG_referenced)))
                return 0;
@@ -156,7 +156,7 @@ static inline int folio_lru_refs(struct folio *folio)
 
 static inline int folio_lru_gen(struct folio *folio)
 {
-       unsigned long flags = READ_ONCE(folio->flags);
+       unsigned long flags = READ_ONCE(folio->flags.f);
 
        return ((flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1;
 }
@@ -268,7 +268,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, LRU_GEN_MASK | BIT(PG_active), flags);
+       set_mask_bits(&folio->flags.f, LRU_GEN_MASK | BIT(PG_active), flags);
 
        lru_gen_update_size(lruvec, folio, -1, gen);
        /* for folio_rotate_reclaimable() */
@@ -293,7 +293,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, LRU_GEN_MASK, flags);
+       flags = set_mask_bits(&folio->flags.f, LRU_GEN_MASK, flags);
        gen = ((flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1;
 
        lru_gen_update_size(lruvec, folio, gen, -1);
@@ -304,9 +304,9 @@ static inline bool lru_gen_del_folio(struct lruvec *lruvec, struct folio *folio,
 
 static inline void folio_migrate_refs(struct folio *new, struct folio *old)
 {
-       unsigned long refs = READ_ONCE(old->flags) & LRU_REFS_MASK;
+       unsigned long refs = READ_ONCE(old->flags.f) & LRU_REFS_MASK;
 
-       set_mask_bits(&new->flags, LRU_REFS_MASK, refs);
+       set_mask_bits(&new->flags.f, LRU_REFS_MASK, refs);
 }
 #else /* !CONFIG_LRU_GEN */
 
index d247da2fdb52adcfa3576a251407ce237a4d34aa..d934a3a5b443e6492c90e90644ae983cc8e5a0aa 100644 (file)
@@ -34,6 +34,10 @@ struct address_space;
 struct futex_private_hash;
 struct mem_cgroup;
 
+typedef struct {
+       unsigned long f;
+} memdesc_flags_t;
+
 /*
  * Each physical page in the system has a struct page associated with
  * it to keep track of whatever it is we are using the page for at the
@@ -72,7 +76,7 @@ struct mem_cgroup;
 #endif
 
 struct page {
-       unsigned long flags;            /* Atomic flags, some possibly
+       memdesc_flags_t flags;          /* Atomic flags, some possibly
                                         * updated asynchronously */
        /*
         * Five words (20/40 bytes) are available in this union.
@@ -383,7 +387,7 @@ struct folio {
        union {
                struct {
        /* public: */
-                       unsigned long flags;
+                       memdesc_flags_t flags;
                        union {
                                struct list_head lru;
        /* private: avoid cluttering the output */
index 9d3ea9085556f7e7c3c0e97d75d6b3d627c79776..990560cd99ee2381df8b7a301349c58d0f025c2f 100644 (file)
@@ -1186,7 +1186,7 @@ static inline bool zone_is_empty(struct zone *zone)
 static inline enum zone_type page_zonenum(const struct page *page)
 {
        ASSERT_EXCLUSIVE_BITS(page->flags, ZONES_MASK << ZONES_PGSHIFT);
-       return (page->flags >> ZONES_PGSHIFT) & ZONES_MASK;
+       return (page->flags.f >> ZONES_PGSHIFT) & ZONES_MASK;
 }
 
 static inline enum zone_type folio_zonenum(const struct folio *folio)
index 8d3fa3a91ce4739efebac7f61b9d306ca92062f6..d53a86e68c89b2f4fc35b3a9ad8e0ac0a90242cb 100644 (file)
@@ -217,7 +217,7 @@ static __always_inline const struct page *page_fixed_fake_head(const struct page
         * cold cacheline in some cases.
         */
        if (IS_ALIGNED((unsigned long)page, PAGE_SIZE) &&
-           test_bit(PG_head, &page->flags)) {
+           test_bit(PG_head, &page->flags.f)) {
                /*
                 * We can safely access the field of the @page[1] with PG_head
                 * because the @page is a compound page composed with at least
@@ -325,14 +325,14 @@ static __always_inline int PageTail(const struct page *page)
 
 static __always_inline int PageCompound(const struct page *page)
 {
-       return test_bit(PG_head, &page->flags) ||
+       return test_bit(PG_head, &page->flags.f) ||
               READ_ONCE(page->compound_head) & 1;
 }
 
 #define        PAGE_POISON_PATTERN     -1l
 static inline int PagePoisoned(const struct page *page)
 {
-       return READ_ONCE(page->flags) == PAGE_POISON_PATTERN;
+       return READ_ONCE(page->flags.f) == PAGE_POISON_PATTERN;
 }
 
 #ifdef CONFIG_DEBUG_VM
@@ -349,8 +349,8 @@ static const unsigned long *const_folio_flags(const struct folio *folio,
        const struct page *page = &folio->page;
 
        VM_BUG_ON_PGFLAGS(page->compound_head & 1, page);
-       VM_BUG_ON_PGFLAGS(n > 0 && !test_bit(PG_head, &page->flags), page);
-       return &page[n].flags;
+       VM_BUG_ON_PGFLAGS(n > 0 && !test_bit(PG_head, &page->flags.f), page);
+       return &page[n].flags.f;
 }
 
 static unsigned long *folio_flags(struct folio *folio, unsigned n)
@@ -358,8 +358,8 @@ static unsigned long *folio_flags(struct folio *folio, unsigned n)
        struct page *page = &folio->page;
 
        VM_BUG_ON_PGFLAGS(page->compound_head & 1, page);
-       VM_BUG_ON_PGFLAGS(n > 0 && !test_bit(PG_head, &page->flags), page);
-       return &page[n].flags;
+       VM_BUG_ON_PGFLAGS(n > 0 && !test_bit(PG_head, &page->flags.f), page);
+       return &page[n].flags.f;
 }
 
 /*
@@ -449,37 +449,37 @@ FOLIO_CLEAR_FLAG(name, page)
 #define TESTPAGEFLAG(uname, lname, policy)                             \
 FOLIO_TEST_FLAG(lname, FOLIO_##policy)                                 \
 static __always_inline int Page##uname(const struct page *page)                \
-{ return test_bit(PG_##lname, &policy(page, 0)->flags); }
+{ return test_bit(PG_##lname, &policy(page, 0)->flags.f); }
 
 #define SETPAGEFLAG(uname, lname, policy)                              \
 FOLIO_SET_FLAG(lname, FOLIO_##policy)                                  \
 static __always_inline void SetPage##uname(struct page *page)          \
-{ set_bit(PG_##lname, &policy(page, 1)->flags); }
+{ set_bit(PG_##lname, &policy(page, 1)->flags.f); }
 
 #define CLEARPAGEFLAG(uname, lname, policy)                            \
 FOLIO_CLEAR_FLAG(lname, FOLIO_##policy)                                        \
 static __always_inline void ClearPage##uname(struct page *page)                \
-{ clear_bit(PG_##lname, &policy(page, 1)->flags); }
+{ clear_bit(PG_##lname, &policy(page, 1)->flags.f); }
 
 #define __SETPAGEFLAG(uname, lname, policy)                            \
 __FOLIO_SET_FLAG(lname, FOLIO_##policy)                                        \
 static __always_inline void __SetPage##uname(struct page *page)                \
-{ __set_bit(PG_##lname, &policy(page, 1)->flags); }
+{ __set_bit(PG_##lname, &policy(page, 1)->flags.f); }
 
 #define __CLEARPAGEFLAG(uname, lname, policy)                          \
 __FOLIO_CLEAR_FLAG(lname, FOLIO_##policy)                              \
 static __always_inline void __ClearPage##uname(struct page *page)      \
-{ __clear_bit(PG_##lname, &policy(page, 1)->flags); }
+{ __clear_bit(PG_##lname, &policy(page, 1)->flags.f); }
 
 #define TESTSETFLAG(uname, lname, policy)                              \
 FOLIO_TEST_SET_FLAG(lname, FOLIO_##policy)                             \
 static __always_inline int TestSetPage##uname(struct page *page)       \
-{ return test_and_set_bit(PG_##lname, &policy(page, 1)->flags); }
+{ return test_and_set_bit(PG_##lname, &policy(page, 1)->flags.f); }
 
 #define TESTCLEARFLAG(uname, lname, policy)                            \
 FOLIO_TEST_CLEAR_FLAG(lname, FOLIO_##policy)                           \
 static __always_inline int TestClearPage##uname(struct page *page)     \
-{ return test_and_clear_bit(PG_##lname, &policy(page, 1)->flags); }
+{ return test_and_clear_bit(PG_##lname, &policy(page, 1)->flags.f); }
 
 #define PAGEFLAG(uname, lname, policy)                                 \
        TESTPAGEFLAG(uname, lname, policy)                              \
@@ -846,7 +846,7 @@ static __always_inline bool folio_test_head(const struct folio *folio)
 static __always_inline int PageHead(const struct page *page)
 {
        PF_POISONED_CHECK(page);
-       return test_bit(PG_head, &page->flags) && !page_is_fake_head(page);
+       return test_bit(PG_head, &page->flags.f) && !page_is_fake_head(page);
 }
 
 __SETPAGEFLAG(Head, head, PF_ANY)
@@ -1170,28 +1170,28 @@ static __always_inline int PageAnonExclusive(const struct page *page)
         */
        if (PageHuge(page))
                page = compound_head(page);
-       return test_bit(PG_anon_exclusive, &PF_ANY(page, 1)->flags);
+       return test_bit(PG_anon_exclusive, &PF_ANY(page, 1)->flags.f);
 }
 
 static __always_inline void SetPageAnonExclusive(struct page *page)
 {
        VM_BUG_ON_PGFLAGS(!PageAnonNotKsm(page), page);
        VM_BUG_ON_PGFLAGS(PageHuge(page) && !PageHead(page), page);
-       set_bit(PG_anon_exclusive, &PF_ANY(page, 1)->flags);
+       set_bit(PG_anon_exclusive, &PF_ANY(page, 1)->flags.f);
 }
 
 static __always_inline void ClearPageAnonExclusive(struct page *page)
 {
        VM_BUG_ON_PGFLAGS(!PageAnonNotKsm(page), page);
        VM_BUG_ON_PGFLAGS(PageHuge(page) && !PageHead(page), page);
-       clear_bit(PG_anon_exclusive, &PF_ANY(page, 1)->flags);
+       clear_bit(PG_anon_exclusive, &PF_ANY(page, 1)->flags.f);
 }
 
 static __always_inline void __ClearPageAnonExclusive(struct page *page)
 {
        VM_BUG_ON_PGFLAGS(!PageAnon(page), page);
        VM_BUG_ON_PGFLAGS(PageHuge(page) && !PageHead(page), page);
-       __clear_bit(PG_anon_exclusive, &PF_ANY(page, 1)->flags);
+       __clear_bit(PG_anon_exclusive, &PF_ANY(page, 1)->flags.f);
 }
 
 #ifdef CONFIG_MMU
@@ -1241,7 +1241,7 @@ static __always_inline void __ClearPageAnonExclusive(struct page *page)
  */
 static inline int folio_has_private(const struct folio *folio)
 {
-       return !!(folio->flags & PAGE_FLAGS_PRIVATE);
+       return !!(folio->flags.f & PAGE_FLAGS_PRIVATE);
 }
 
 #undef PF_ANY
index 8a7f4f802c5748c6f4315083070030069e27307d..38a82d65e58e9679b57321142bc33ee84edd786b 100644 (file)
@@ -107,7 +107,8 @@ static inline bool get_page_tag_ref(struct page *page, union codetag_ref *ref,
        if (static_key_enabled(&mem_profiling_compressed)) {
                pgalloc_tag_idx idx;
 
-               idx = (page->flags >> alloc_tag_ref_offs) & alloc_tag_ref_mask;
+               idx = (page->flags.f >> alloc_tag_ref_offs) &
+                       alloc_tag_ref_mask;
                idx_to_ref(idx, ref);
                handle->page = page;
        } else {
@@ -149,11 +150,11 @@ static inline void update_page_tag_ref(union pgtag_ref_handle handle, union code
                idx = (unsigned long)ref_to_idx(ref);
                idx = (idx & alloc_tag_ref_mask) << alloc_tag_ref_offs;
                do {
-                       old_flags = READ_ONCE(page->flags);
+                       old_flags = READ_ONCE(page->flags.f);
                        flags = old_flags;
                        flags &= ~(alloc_tag_ref_mask << alloc_tag_ref_offs);
                        flags |= idx;
-               } while (unlikely(!try_cmpxchg(&page->flags, &old_flags, flags)));
+               } while (unlikely(!try_cmpxchg(&page->flags.f, &old_flags, flags)));
        } else {
                if (WARN_ON(!handle.ref || !ref))
                        return;
index fe33a255b7d093aa46b7b0e3cd301475d298275e..ea6b5c4baf3d599d0c906cae13c0eb4ae6a4d375 100644 (file)
@@ -28,7 +28,7 @@ DECLARE_EVENT_CLASS(page_ref_mod_template,
 
        TP_fast_assign(
                __entry->pfn = page_to_pfn(page);
-               __entry->flags = page->flags;
+               __entry->flags = page->flags.f;
                __entry->count = page_ref_count(page);
                __entry->mapcount = atomic_read(&page->_mapcount);
                __entry->mapping = page->mapping;
@@ -77,7 +77,7 @@ DECLARE_EVENT_CLASS(page_ref_mod_and_test_template,
 
        TP_fast_assign(
                __entry->pfn = page_to_pfn(page);
-               __entry->flags = page->flags;
+               __entry->flags = page->flags.f;
                __entry->count = page_ref_count(page);
                __entry->mapcount = atomic_read(&page->_mapcount);
                __entry->mapping = page->mapping;
index 1a388b11cfa93de2bb40a1ac04bf64f47ef750a3..f3a6c24897f4ac3198432421c55a65438b5b5d5f 100644 (file)
@@ -1140,10 +1140,10 @@ static int wake_page_function(wait_queue_entry_t *wait, unsigned mode, int sync,
         */
        flags = wait->flags;
        if (flags & WQ_FLAG_EXCLUSIVE) {
-               if (test_bit(key->bit_nr, &key->folio->flags))
+               if (test_bit(key->bit_nr, &key->folio->flags.f))
                        return -1;
                if (flags & WQ_FLAG_CUSTOM) {
-                       if (test_and_set_bit(key->bit_nr, &key->folio->flags))
+                       if (test_and_set_bit(key->bit_nr, &key->folio->flags.f))
                                return -1;
                        flags |= WQ_FLAG_DONE;
                }
@@ -1226,9 +1226,9 @@ static inline bool folio_trylock_flag(struct folio *folio, int bit_nr,
                                        struct wait_queue_entry *wait)
 {
        if (wait->flags & WQ_FLAG_EXCLUSIVE) {
-               if (test_and_set_bit(bit_nr, &folio->flags))
+               if (test_and_set_bit(bit_nr, &folio->flags.f))
                        return false;
-       } else if (test_bit(bit_nr, &folio->flags))
+       } else if (test_bit(bit_nr, &folio->flags.f))
                return false;
 
        wait->flags |= WQ_FLAG_WOKEN | WQ_FLAG_DONE;
index d89992b65acc982909ea9af07ce1c1655fb3662f..aac5f0a2cb54043f820f28ad493905ed98bca5b0 100644 (file)
@@ -3303,8 +3303,8 @@ static void __split_folio_to_order(struct folio *folio, int old_order,
                 * unreferenced sub-pages of an anonymous THP: we can simply drop
                 * PG_anon_exclusive (-> PG_mappedtodisk) for these here.
                 */
-               new_folio->flags &= ~PAGE_FLAGS_CHECK_AT_PREP;
-               new_folio->flags |= (folio->flags &
+               new_folio->flags.f &= ~PAGE_FLAGS_CHECK_AT_PREP;
+               new_folio->flags.f |= (folio->flags.f &
                                ((1L << PG_referenced) |
                                 (1L << PG_swapbacked) |
                                 (1L << PG_swapcache) |
index df6ee59527ddf5b9918ab9e4319a2f40b4bbe777..b93ab99ad3ef9336f6c88fe52cd701b201283f96 100644 (file)
@@ -1708,10 +1708,10 @@ static int identify_page_state(unsigned long pfn, struct page *p,
         * carried out only if the first check can't determine the page status.
         */
        for (ps = error_states;; ps++)
-               if ((p->flags & ps->mask) == ps->res)
+               if ((p->flags.f & ps->mask) == ps->res)
                        break;
 
-       page_flags |= (p->flags & (1UL << PG_dirty));
+       page_flags |= (p->flags.f & (1UL << PG_dirty));
 
        if (!ps->mask)
                for (ps = error_states;; ps++)
@@ -2137,7 +2137,7 @@ retry:
                return action_result(pfn, MF_MSG_FREE_HUGE, res);
        }
 
-       page_flags = folio->flags;
+       page_flags = folio->flags.f;
 
        if (!hwpoison_user_mappings(folio, p, pfn, flags)) {
                folio_unlock(folio);
@@ -2397,7 +2397,7 @@ try_again:
         * folio_remove_rmap_*() in try_to_unmap_one(). So to determine page
         * status correctly, we save a copy of the page flags at this time.
         */
-       page_flags = folio->flags;
+       page_flags = folio->flags.f;
 
        /*
         * __munlock_folio() may clear a writeback folio's LRU flag without
@@ -2742,13 +2742,13 @@ static int soft_offline_in_use_page(struct page *page)
                                putback_movable_pages(&pagelist);
 
                        pr_info("%#lx: %s migration failed %ld, type %pGp\n",
-                               pfn, msg_page[huge], ret, &page->flags);
+                               pfn, msg_page[huge], ret, &page->flags.f);
                        if (ret > 0)
                                ret = -EBUSY;
                }
        } else {
                pr_info("%#lx: %s isolation failed, page count %d, type %pGp\n",
-                       pfn, msg_page[huge], page_count(page), &page->flags);
+                       pfn, msg_page[huge], page_count(page), &page->flags.f);
                ret = -EBUSY;
        }
        return ret;
index f9baa8882fbf30eacfaf40fb071e3dffaf07e277..0c8f181d9d50068b3a2359805bd81791b97c5bf0 100644 (file)
@@ -99,14 +99,14 @@ int folio_xchg_last_cpupid(struct folio *folio, int cpupid)
        unsigned long old_flags, flags;
        int last_cpupid;
 
-       old_flags = READ_ONCE(folio->flags);
+       old_flags = READ_ONCE(folio->flags.f);
        do {
                flags = old_flags;
                last_cpupid = (flags >> LAST_CPUPID_PGSHIFT) & LAST_CPUPID_MASK;
 
                flags &= ~(LAST_CPUPID_MASK << LAST_CPUPID_PGSHIFT);
                flags |= (cpupid & LAST_CPUPID_MASK) << LAST_CPUPID_PGSHIFT;
-       } while (unlikely(!try_cmpxchg(&folio->flags, &old_flags, flags)));
+       } while (unlikely(!try_cmpxchg(&folio->flags.f, &old_flags, flags)));
 
        return last_cpupid;
 }
index 2ee21e46f0fb4badaa824914b56cf9086afdbfdf..ca9e6b9633f79ff28448a6008749fa6ca2696332 100644 (file)
@@ -950,7 +950,7 @@ static inline void __free_one_page(struct page *page,
        bool to_tail;
 
        VM_BUG_ON(!zone_is_initialized(zone));
-       VM_BUG_ON_PAGE(page->flags & PAGE_FLAGS_CHECK_AT_PREP, page);
+       VM_BUG_ON_PAGE(page->flags.f & PAGE_FLAGS_CHECK_AT_PREP, page);
 
        VM_BUG_ON(migratetype == -1);
        VM_BUG_ON_PAGE(pfn & ((1 << order) - 1), page);
@@ -1043,7 +1043,7 @@ static inline bool page_expected_state(struct page *page,
                        page->memcg_data |
 #endif
                        page_pool_page_is_pp(page) |
-                       (page->flags & check_flags)))
+                       (page->flags.f & check_flags)))
                return false;
 
        return true;
@@ -1059,7 +1059,7 @@ static const char *page_bad_reason(struct page *page, unsigned long flags)
                bad_reason = "non-NULL mapping";
        if (unlikely(page_ref_count(page) != 0))
                bad_reason = "nonzero _refcount";
-       if (unlikely(page->flags & flags)) {
+       if (unlikely(page->flags.f & flags)) {
                if (flags == PAGE_FLAGS_CHECK_AT_PREP)
                        bad_reason = "PAGE_FLAGS_CHECK_AT_PREP flag(s) set";
                else
@@ -1358,7 +1358,7 @@ __always_inline bool free_pages_prepare(struct page *page,
                int i;
 
                if (compound) {
-                       page[1].flags &= ~PAGE_FLAGS_SECOND;
+                       page[1].flags.f &= ~PAGE_FLAGS_SECOND;
 #ifdef NR_PAGES_IN_LARGE_FOLIO
                        folio->_nr_pages = 0;
 #endif
@@ -1372,7 +1372,7 @@ __always_inline bool free_pages_prepare(struct page *page,
                                        continue;
                                }
                        }
-                       (page + i)->flags &= ~PAGE_FLAGS_CHECK_AT_PREP;
+                       (page + i)->flags.f &= ~PAGE_FLAGS_CHECK_AT_PREP;
                }
        }
        if (folio_test_anon(folio)) {
@@ -1391,7 +1391,7 @@ __always_inline bool free_pages_prepare(struct page *page,
        }
 
        page_cpupid_reset_last(page);
-       page->flags &= ~PAGE_FLAGS_CHECK_AT_PREP;
+       page->flags.f &= ~PAGE_FLAGS_CHECK_AT_PREP;
        reset_page_owner(page, order);
        page_table_check_free(page, order);
        pgalloc_tag_sub(page, 1 << order);
index 60e7b509807b85b1703b87e821ce2c0c7f59c336..2260dcd2775e7514682d8f71296ac8ebc800d5bf 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -388,14 +388,14 @@ 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);
+       unsigned long new_flags, old_flags = READ_ONCE(folio->flags.f);
 
        if (folio_test_unevictable(folio))
                return;
 
        /* see the comment on LRU_REFS_FLAGS */
        if (!folio_test_referenced(folio)) {
-               set_mask_bits(&folio->flags, LRU_REFS_MASK, BIT(PG_referenced));
+               set_mask_bits(&folio->flags.f, LRU_REFS_MASK, BIT(PG_referenced));
                return;
        }
 
@@ -407,7 +407,7 @@ static void lru_gen_inc_refs(struct folio *folio)
                }
 
                new_flags = old_flags + BIT(LRU_REFS_PGOFF);
-       } while (!try_cmpxchg(&folio->flags, &old_flags, new_flags));
+       } while (!try_cmpxchg(&folio->flags.f, &old_flags, new_flags));
 }
 
 static bool lru_gen_clear_refs(struct folio *folio)
@@ -419,7 +419,7 @@ static bool lru_gen_clear_refs(struct folio *folio)
        if (gen < 0)
                return true;
 
-       set_mask_bits(&folio->flags, LRU_REFS_FLAGS | BIT(PG_workingset), 0);
+       set_mask_bits(&folio->flags.f, LRU_REFS_FLAGS | BIT(PG_workingset), 0);
 
        lrugen = &folio_lruvec(folio)->lrugen;
        /* whether can do without shuffling under the LRU lock */
index 4025e614e59e4e82d1e36765f0fb2fc1c4220baa..0f489976fa2be1cdee6462c73643f3a0d575455a 100644 (file)
@@ -888,11 +888,11 @@ static bool lru_gen_set_refs(struct folio *folio)
 {
        /* see the comment on LRU_REFS_FLAGS */
        if (!folio_test_referenced(folio) && !folio_test_workingset(folio)) {
-               set_mask_bits(&folio->flags, LRU_REFS_MASK, BIT(PG_referenced));
+               set_mask_bits(&folio->flags.f, LRU_REFS_MASK, BIT(PG_referenced));
                return false;
        }
 
-       set_mask_bits(&folio->flags, LRU_REFS_FLAGS, BIT(PG_workingset));
+       set_mask_bits(&folio->flags.f, LRU_REFS_FLAGS, BIT(PG_workingset));
        return true;
 }
 #else
@@ -3257,13 +3257,13 @@ 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)
 {
-       unsigned long new_flags, old_flags = READ_ONCE(folio->flags);
+       unsigned long new_flags, old_flags = READ_ONCE(folio->flags.f);
 
        VM_WARN_ON_ONCE(gen >= MAX_NR_GENS);
 
        /* see the comment on LRU_REFS_FLAGS */
        if (!folio_test_referenced(folio) && !folio_test_workingset(folio)) {
-               set_mask_bits(&folio->flags, LRU_REFS_MASK, BIT(PG_referenced));
+               set_mask_bits(&folio->flags.f, LRU_REFS_MASK, BIT(PG_referenced));
                return -1;
        }
 
@@ -3274,7 +3274,7 @@ static int folio_update_gen(struct folio *folio, int gen)
 
                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, &old_flags, new_flags));
+       } while (!try_cmpxchg(&folio->flags.f, &old_flags, new_flags));
 
        return ((old_flags & LRU_GEN_MASK) >> LRU_GEN_PGOFF) - 1;
 }
@@ -3285,7 +3285,7 @@ static int folio_inc_gen(struct lruvec *lruvec, struct folio *folio, bool reclai
        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);
+       unsigned long new_flags, old_flags = READ_ONCE(folio->flags.f);
 
        VM_WARN_ON_ONCE_FOLIO(!(old_flags & LRU_GEN_MASK), folio);
 
@@ -3302,7 +3302,7 @@ static int folio_inc_gen(struct lruvec *lruvec, struct folio *folio, bool reclai
                /* for folio_end_writeback() */
                if (reclaiming)
                        new_flags |= BIT(PG_reclaim);
-       } while (!try_cmpxchg(&folio->flags, &old_flags, new_flags));
+       } while (!try_cmpxchg(&folio->flags.f, &old_flags, new_flags));
 
        lru_gen_update_size(lruvec, folio, old_gen, new_gen);
 
@@ -4553,7 +4553,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, LRU_REFS_MASK, 0);
+               set_mask_bits(&folio->flags.f, LRU_REFS_MASK, 0);
 
        /* for shrink_folio_list() */
        folio_clear_reclaim(folio);
@@ -4766,7 +4766,7 @@ retry:
 
                /* 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, LRU_REFS_FLAGS, BIT(PG_active));
+                       set_mask_bits(&folio->flags.f, LRU_REFS_FLAGS, BIT(PG_active));
        }
 
        spin_lock_irq(&lruvec->lru_lock);
index 6e7f4cb1b9a7807e9288955f180a5b6cffab1a40..68a76a91111f4f649a5c1c70c1392a622f218a63 100644 (file)
@@ -318,7 +318,7 @@ static void lru_gen_refault(struct folio *folio, void *shadow)
                folio_set_workingset(folio);
                mod_lruvec_state(lruvec, WORKINGSET_RESTORE_BASE + type, delta);
        } else
-               set_mask_bits(&folio->flags, LRU_REFS_MASK, (refs - 1UL) << LRU_REFS_PGOFF);
+               set_mask_bits(&folio->flags.f, LRU_REFS_MASK, (refs - 1UL) << LRU_REFS_PGOFF);
 unlock:
        rcu_read_unlock();
 }