文件系统和崩溃一致性
VSFS
文件系统:纯软件。VSFS(Very Simple File System)。一个简单的实现如下:
大致磁盘结构:
S:超级块,包含 inode 的数目和数据块数目,inode 表开始位置等等。
i,d:位图,表示占用还是空闲。
I:inode 表。存放文件信息,如是否可以读、写、执行,拥有者,大小、访问时间、磁盘指针…
D:数据区域。
多级索引:文件太大的话磁盘指针不够用,可以用一个磁盘指针指向一个间接块,继续存放磁盘指针。
局部性和快速文件系统
第一个 UNIX 文件系统:
inode 包含指向空闲列表块的头部的指针。
很多东西都是一步步迭代的,刚开始就是勉强能用,性能不是首要关注点,然后再慢慢改进。
碎片问题:
原始块太小,定位开销。
FFS:更改磁盘结构,分组,称为柱面组。在每个组分配文件和目录,每个组有超级块的一个副本。相关文件放在同一个组中。
局部性:大量的文件访问是相同的文件或同一目录的文件。
大文件:一个组放一部分,防止占用过多影响相关文件。
子块:4KB块可能导致磁盘浪费,可以分成更小的子块。子块满了再分配一个子块,缓冲写入(如4KB块缓冲写入,避免子块特殊情况)。
优化磁盘布局:防止读完0刚发请求读1的时候1转跑了。如下图只是一种方案,FFS更智能。
崩溃一致性:FSCK和日志
crash consistency problem
写到一半崩了怎么办?如要写 inode,更新位图,写入数据,崩了可能导致数据不一致。
文件系统检查程序
无法解决的问题:文件系统看起来一致,但是 inode 指向垃圾数据。
fsck 在文件系统挂载并可用之前进行。
全部扫描,检查 inode,位图和磁盘指针,有效,但浪费。
预写日志
带有日志的 ext3 文件系统如下所示:
操作顺序:
- 日志写入,将事务(事务开始块,要写入的数据和元数据,事务结束块)写入日志。
- 加检查点:写入元数据和数据更新。
防止日志写入时崩溃可以:等待事务开始和数据、元数据写入了再写事务结束块,或者加上校验和。
批处理日志更新:先修改内存中数据,超时一段时间后写入磁盘时提交事务,避免大量磁盘写入流量。
日志写入可以选择不写入具体的数据,前提是在事务提交之前数据已经写好,也就是 inode 不能指向无效数据。
inode, 位图,数据块。