Ext3文件系统
1 Ext3文件系统简介
Ext3一种日记式文件系统。日记文件系统会把系统对磁盘文件系统的更改第一一一记录在日记文件中,然后再更新到磁盘上。在由某种原因(例如down机等)而致使文件系统显现不一致的情形下,能够通过重放(replay)日记文件来恢复文件系统的一致性。
Ext3是直接从Ext2文件系统进展过来的,采纳了Ext2文件系统的磁盘数据布局,实现了对Ext2的完全兼容。
依照写入日记的内容和数据刷新时刻的不同,Ext3可支持三个不同的日记格式:Journal模式,ordered模式和writeback模式。
1.1 Ext3日记模式
第一介绍元数据的概念,在Ext2 和 Ext3中,有六种元数据,别离是:超级块,块组描述符,节点,间接块,数据位图。可见,元数据记录了数据的改变。
Ext3既能够只对元数据做日记,也能够同时对文件数据块做日记。具体来讲,Ext3提供以下三种日记模式:
日记(Journal )
文件系统所有数据和元数据的改变都记入日记。这种模式减少了丢失每一个文件所作修改的机遇,可是它需要很多额外的磁盘访问。例如,当一个新文件被创建时,它的所有数据块都必需复制一份作为日记记录。这是最平安和最慢的Ext3日记模式。
预定(Ordered )
只有对文件系统元数据的改变才记入日记。但是,Ext3文件系统把元数据和相关的数据块进行分组,以便把元数据写入磁盘之前写入数据块。如此,就能够够减少文件内数据损坏的机遇;例如,确保增大文件的任何写访问都完全受日记的爱惜。这是缺省的Ext3 日记模式。
写回(Writeback )
只有对文件系统元数据的改变才记入日记;这是在其改日记文件系统发觉的方式,也是最快的模式
1.2 日记块设备(JBD)
Ext3 文件系统本身不处置日记,而是利用日记块设备(Journaling Block Device)或叫JBD 的通用内核层。Ext3文件系统挪用JDB例程以确保在系统万一显现故障时它的后续操作可不能损坏磁盘数据结构。Ext3 与JDB 之间的交互本质上基于三个大体单元:日记记录,原子操作和事务。
日记记录本质上是文件系统将要发出的低级操作的描述。在某些日记文件系统中,日记记录只包括操作所修改的字节范围及字节在文件系统中的起始位置。但是,JDB 层利用的日记记录由低级操作所修改的整个缓冲区组成。这种方式可能浪费很多日记空间(例如,当低级操作仅仅改变位图的一个位时),可是,它仍是相当快的,因为JBD 层直接对缓冲区缓和冲区首部进行操作。
修改文件系统的任一系统挪用都通常划分为操纵磁盘数据结构的一系列低级操作。若是这些低级操作尚未全数完成系统就意外宕机,就会损坏磁盘数据。为了避免数据损坏,Ext3文件系统必需确保每一个系统挪用以原子的方式进行处置。原子操作是对磁盘数据结构的一组低级操作,这组低级操作对应一个单独的高级操作。
出于效率的缘故,JBD 层对日记的处置采纳分组的方式,即把属于几个原子操作处置的日记记录分组放在一个单独的事务中。另外,与一个处置相关的所有日记记录都必需包括在同一个事务中。一个事务的所有日记记录都寄存在日记的持续块中。JBD层把每一个事务作为整体来处置。例如,只有当包括在一个事务的日记记录中的所有数据提交给文件系统时才回收该事务所利用的块。
2 JBD层
2.1 JBD层大体概念
Log record
记录文件系统中一个block的改动。记录格式为journal_block_tag_t结构,存储在日记文件.journal中的discriptor block。当JBD层把一个block写入磁盘时,给block对应的buffer head添加一个journal_head结构。
Atomic operation handle
一个system call对应的所有log record组织在一路,称为一个handle。为保证文件系统一致性,handle为原子操作,当恢复系统fsck时,要么执行一个handle中的所有log record操作,要么一个都不执行。
Transaction
JBD将多个handle组织成一个transaction,transaction中的所有log record存储
在日记文件的持续的块中。当一个transaction中的所有log record被提交到磁盘上以后,那个transaction占用的block就能够够被回收再利用了。
transaction的整个生命历程中的状态和完成的工作如下:
1) T_RUNNING:表示当前transaction正在运行,能够接收数据到各个链表。每当发起一个写数据操作的时候,就会启动一个new handle, new handle会检查当前是不是有running transaction,若是有,就向那个transaction里面提交数据。若是当前没有running transaction,就会创建一个新的transaction并置为running状态,向那个transaction提交数据。细节能够详见start_this_handle()函数
2) T_LOCKED:transaction的锁,很多时候会用到,比如commit的时候
3) T_RUNDOWN:
4) T_FLUSH:把ordered模式下的数据刷到硬盘上
5) T_COMMIT:写日记到硬盘。现在所有要写到日记的内容已经放到当前transaction的t_buufer链表中了(三种日记模式下要写入的数据和元数据不一样,详见前面的分析,可是所有的内容都放入那个链表),扫描那个链表,把所有内容写入journal.
以后那个transaction会被加入到joural的 checkpoint list,在适合的时候把数据或元数据写入硬盘。可见,checkpoint 确实是把数据或元数据写入硬盘。 6) T_FINISHED:这时数据已经写入硬盘,transaction工作完毕,能够从日记中删除
2.2 Jbd数据结构关系