Nand flash设备存储结构示例
上图是一个1056Mb的存储设备。页面用户数据 空间是2KB,OOB是64字节,每个块 包含64个页面,一共 1024个块。用户数据 空间是128MB,OOB空间是4MB。
每个页面的OOB保留一个字节 用于坏块 标识 ,一定数量的ECC校验数存储空间,用于用户数据,如 2KB的用户 数据需要22字节的ECC校验码。
OOB剩下的空间就可以用于转换层管理数据(日志)的存放。
设计概述
- NFTL将所管理的所有页面作为一个环形队列循环使用。
- 通过一个索引表记录所有页面的逻辑地址和物理地址的映射关系,该表在系统初始化时根据保存OOB中的日志数据创建,在系统执行写入请求时更新。
- 任何页面写入请求,数据均存放在队首页面,并在OOB区保存日志数据。
- 日志数据包含队列信息以及最近写入页面的映射关系。
- 如果写入的页面已经存在,则旧的页面成为垃圾页面。
- 在队列的剩余空间小于一定尺寸时触发磨损平衡处理的同时实现垃圾回收 。
日志数据
每个页面的OOB中存放格式一致的转换层日志数据:
|
日志头
首字节:固定字符‘N’,作为日志标记;
Ep:擦写计数,该计数可以在系统初始化时找回日志的root页;
Tail:队尾页索引,指向环形队列尾部页面;
Count:当前队列内有效页面数量计数;
Bc:坏块计数,当前擦写循环的坏块计数;
Bn:上一次擦写循环的坏块总数;
映射区
映射区用于存放页面的逻辑地址和物理地址的映射关系。
保存了当前页及其前面相邻页面的逻辑地址,第一个为本页逻辑地址,后面依次是前面相邻的页逻辑地址。
地址数据的数据宽度根据所管理的存储区域内的页面总容量而定。比如, 2字节的页索引可以记录65K个页面,每个页面2K,对应的用户数据空间是128M,足够一般的嵌入式设备使用。
映射区保存的页面映射数量除了和地址宽度有关,还有的oob尺寸。
如示例的flash设备每个页面有64字节的OOB(实际常见的有128和256字节),去掉坏块标识和ecc校验码,余下41字节。地址宽度按2字节计算,去掉日志头11字节,映射区可以保存15个页的逻辑地址。
索引表
索引表保存逻辑地址到物理地址的映射关系,在系统初始化时根据读取的日志映射区信息构建。
可以用一维数组表示,数组的索引值代表页面的逻辑地址,数组项保存的该逻辑页面对应的物理页面地址——所在存储区的页面索引值。
物理页地址由块索引和页的块内索引组成。假如每个块包含64个页,则该值的低6位是该页在其所在块内的页索引值,其他位的值是这个块在该转换层所管理的flash分区的块索引。
Root页面和队列头
最后写入的页面是root页面,该页面保存的日志的头部信息是队列的最新状态。
Root页面的下一个页面是队列头-head,指向队列下一个可用页面。
Root和head信息不需要在日志中保存,在设备初始化时根据擦写计数找回 。
图示说明
索引表:逻辑地址(vId,索引序号)转换物理地址(pId)
物理页面:蓝色所在页为root页,head指向下一个待写入页面
root日志数据,为简化描述,示例仅记录三条映射
注:用户读写flash的页面是随机的,所以,map保存的逻辑地址值并不一定连续 |
初始化过程
转换层初始化就是其所管理的页面的环形队列初始化。先确定root页面的位置,再读取所有有效映射关系重建索引表。
Root位置查找
根据Ep找到队首页面所在的块:读取第一块首页的OOB,获取Ep值,再
用折半查找法,找出最后一个 和 该值相同的块;继续在块内查找最后一个Ep值相同的页,仍然用折半查找法。
索引表初始化
读取root页面的OOB数据,即可获取队列的尾部信息,根据映射区保存的映射数量n,从root向队尾方向每n个页面读取一次(遇到坏块应该重新对齐新块边缘读取),根据读取到的映射信息重建页面索引表。重建过程插入新的映射记录时,如果该映射已经存在,表明待插入的映射所指的页面是垃圾页面,则放弃插入跳过即可。
当遍历到tail页面时,插入的记录数量应该和root日志记录的页面计数相等。
注:如果读取方向是从tail项root,则不需要判断映射是否存在,直接保存即可,这样所有旧的映射记录都会被最新的记录覆盖。
垃圾页面
垃圾页面的产生
每次页面写入请求都是保存在head指向的队首页面,如果该页面的逻辑地址在之前的页面中已经存在,则之前的页面就成为垃圾页面。
垃圾页面回收
设置垃圾页面回收窗口m,当队列头到尾之间的未使用页面数量小于等于整体页面数量(Pm)的1/(m+1),则执行写入请求时将同时从队尾搬移m个页面到队首,如果搬移过程有垃圾页面则直接跳过。这样,经过Pm/(1+m)次写入后,当前队列中可能存在的垃圾页面就会被完全回收。
垃圾页面确认
每个页面的日志数据的M0保存的是该页面逻辑地址,根据该逻辑地址从索引表查找其对应的物理页地址,如果该页地址指向的是另外一个物理页面,则表示当前页面是垃圾页面。
磨损平衡
垃圾回收的过程也是磨损平衡处理的过程。
任何写入请求都保存在保存队首页面,队尾指向的页面如果是有效页面,则表明该页面在当前记录循环内没有被重写过,即为冷数据页面,垃圾回收过程遇到冷数据页面就会将其搬移到队首。这种设计保证转换层所管理的所有页面的擦写次数最多差1,也就是当前root页面所在块及其之前的块比其之后的块擦除次数 多1。
相比哪定一个阈值,当擦写次数超过该阈值则找一个冷块做交换的做法,本设计更简单,在局部磨损严重的情况发生之前已经做了预防性数据搬移。
坏块管理
写入过程遇到坏块直接跳过即可,不需要一个坏块表将其重新映射到另外一个块做替代使用。
同样,初始化重建索引表过程遇到坏块直接跳过即可,不需要特殊处理。
记录队列每次翻转时,可以根据当前轮和上一轮的坏块数量变化情况判断flash设备的磨损情况。