基本模型
zswap初始化流程
为系统里的每一个cpu core分配per cpu dst内存。
为每个cpu core分配内核压缩解压缩的上下文。
创建zpool, 并根据用户态模块参数选择zpool后端使用的内存分配器。创建
zpool的时候需要给zpool注册一个evict的回调函数,这个函数用于在zpool的
后端内存分配器没有内存的时候, 把zpool里的压缩内存向swap设备写入。可以
看到现在的evict在向swap设备写数据的时候还要先把压缩的数据解压缩,如果写
入swap设备的数据将来被使用,重新加载回内存的代码路径是标准的缺页流程,
和zswap没有关系。这个步骤整体上把创建出来的各种基础数据结构封装在一个
struct zswap_pool的结构中, 上面步骤里的per cpu压缩解压缩上下文也放在了
zswap_pool。注册frontswap的回调函数。根据内核Documentation/vm/frontswap.rst,store
用于把swap页存入zpool, load用于从zpool重新加载swap的页,invalidate_*
用于把zpool里存放的压缩页面释放。
核心数据结构
1
2
3
4
5
6
7
8struct zswap_pool
swap page ---> frontswap
.store
.load
.invalidate_page
.invalidate_area
.initzswap初始化的时候注册frontswap的一个实例,frontswap的各个回调中使用zpool接口
存储压缩的内存,zpool接口的后端可以是不同的专用于存储压缩内存的内存分配器。对用户态的接口
zswap用多个模块参数用来配置zswap的参数: zpool的后端内存分配器是可以选的
(默认是zbud); 压缩解压算法(默认是LZO),测试硬件offload的时候,这里要选
则相应的算法; zpool占内存的大小; 对相同页的优化处理。这些参数在/sys/module/zswap/parameters/下也可以配置。
在/sys/kernel/debug/zswap/下有zswap的相关统计项。
对内核crypto comp的接口
- 当前代码使用的是内核crypto comp压缩解压缩接口,没有使用crypto acomp接口。
实现细节
不清楚这里的逻辑,为什么要一个zswap pool的链表。
1 | __zswap_pool_create_fallback(void) |
这里选一个zswap_frontswap_store的实现分析:
1 | zswap_frontswap_store |
从上面store函数的分析中可以看到,因为整个设计都是基于per cpu的,所以做
crypto_comp_compress的时候都是关闭抢占的(是否要关闭调度), 这和acomp的基本
使用方式是不兼容的,在crypto testmgr.c里acomp的test case是wait等待任务完成
的。还有一点,压缩完的数据需要copy到zpool的内存里。