ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

page_aolloc get_pfnblock_bit

page_aolloc get_pfnblock_bit 检查某个 pageblock 的单个独立位是否被设置。它建立在前__get_pfnblock_flags_mask()之上并加上独立位的合法性检查。一、函数签名bool get_pfnblock_bit(const struct page *page, unsigned long pfn, enum pageblock_bits pb_bit)参数参数类型含义pageconst struct page *目标页所在 pageblock 内的某一页用于定位pfnunsigned long目标页帧号pb_bitenum pageblock_bits要检查的单个pageblock 属性位返回值booltrue表示该位被置位false表示未置位。注释/** * get_pfnblock_bit - Check if a standalone bit of a pageblock is set * page: The page within the block of interest * pfn: The target page frame number * pb_bit: pageblock bit to check * * Return: true if the bit is set, otherwise false */关键词standalone bit只检查独立位即is_standalone_pb_bit()为真的那种位不属于迁移类型字段。为什么强调 standalone因为迁移类型字段是多位编码不能单独 test 某一位而独立位可以单独检查。二、典型实现补充bool get_pfnblock_bit(const struct page *page, unsigned long pfn, enum pageblock_bits pb_bit) { VM_BUG_ON_PAGE(!is_standalone_pb_bit(pb_bit), page); return __get_pfnblock_flags_mask(page, pfn, 1UL pb_bit) ! 0; }逐步说明1. 断言是独立位VM_BUG_ON_PAGE(!is_standalone_pb_bit(pb_bit), page);VM_BUG_ON_PAGE调试配置CONFIG_DEBUG_VM下的运行时断言。is_standalone_pb_bit(pb_bit)前面讲过的判断该位是否在迁移类型字段之外、__NR_PAGEBLOCK_BITS之内。如果传进来的不是独立位比如误传PB_migrate或PB_migrate_end触发 bug 报告。生产内核下该检查被编译掉零开销。用VM_BUG_ON_PAGE而不是BUILD_BUG_ON因为pb_bit是运行期参数不是编译期常量。2. 调用__get_pfnblock_flags_mask()读取return __get_pfnblock_flags_mask(page, pfn, 1UL pb_bit) ! 0;1UL pb_bit只关心pb_bit这一位所以 mask 就是该位为 1。__get_pfnblock_flags_mask()前面讲的读取实现读出该 pageblock 的属性位并按 mask 过滤。! 0过滤后非零 ⇒ 该位被置位 ⇒ 返回true否则false。为什么不用test_bit直接查可以用get_pfnblock_bitmap_bitidx()test_bit自己实现但复用__get_pfnblock_flags_mask()更简洁且保持了读 pageblock 属性的统一路径内部处理了 SPARSEMEM/非 SPARSEMEM、跨字等细节。三、它是独立位三件套之一和下面这些函数配套函数作用get_pfnblock_bit(page, pfn, pb_bit)检查某独立位是否置位set_pfnblock_bit(page, pfn, pb_bit)设置某独立位clear_pfnblock_bit(page, pfn, pb_bit)清除某独立位它们都只允许操作独立位is_standalone_pb_bit()为真不允许单独操作迁移类型字段的位。对应的写函数void set_pfnblock_bit(const struct page *page, unsigned long pfn, enum pageblock_bits pb_bit) { unsigned long *bitmap; unsigned long bitidx; VM_BUG_ON_PAGE(!is_standalone_pb_bit(pb_bit), page); bitmap get_pageblock_bitmap(page, pfn); bitidx pfn_to_bitidx(page, pfn); set_bit(bitidx pb_bit, bitmap); }写操作直接定位到字 位用set_bit。读操作复用__get_pfnblock_flags_mask()因为读不需要原子性/字定位优化。四、典型用途1.PB_migrate_skip——是否跳过内存规整if (get_pfnblock_bit(page, pfn, PB_migrate_skip)) /* 这个 pageblock 被标记为跳过规整 */内存规整compaction扫描到某 pageblock 时若该位被设置就跳过它节省扫描开销。compaction.c里常见。2. 其他独立位不同内核版本可能还有别的独立位如与内存隔离、pageblock 特殊标记相关的都用同一套接口。3. 与迁移类型的区别迁移类型用get_pfnblock_migratetype()读多位字段。独立位用get_pfnblock_bit()读单个位。不能混用不能对迁移类型字段用get_pfnblock_bit()VM_BUG_ON_PAGE会拦截。五、与前面内容的呼应前面出现过的这里的关联is_standalone_pb_bit()这里用VM_BUG_ON_PAGE断言传入位是独立位__get_pfnblock_flags_mask()这里直接调用它读取get_pageblock_bitmap()/pfn_to_bitidx()写函数里用读函数里被__get_pfnblock_flags_mask()间接用enum pageblock_bits/NR_PAGEBLOCK_BITS位类型与总数PB_migrate_skip最典型的独立位用例VM_BUG_ON_PAGE调试断言机制调用链get_pfnblock_bit(page, pfn, pb_bit) ├── VM_BUG_ON_PAGE(!is_standalone_pb_bit(pb_bit), page) // 调试断言 └── __get_pfnblock_flags_mask(page, pfn, 1UL pb_bit) ├── get_pageblock_bitmap() ├── pfn_to_bitidx() └── 读位 mask六、小结表项说明函数名get_pfnblock_bit作用检查某 pageblock 的单个独立位是否置位参数page用于定位 zone/位图参数pfn目标页帧号参数pb_bit要检查的独立位enum pageblock_bits返回值bool位是否置位关键约束只能是独立位由VM_BUG_ON_PAGE(!is_standalone_pb_bit(...))保证实现依赖__get_pfnblock_flags_mask(page, pfn, 1UL pb_bit)配套函数set_pfnblock_bit()/clear_pfnblock_bit()典型用例PB_migrate_skip跳过规整一句话总结get_pfnblock_bit()用于读取某个 pageblock 的单个独立位它先断言该位是独立位不能是迁移类型字段中的位再通过__get_pfnblock_flags_mask(page, pfn, 1UL pb_bit)读取并返回布尔结果它与set_pfnblock_bit()/clear_pfnblock_bit()构成独立位操作的读/写接口典型应用是PB_migrate_skip等 pageblock 级标记。
返回列表