按文件偏移查找页缓存
页缓存用 XArray 把文件页索引映射到 folio,支持稀疏条目和多页 folio。
相关概念
工程问题#
大文件通常只有部分内容驻留内存;读写路径需要按偏移查缓存,还要区分未命中、正在变化的条目及特殊值。
实际实现#
address_space 的 i_pages 是 XArray。filemap_get_entry 使用 xas_load 读取条目,并配合 RCU、引用获取和重试确认对象仍有效。
处理流程#
- 把文件偏移换算为页索引
- 从 i_pages 读取条目
- 获取引用并校验,必要时重试
- 返回 folio、特殊条目或未命中,由上层决定后续读取或缺页处理
源码片段#
固定版本 · 原文摘录mm/filemap.cv6.12 · L1839–L1860
1839 rcu_read_lock();1840repeat:1841 xas_reset(&xas);1842 folio = xas_load(&xas);1843 if (xas_retry(&xas, folio))1844 goto repeat;1845 /*1846 * A shadow entry of a recently evicted page, or a swap entry from1847 * shmem/tmpfs. Return it without attempting to raise page count.1848 */1849 if (!folio || xa_is_value(folio))1850 goto out;18511852 if (!folio_try_get(folio))1853 goto repeat;18541855 if (unlikely(folio != xas_reload(&xas))) {1856 folio_put(folio);1857 goto repeat;1858 }1859out:1860 rcu_read_unlock();filemap_get_entry
RCU 临界区内读取 XArray;特殊值直接返回路径处理,普通 folio 必须成功获取引用,并用 xas_reload 确认条目未被替换,否则释放引用后重试。XA_STATE 在本段上方绑定 mapping->i_pages 和页索引。
连续截取查找、引用校验和 RCU 解锁部分;函数的 XA_STATE 声明和最终 return 在相邻上下文。
收益与取舍#
工程分析带来的收益
- 为稀疏文件索引按需分配元数据
- 同一索引支持查找与有序扫描
付出的代价
- 工程分析:树节点消耗额外内存
- 无锁读取仍需要引用校验与重试协议
可比较的选择
普通哈希表点查找直接,但有序扫描和多索引范围表示需额外设计。
版本与适用范围#
对应页缓存索引;XArray 不负责页缓存的全部淘汰策略,也不等同于磁盘文件系统索引。