当我们修改某个文件时,必然要对相应文件系统上的块进行更新。但是对文件系统块的更新可能因为页高速缓存的影响在内存保留相当长的时间后才刷新到磁盘,此时若发生断电故障或系统崩溃这样的不可预测的时间,可能会导致文件系统处于不一致的状态。文件系统的不一致状态,是指元数据中存储的信息与磁盘实际情况不一致。这个相当长的时间是相对于计算机运行速度来说,事实上也是极短的(通常为1/500 秒?)。为了克服这个问题,传统的Unix文件系统在安装之前都要进行检查;如果它没有被正常卸载(例如:超级块的 s_mount_state != EXT2_VALID_FS ),那么一个特定的程序(e2fsck)将执行彻底、耗时的检查,并修正磁盘文件系统的所有数据结构。
然而当文件系统的文件数、目录数增大到一定程度时,一次一致性检查接可能花费数个小时,这显然是无法接受的。日志文件系统的目标就是避免对整个文件系统进行耗时的一致性检查。简单来说,当文件系统没有被正常卸载时,只需要直接去查看日志的内容,日志存放在一个特定的磁盘区,然后对日志中的内容进行检查和修正就可以了。
Ext3日志文件系统Ext3的核心思想是对文件系统进行的任何高级修改都分成以下步骤:
将待写块的一个副本存放在日志中。 将此次操作记录在日志中。 将已在内存中修改好的块写入文件系统。 将日志中的待写块的副本删除。但是如果文件的内容非常多,岂不是要花费大量的时间在副本的拷贝上?
事实上,每个文件系统都由所谓的元数据块和普通数据块组成。在Ext2和Ext3的文件系统中,有六种元数据:超级块、块组描述符、索引节点表、用于间接寻址的块、数据位图块和索引节点位图块。很多日志文件系统(如SGI的XFS以及IBM的JFS)都限定自己把影响元数据的操作计入日志。元数据的日志记录足以恢复磁盘文件系统数据结构的一致性,但因为文件的数据块不记入日志,就无法防止系统故障造成的文件内容损坏。
Ext3文件系统可以通过配置把影响文件系统元数据的操作和影响文件数据块的操作都计入日志,但每种写操作都计入日志会导致极大的性能损失,因此,Ext3让系统管理员决定应当把什么计入日志。Ext3提供三种不同的日志模式:
日志(Journal)文件系统所有数据和元数据的改变都被记入日志。这提高了安全性,但损失性能,因为所有数据要写入两次。 预定(Ordered)
只将文件元数据的改变记入日志。但在日志被写入前,数据必须被先写入文件系统。这是Ext3的缺省模式。 写回(Writeback)
只将文件元数据的改变记入日志。不要求日志必须在数据被写入之后才被写,可以同时进行。
三种模式下的所有文件元数据都是通过下文的JDB来写入磁盘的。日志模式下的文件数据由JDB写入磁盘,预定模式下的文件数据由JDB写入磁盘(PS:UTLK中写到该模式下的缓冲区同时被加入到了索引节点的脏缓冲区链表,这我不是很理解,望明白的同学可以指教一下。),写回模式下的数据则由磁盘高速缓存的刷新机制写入磁盘(脏页写回)。
JBDExt3文件系统本身不处理日志,而是利用所谓的日志块设备(Journaling Block Device,JDB)的通用内核层。
EXT3文件系统和JBD之间相互独立,它们交互的基本单元有3个:
日志记录:记录日志文件系统中一个磁盘块的一次更新; 原子操作处理(handle_s):文件系统的一次系统调用所对应的日志记录,包含了多个日志记录,具有原子性,要么包含的日志记录全部完成,要么全不完成; 事务(journal_s):包含多个原子操作处理,是JBD对磁盘写操作的单位。一般情况下,JBD如下工作,每次系统调用都会把若干对文件系统的修改以原子操作处理的方式打包,然后写入当前的事务中,当前的事务收集原子操作处理。每隔固定的时间间隔(5 s),或是事务剩余空间不足,JBD会将事务写到磁盘的日志中,如下图所示:

若出现断电或是系统崩溃,重启后自动进行的 e2fsck 检查可分为以下2种情况:
若事务是完整的,则将日志中的事务内容重新写到磁盘上; 若事务是不完整的,不论该事务是否完成,但没有顺利地完整写到日志中,事务中的内容均是无效的,e2fsck 无视它。这样就缩短了EXT3用于恢复系统一致性状态所需的时间。 日志如何工作以下是一个比较通用的模式,可能在默写特定情况下不是很符合,但还是具有参考意义的。
用户使用 write() 系统调用写入文件。 (1)操作对应于一个原子操作,被加入到JDB的一个事务中。 JDB在条件满足时将该事务写入到日志的磁盘区。(文件数据并没有开始写) JDB激活事务中的所有I/O数据传送。 传送成功完成后,磁盘上相应的事务记录由内核的一个周期性程序删除。 存在的缺陷理论上,上述机制足以应付断电或是系统崩溃等状况,但在实际操作中存在着不足之处。在频繁地断电或是系统故障条件下,表现尤为明显。
EXT3日志型文件系统存在以下缺陷:
日志与文件系统存储在同一个磁盘上,这是最常见的情况。日志也是存储于磁盘上的文件,并不能免受磁盘故障 的损害。在出现故障时,磁盘上的日志文件写入状态是不可保证的。若是作为恢复依据的日志内容出错,则在进行检查 恢复时,也必定会出现错误,并且循环下去,出现错误的概 率会越来越大,直到整个文件系统崩溃不可再用为止;
事务是先缓存在内存中,等待一定时间间隔后(默认为 5 s)或是剩余空间不够了,才写到磁盘中的日志中。这样的话 若是在写入磁盘之前出现断电,这些事务就会丢失。这样的话,会发生同上述情况一样的结果,作为恢复根据的日志内容不完整,或是有错。
EXT3 及 JBD 原有机制只是为了缩短用于磁盘检查修复 所需的时间,但作为该机制核心基础的日志内容在一些频繁 出现故障的情况下,仍然会出现错误,该机制就无法保证其 可靠性,这在些极端情况下无法保证文件系统应有的可用性。
参考:
UTLK [PDF]基于 JBD 的日志型文件系统性能优化(作者:陈 颖,奚宏生)如若觉得本文尚可,欢迎转载交流,转载请在正文明显处注明原文地址,谢谢!