__folio_alloc_noprof()是__alloc_pages_noprof()的folio 版本封装。它的核心作用是将伙伴系统返回的struct page *转换为struct folio *,并在必要时执行 THP(透明大页)相关的准备工作。
核心作用与背景
struct folio是 Linux 内存管理引入的新抽象,用于明确表示“一个完整的(可能复合的)页”,替代过去模糊的struct page语义。__folio_alloc_noprof()为需要以 folio 粒度操作内存的调用方提供分配接口。
核心实现
struct folio *__folio_alloc_noprof(gfp_t gfp, unsigned int order, int preferred_nid, nodemask_t *nodemask) { struct page *page; page = __alloc_pages_noprof(gfp | __GFP_COMP, order, preferred_nid, nodemask); if (page && order > 1) prep_transhuge_page(page); return (struct folio *)page; }关键步骤:
强制
__GFP_COMP:传入gfp | __GFP_COMP,确保分配出的页块被初始化为复合页(compound page)。这是 folio 语义的前提——folio 必须有一个明确的 head page 来承载整个页块的元数据。委托
__alloc_pages_noprof():实际的物理内存分配完全交给页面分配器主入口。THP 准备(
order > 1):当分配阶数大于 1 时,调用prep_transhuge_page()进行透明大页的初始化。order == 1(两页的 folio)跳过此步骤,因为 deferred list 需要存储在第二个尾页中,而两页 folio 没有足够的尾页空间。类型转换返回:将
struct page *直接强制转换为struct folio *。在当前实现中,struct folio与struct page是联合体关系,指向首页的指针可以安全地互相转换。
在调用链中的位置
folio_alloc(gfp, order) // 上层宏 └── __folio_alloc_noprof(gfp, order, numa_node_id(), NULL) // ← 这里 ├── __alloc_pages_noprof(gfp | __GFP_COMP, order, ...) // 物理分配 └── prep_transhuge_page(page) // order > 1 时的 THP 准备
总结
__folio_alloc_noprof()是 folio 分配路径的核心实现:它通过__alloc_pages_noprof()获取复合页,对order > 1的分配执行prep_transhuge_page()完成 THP 初始化,最后将首页指针转换为struct folio *返回。__GFP_COMP的强制添加保证了 folio 语义所依赖的复合页结构。