f2fs——新型flash友好文件系统gc部分源码分析

时间:2021-07-03 10:01:21

1、F2FS数据布局

 f2fs——新型flash友好文件系统gc部分源码分析

F2FS 将整个卷切分成大量的 Segments,每个 Segment 的大小是固定的2 MB。连续的若干个Segments 构成 Section,连续的若干个 Sections 构成 Zone

F2FS 将整个卷切分成6个区域,除了超级块(SuperblockSB)外,其余每个区域都包含多个 Segments

F2FS数据布局参考博客:http://blog.chinaunix.net/uid-28989651-id-3890455.html

 

2、gc源码分析

背景:

磨损平衡(Wear Leveling)和垃圾回收(Garage Collection)都是基于闪存的基本特征而产生:

1、不支持本地更新(outplace-update,即不能在原数据位置进行覆盖写入或者直接更改,更改数据需要将更改后的数据搬迁至新的可用的page,原有位置的page被标示为无效页,必须要先擦除无效页才能在原位置重新写入数据);

2、以page为单位写入,以Block为单位擦除,擦除Block需要先将有效数据进行搬迁,那么,当有大量的Block可以被选择擦除时,搬迁哪些Block并重新利用就关系到对不同Block的擦除次数;

3、每个Block有擦除次数限制,经常被擦除的Block会很快成为坏块(bad block因此,只有均衡每个Block的擦除次数,才能让闪存具有更长的使用寿命。

FTL通常将page分为三种类型:有效页(valid page)、无效页(Invalid page)、可用页(Free page,若物理页有逻辑地址相对应则表明该页的数据是有效的,称为有效页,反之,称为无效页,当GC运行后,无效页被Erase,成为可用页,此时,才可以重新被写入数据。

 

算法分析:

Greedy算法

固件需要维护一张Block属性表,记录每个Block当前的Valid Page数量。假设每次GC处理8Block,查表挑出Valid Page最少的8Block进行GC,这样做的好处是复制Valid Page的开销最小。

 

Cost-Benefit算法

f2fs——新型flash友好文件系统gc部分源码分析

u代表valid page在该Block中的比例,age代表该Block距离最近一次修改的时间。

1-u是对这个Block进行GC以后能够获得Free Page的数量

2u是对这个Block进行GC的开销,读取Valid Page1u)然后写入到新的Block(再1u

1-u/2u可以理解为投入产出比

固件需要维护的Block属性表里,需要记录每个Block最后一次被写入的时间,GC时选择更久没有被修改的Block(冷数据)

该策略就是选择投入产出比更高,未修改时间更长的Block进行GC,两者相乘数字更大的优先被GC

GREEDY和CB算法参考:http://www.sohu.com/a/149524820_505795

 

CAT算法

CAT的全称是Cost Age Times,在Benefit-Cost算法的基础上,增加了对数据寿命和擦除次数的考虑。

f2fs——新型flash友好文件系统gc部分源码分析

μ代表一个BlockValid Page的比例;

μ/(1-μ)理解为为了释放出(1-μ)的free page必须付出迁移μvalid page,也就是整体的Cost

1/age代表Hot degreeAge成反比

NumberOfCleaning代表Hot degreeBlockPE Cycle成正比

对每个Block进行计算,选择那些结果最高的Block进行GC过程。

CAT算法参考:http://www.sohu.com/a/149784682_505795

 

代码分析:

alloc_mode:

LFS:顺序写,空间不足时清理

SSR:写在脏数据上,不用清理

gc_mode:GC_CB or GC_GREEDY

gc_type:BG_GC or FG_GC

DIRTY_I(宏定义):返回dirty_seglist_info结构

gc.c函数结构示意:

f2fs——新型flash友好文件系统gc部分源码分析 

 

gc_thread_func:

等待时间初始化最小

循环体(条件:线程不应该结束)

尝试冻结->等待时间中断超时

。。。停止则跳出循环

* [GC triggering condition]

  * 0. GC is not conducted currently.

  * 1. There are enough dirty segments.

  * 2. IO subsystem is idle by checking the # of writeback pages.

  * 3. IO subsystem is idle by checking the # of requests in bdev's request list.

  * Note: We have to avoid triggering GCs too much frequently.

  * Because it is possible that some segments can be

  * invalidated soon after by user update or deletion.

  * So, I'd like to wait some time to collect dirty segments.)

尝试上锁

若不空闲,延长等待时间,解锁

有足够的非法块则减少等待时间->增加等待时间

。。。。计数

没有目标被选中则设等待时间为相应值

平衡f2fs元数据

 

select_gc_type(gc模式选择)

前台GREEDY,后台CB

空闲

状态为1CB->状态为2GREEDY

 

get_victim_by_default(被垃圾回收或者SSR段选择调用)

gc_node_segment

该功能将总结的节点地址与NAT中的节点地址进行比较。

在有效性的情况下,复制具有冷状态的节点,否则(无效节点)忽略该节点。

 

start_bidx_of_node:

计算指示给定节点偏移量的起始块索引。要小心,调用者应该给这个节点偏移仅指示直接节点块。如果任何节点偏移,指出其他类型的节点块,如间接或双间接节点块,则它必须是调用者的错误。

 

check_dnode:

检查dnode的有效性。

 

check_bg_victim:

如果gc_typeFG_GC,我们可以选择后台GC选择的受害者段。这些分段保证它们具有小的有效块。


更方便的在手机上阅读——公众号关注:aohushare