预计阅读本页时间:-
4.3.6 日志文件系统
虽然基于日志结构的文件系统是一个很吸引人的想法,但是由于它们和现有的文件系统不相匹配,所以还没有被广泛应用。尽管如此,它们内在的一个思想,即面对出错的鲁棒性,却可以被其他文件系统所借鉴。这里的基本想法是保存一个用于记录系统下一步将要做什么的日志。这样当系统在完成它们即将完成的任务前崩溃时,重新启动后,可以通过查看日志,获取崩溃前计划完成的任务,并完成它们。这样的文件系统被称为日志文件系统,并已经被实际应用。微软(Microsoft)的NTFS文件系统、Linux ext3和ReiserFS文件系统都使用日志。接下来,我们会对这个话题进行简短介绍。
为了看清这个问题的实质,考虑一个简单、普通并经常发生的操作:移除文件。这个操作(在UNIX中)需要三个步骤完成:
1)在目录中删除文件;
广告:个人专属 VPN,独立 IP,无限流量,多机房切换,还可以屏蔽广告和恶意软件,每月最低仅 5 美元
2)释放i节点到空闲i节点池;
3)将所有磁盘块归还空闲磁盘块池。
在Windows中,也需要类似的步骤。不存在系统崩溃时,这些步骤执行的顺序不会带来问题;但是当存在系统崩溃时,就会带来问题。假如在第一步完成后系统崩溃。i节点和文件块将不会被任何文件获得,也不会被再分配;它们只存在于废物池中的某个地方,并因此减少了可利用的资源。如果崩溃发生在第二步后,那么只有磁盘块会丢失。
如果操作顺序被更改,并且i节点最先被释放,这样在系统重启后,i节点可以被再分配,但是旧的目录入口将继续指向它,因此指向错误文件。如果磁盘块最先被释放,这样一个在i节点被清除前的系统崩溃将意味着一个有效的目录入口指向一个i节点,它所列出的磁盘块当前存在于空闲块存储池中并可能很快被再利用。这将导致两个或更多的文件分享同样的磁盘块。这样的结果都是不好的。
日志文件系统则先写一个日志项,列出三个将要完成的动作。然后日志项被写入磁盘(并且为了良好地实施,可能从磁盘读回来验证它的完整性)。只有当日志项已经被写入,不同的操作才可以进行。当所有的操作成功完成后,擦除日志项。如果系统这时崩溃,系统恢复后,文件系统可以通过检查日志来查看是不是有未完成的操作。如果有,可以重新运行所有未完成的操作(这个过程在系统崩溃重复发生时执行多次),直到文件被正确地删除。
为了让日志文件系统工作,被写入日志的操作必须是幂等的,它意味着只要有必要,它们就可以重复执行很多次,并不会带来破坏。像操作“更新位表并标记i节点k或者块n是空闲的”可以重复任意次。同样地,查找一个目录并且删除所有叫foobar的项也是幂等的。在另一方面,把从i节点k新释放的块加入空闲表的末端不是幂等的,因为它们可能已经被释放并存放在那里了。更复杂的操作如“查找空闲块列表并且如果块n不在列表就将块n加入”是幂等的。日志文件系统必须安排它们的数据结构和可写入日志的操作以使它们都是幂等的。在这些条件下,崩溃恢复可以被快速安全地实施。
为了增加可信性,一个文件系统可以引入数据库中原子事务(atomic transaction)的概念。使用这个概念,一组动作可以被界定在开始事务和结束事务操作之间。这样,文件系统就会知道它必须完成所有被界定的操作,或者什么也不做,但是没有其他的选择。
NTFS有一个扩展的日志文件系统,并且它的结构几乎不会因系统崩溃而受到破坏。自1993年NTFS第一次随Windows NT一起发行以来就在不断地发展。Linux上有日志功能的第一个文件系统是ReiserFS,但是因为它和后来标准化的ext2文件系统不相匹配,它的推广受到阻碍。相比之下,ext3——一个不像ReiserFS那么有野心的工程,也具有日志文件功能并且和之前的ext2系统可以共存。