zpool解压页面过程详解

从 zpool 解压页面到 DRAM 的详细过程

1. 触发页面解压

当系统访问一个被 zswap 缓存并压缩存储在 zpool 中的页面时,可能会触发以下情况之一:

  • 进程访问已被交换到 zswap 的页面,触发 缺页异常 (Page Fault)
  • swapin 机制被触发,从 zswap 读取该页面的压缩数据。
  • 内存管理子系统决定将 zswap 内存中的数据重新加载到 DRAM。

2. 在 zswap 中查找压缩页面

zswap 维护一个 红黑树 (rb_tree) 来存储交换缓存的映射关系。
当需要访问某个 swap entry 时,zswap 通过 zswap_rb_search()rb_tree 中查找该页面的压缩数据。

struct zswap_entry *zswap_rb_search(swap_entry_t entry);
  • 如果找到该条目,说明该页面在 zpool 里有压缩存储。
  • zswap_entry 结构体包含 handle,用于索引 zpool 里的数据。

3. 读取 zpool 里的压缩数据

zpool 负责管理 zswap 使用的压缩数据。

  • zswap_entry->handle 指向 zpool 里的数据。
  • zpool 后端可以是 zbudzsmalloc
    • zbud: 一个物理页存储 2 个压缩页。
    • zsmalloc: 允许多个小页面共享一个物理页。
struct zswap_entry {
    struct rb_node rbnode;
    unsigned long handle;  // 指向 zpool 里的压缩数据
};

通过 zpool_malloc() 访问压缩数据:

void *compressed_data = zpool_malloc(zswap_pool, handle);

4. 分配 DRAM 物理页

在解压之前,系统需要为该页分配 DRAM 物理页。

  • alloc_page(GFP_KERNEL) 申请一个 4KB 页框。
  • 在 NUMA 体系结构中,可能需要从 node0 (DRAM) 分配。
struct page *page = alloc_page(GFP_KERNEL);

5. 解压数据

zswap 读取 zpool 里的压缩数据,并调用相应的解压缩函数,例如 LZ4_decompress_safe()zstd_decompress()

LZ4_decompress_safe(compressed_data, output_page, compressed_size, PAGE_SIZE);

代码路径:

  1. zswap_frontswap_load() 处理前端交换加载。
  2. zpool_malloc() 读取 zpool 数据。
  3. zswap_entry_get() 获取 handle 关联的压缩数据。
  4. zswap_decompress() 进行解压。

6. 更新页表

解压后的数据被写入 DRAM 物理页后,需要更新 页表 (page table),将该物理页映射回用户进程的地址空间。

  • 通过 set_pte_at()pte_mkpresent() 让该页重新可用。
set_pte_at(mm, address, ptep, pte);

7. 释放 zpool 里的压缩数据

如果该页面不再需要压缩存储,则可以从 zswap 中删除:

zswap_rb_erase(entry);
zpool_free(entry->handle);

8. 关键数据结构

zswap_entry 结构体

struct zswap_entry {
    struct rb_node rbnode;  // 红黑树节点
    unsigned long handle;   // zpool 里的数据索引
    ...
};

zpool API 相关函数

void *zpool_malloc(struct zpool *pool, size_t size);
void zpool_free(struct zpool *pool, void *ptr);

完整流程总结

  1. 进程访问 zswap 里的压缩页面,触发 Page Fault
  2. zswap_rb_search()rb_tree 里查找 zswap_entry
  3. zpool_malloc() 读取 zpool 里的压缩数据。
  4. alloc_page(GFP_KERNEL) 分配 DRAM 物理页。
  5. zswap_decompress() 通过 LZ4/ZSTD 解压数据。
  6. set_pte_at() 更新页表,映射到用户进程地址空间。
  7. zpool_free() 释放 zpool 里的压缩数据(可选)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值