1、F2FS数据布局
F2FS 将整个卷切分成大量的 Segments,每个 Segment 的大小是固定的2 MB。连续的若干个Segments 构成 Section,连续的若干个 Sections 构成 Zone。
F2FS 将整个卷切分成6个区域,除了超级块(Superblock,SB)外,其余每个区域都包含多个 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处理8个Block,查表挑出Valid Page最少的8个Block进行GC,这样做的好处是复制Valid Page的开销最小。
Cost-Benefit算法
u代表valid page在该Block中的比例,age代表该Block距离最近一次修改的时间。
1-u是对这个Block进行GC以后能够获得Free Page的数量
2u是对这个Block进行GC的开销,读取Valid Page(1个u)然后写入到新的Block(再1个u)
(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算法的基础上,增加了对数据寿命和擦除次数的考虑。
μ代表一个Block里Valid Page的比例;
μ/(1-μ)理解为为了释放出(1-μ)的free page必须付出迁移μ的valid page,也就是整体的Cost;
1/age代表Hot degree跟Age成反比
NumberOfCleaning代表Hot degree跟Block的PE 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函数结构示意:
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
空闲
状态为1则CB->状态为2则GREEDY
get_victim_by_default(被垃圾回收或者SSR段选择调用)
gc_node_segment
该功能将总结的节点地址与NAT中的节点地址进行比较。
在有效性的情况下,复制具有冷状态的节点,否则(无效节点)忽略该节点。
start_bidx_of_node:
计算指示给定节点偏移量的起始块索引。要小心,调用者应该给这个节点偏移仅指示直接节点块。如果任何节点偏移,指出其他类型的节点块,如间接或双间接节点块,则它必须是调用者的错误。
check_dnode:
检查dnode的有效性。
check_bg_victim:
如果gc_type是FG_GC,我们可以选择后台GC选择的受害者段。这些分段保证它们具有小的有效块。
更方便的在手机上阅读——公众号关注:aohushare