STRUCT FOLIO(9)
π struct folio(9) π
okay so bestie, we're in the Kernel API Manual today and we're talking about struct folio β yes the big one, the main character of memory management, and I promise by the end of this you're gonna be obsessed. π«Ά
β¨ NAME β¨
struct folio β Represents a contiguous set of bytes.
like literally what it says on the tin. a contiguous set of bytes. that's her. that's the whole vibe. π
πΈ SYNOPSIS πΈ
struct folio {
memdesc_flags_t flags;
union {
struct list_head lru;
unsigned int mlock_count;
struct dev_pagemap *pgmap;
};
struct address_space *mapping;
union {
pgoff_t index;
unsigned long share;
};
union {
void *private;
swp_entry_t swap;
unsigned long migrate_info;
};
atomic_t _mapcount;
atomic_t _refcount;
#ifdef CONFIG_MEMCG;
unsigned long memcg_data;
#elif defined(CONFIG_SLAB_OBJ_EXT);
unsigned long _unused_slab_obj_exts;
#endif;
#if defined(WANT_PAGE_VIRTUAL);
void *virtual;
#endif;
#ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS;
int _last_cpupid;
#endif;
atomic_t _large_mapcount;
atomic_t _nr_pages_mapped;
#ifdef CONFIG_64BIT;
atomic_t _entire_mapcount;
atomic_t _pincount;
#endif ;
mm_id_mapcount_t _mm_id_mapcount[2];
union {
mm_id_t _mm_id[2];
unsigned long _mm_ids;
};
#ifdef NR_PAGES_IN_LARGE_FOLIO;
unsigned int _nr_pages;
#endif ;
struct list_head _deferred_list;
#ifndef CONFIG_64BIT;
atomic_t _entire_mapcount;
atomic_t _pincount;
#endif ;
void *_hugetlb_subpool;
void *_hugetlb_cgroup;
void *_hugetlb_cgroup_rsvd;
void *_hugetlb_hwpoison;
};
ngl the preprocessor conditionals are giving "two different outfits depending on the CONFIG_ vibe check" and honestly? we respect the versatility. π
π Members π
here's the member-by-member tour, bestie. every single one, no skips, i would never π
flagsβ Identical to the page flags.{unnamed_union}β anonymouslruβ Least Recently Used list; tracks how recently this folio was used.mlock_countβ Number of times this folio has been pinned by mlock.pgmapβ Metadata forZONE_DEVICEmappingsmappingβ The file this page belongs to, or refers to theanon_vmafor anonymous memory.{unnamed_union}β anonymousindexβ Offset within the file, in units of pages. For anonymous memory, this is the index from the beginning of the mmap.shareβ number of DAX mappings that reference this folio. Seedax_associate_entry.{unnamed_union}β anonymousprivateβ Filesystem per-folio data (seefolio_attach_private).swapβ Used forswp_entry_tiffolio_test_swapcache.migrate_infoβ Stores migration state (anon_vmapointer andFOLIO_WAS_*markers)._mapcountβ Do not access this member directly. Usefolio_mapcountto find out how many times this folio is mapped by userspace._refcountβ Do not access this member directly. Usefolio_ref_countto find how many references there are to this folio.memcg_dataβ Memory Control Group data._unused_slab_obj_extsβ Placeholder to matchobj_extsinstruct slab.virtualβ Virtual address in the kernel direct map._last_cpupidβ IDs of last CPU and last process that accessed the folio._large_mapcountβ Do not use directly, callfolio_mapcount._nr_pages_mappedβ Do not use outside of rmap and debug code._entire_mapcountβ Do not use directly, callfolio_entire_mapcount._pincountβ Do not use directly, callfolio_maybe_dma_pinned._mm_id_mapcountβ Do not use outside of rmap code.{unnamed_union}β anonymous_mm_idβ Do not use outside of rmap code._mm_idsβ Do not use outside of rmap code._nr_pagesβ Do not use directly, callfolio_nr_pages._deferred_listβ Folios to be split under memory pressure._entire_mapcountβ Do not use directly, callfolio_entire_mapcount._pincountβ Do not use directly, callfolio_maybe_dma_pinned._hugetlb_subpoolβ Do not use directly, use accessor inhugetlb.h._hugetlb_cgroupβ Do not use directly, use accessor inhugetlb_cgroup.h._hugetlb_cgroup_rsvdβ Do not use directly, use accessor inhugetlb_cgroup.h._hugetlb_hwpoisonβ Do not use directly, callraw_hwp_list_head.
β οΈ okay real talk bestie β see how many of these say "do not access directly" / "do not use directly" / "do not use outside of rmap code"? that is NOT a suggestion. those fields are private. you use the accessor function, every time, no exceptions, i'm literally begging. the kernel will not be nice about it and neither will the debugging session. π
also yes, _entire_mapcount and _pincount show up twice in that list β once for the CONFIG_64BIT branch, once for the #ifndef CONFIG_64BIT branch. only one of them is ever actually compiled in. it's giving "same fit, different season" π
π Description π
A folio is a physically, virtually and logically contiguous set of bytes. It is a power-of-two in size, and it is aligned to that same power-of-two. It is at least as large as PAGE_SIZE. If it is in the page cache, it is at a file offset which is a multiple of that power-of-two. It may be mapped into userspace at an address which is an arbitrary page offset, but its kernel virtual address is aligned to its size.
okay so let me translate: power-of-two size, aligned to that same power-of-two, never smaller than PAGE_SIZE β the whole thing is so consistent, it's giving main character energy fr fr β¨
π¦ SEE ALSO π¦
- Kernel file
./include/linux/mm_types.h softleaf_t(9)struct ptdesc(9)vm_fault_t(9)enum vm_fault_reason(9)enum fault_flag(9)
and that's the page!! you ate that, bestie, go read mm_types.h and slay π
π sign-off: this little masterpiece lives in ./include/linux and it's dated October 2026 β yes, we're being that specific. mwah. ππΈ
π¦ where this page comes from
- nixpkgs unstable: linux-manual 7.3.1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms