根据前面的分析可知,medatada pair用于存储需要原子更新的信息,而CTZ skip-list用于存储COW数据。那么用于存储metadata pair和COW数据的block是怎么分分配的呢?block alloctor负责分配block。
通常,文件系统会使用free list或者bitmap来表示空闲的block,这些free list和bitmap也是存储在文件系统中的,并随着空闲块信息的改变而不断的更新。由于这些信息也是存储在文件系统中,即使有掉电恢复的功能,保证这些信息的完整性也是很复杂的。
littlefs才用了一个比较谨慎的方法。littlefs不是采用存储在flash上的free list,而是认为文件系统时flash尚的空闲块的镜像。block alloctor类似于垃圾回收器,在需要的时候会扫描未使用的block。虽然这个方法看起很复杂,但是由于不需要维持free list,大大减小了程序的复杂度。
block alloctor需要高效的找到空闲块。可以在每次分配空闲块时都遍历每个block并和文件系统已使用的block进行比较,但这样效率不高,在一次遍历中应收集多个空闲块。在一些大型文件系统中,会在内存中维持一个所有block空闲状态的bitmap,这样查找空闲块时遍历这个bitmap即可,但是这个方法会消耗一定数量的RAM。
littlefs中的block alloctor采取了一个折中的办法,不是维持所有的block的bitmap,而是只维持一定数量的block的bitmap,比如32个block,这样只需要一个unsigned int即可。这个较小的固定数量的bitmap就叫lookahead buffer。下图展示了采用一个32bit的lookahead buffer,在具有128个block的flash上分配4个空闲块的情形: