文件系统及Fsck设计思路理解
魏星
Fsck是实现对文件系统的修复功能(fs check)。理解fsck需要掌握Linux文件系统设计原理、fsck设计原理和fsck实现的步骤。
一、Linux文件系统设计原理
1、文件系统基本概念
基本概念:super block、inode、目录文件、普通文件
a、super block
超级块存储文件系统的相关信息,包括文件系统的格式,inode/block的总数、使用量、剩余量等信息。没有superblock就没有这个filesystem了。
他主要记录的信息有:
.block与inode的总数;
.未使用与已使用的inode/blodk数量;
.block与inode的大小(block为1,2,4K,inode为128byte或者256byte);
.filessystem的挂载时间、最近一次写入数据的时间、最近一次检查磁盘(fsck)的时间等文件系统的相关信息;
.一个valid bit数值,若此文件系统已经被挂载,则valid bit为0,若未被挂载,则valid bit为1。
格式化就是写super block的内容。Super block对文件系统太重要了,所以是有备份隐藏在系统中的,如果这个块坏了,可以用备份的块来恢复。
恢复办法见:
http://blog.chinaunix.net/uid-26557245-id-3748168.html
b、Inode
Inodes是实现文件系统存储的关键。在Linux系统中,一个文件可以分成几个数据块存储,就好像是分散在各地的龙珠一样。为了顺利的收齐龙珠,我们需要一个“雷达”来指引,这个“雷达”就是inode。每个文件对应一个inode,每个inode中包含多个指针,指向属于该文件各个数据块。当操作系统需要读取文件时,只需要对应inode的“地图”,收集起分散的数据块,就得到文件了。数据块才是正真存储文件的地方。
文件是文件系统对数据的分割单元。文件系统用目录来组织文件,赋予文件以上下分级的结构。在硬盘上实现这一分级结构的关键是使用inode来虚拟普通文件和目录文件对象。
在Linux文件管理中除了自身的数据,还有一个附属信息,即文件的元数据(metadata)。这个元数据用于记录文件的许多信息,比如文件大小、拥有人、所属的组、创建日期、修改日期等。元数据并不包含在文件的数据中,而是由操作系统维护的,元数据包含在inode中。
当Linux想要打开一个文件时,只需要找到文件对应的inode,然后沿着指针,将所有的数据块收集起来,就可以在内存中组成一个文件的数据。
Inode包含文件的元信息,具体如下:
*文件的字节数
*文件拥有者的User ID
*文件的Group ID
*文件的读、写、执行权限
*文件的时间戳,共有三个:ctime指inode创建时间,mtime指文件内容修改时间,atime指文件访问时间。
*链接数即多少文件名指向该inode
*文件数据block的位置
Inode的特色:
每个inode大小是固定的 128字节或者256字节
每个档案都仅会占用一个inode而已
因此文件系统能够建立的档案数量与inode的数量有关
系统读取档案是需要先找到inode,并分析inode所记录的权限与用户是否符合,如符合才能够开始实际读取block的内容
Inode的结构示意图
上图inode有128bytes,这样子inode能够指定多少个block呢?我们以较小的1Kblock来说明吧!
.12个直接指向:12*1K=12K
.间接:1256*1K=256K
每笔block号码的记录会花掉4bytes,因此1K的大小能够记录256笔记录
.双间接:256*256*1K
.三间接:256*256*256*1K
总额:将直接、间接、双间接、三间接相加。最大一个文件16G。
每个inode节点的大小,一般是128字节或者256字节。Inode节点的总数在格式化时就给定,一般是每1KB或每2KB就设置一个inode。假设在一个块1GB的硬盘中,每个inode节点的大小为128字节,每1KB就设置一个inode,那么inode table的大小就会达到128MB,占整个块硬盘的12.8%。
[email protected]:/$ sudo dumpe2fs -h /dev/sdb |grep "Inode size"
[sudo] password for ubuntu:
dumpe2fs 1.41.14 (22-Dec-2010)
Inode size: 256
这就是为什么格式化以后每个盘能够存储的容量只能占整个设备80%的原因
c、目录文件
目录文件存储了一张表,该表就是该目录文件下,所有文件名和inode的映射关系。
从父亲目录中获得本文件的inode号--->找到inode-table表中找到这个inode号对应的数据域中的起点以及其他信息--->去这个数据域中读取该文件的内容(普通文件的内容是字符串,目录文件的内容是一张表)
Linux系统文件名最多127byte,那就是说这里定义的是128byte
d、普通文件
普通文件存储的是用户存储的数据内容啦!搞了半天就是为了存它嘛
2、文件系统的访问模型
文件text.txt的访问模型
在设备中实际存储为:
二、FSCK设计原理
1、Super block checking
在一个文件系统中最经常corrupt掉的是super block中的汇总信息。原因是这些信息在文件系统的block或者inode的每项改动,都需要在汇总信息中做相应的修改。因此,经常会corrupt(汇总信息与实际的文件系统信息不一致)。
Super block的一致性检查包括文件系统大小,inode数量,空闲的block块,空闲的inode数量等。文件系统的大小必须大于super block和inode使用的block数的和。文件系统的大小和布局信息是对fsck而言至关重要的信息。但并没有一种可以实际检查这些大小,因为他们是由newfs静态决定的,fsck可以检查这些大小在一个合理的范围之内。如果fsck在默认的super block中的静态的参数中检查到corrupt,它就会要求提供备用的super block所存放的地址。
2、Free block checking
Fsck会检查所有在cylinder group blocks maps(注:cylinder group即对应于fs的partions)中标记为free的块,即没有被文件占用的块。Fsck会检查free的块的数量与inode中声明使用的块的数量的和是否与整个文件系统的所有块数相等。
如果在block allocation maps中有任何错误,fsck将根据其计算的allocated blocks进行重新组建block allocation maps。
Super block中冶存有所有free块的数量信息,fsck会把自己检查的结果与super block中的信息进行比较,如果这两个数不等,则fsck会将检查得到的结果更新到super block中。
对文件系统中free inode的处理同上
3、Checking the inode state
当文件系统中有很多inode存在的时候(即很多文件),有可能会有几个inode corrupt。文件系统中的inode链表是从inode2开始顺序检查的(inode0标记没有用过的inode,inode1用来将来的扩展),直到文件系统中的最后一个inode。Inode的状态检查包括:format and type,link count,duplicated blocks,bad blocks,and inode size。
每个inode都有一个mode word,它描述了inode的type和state。Inode必须处于六种类型之一:普通inode,目录inode,symbollink inode,special block inode,special character inode,或者是socket inode。
Inode有三种allocation状态:unallocated,allocated和不属于前两种情况的情况。在第三种状态的inode就是不正确的inode,当inodes链表被写入坏的数据的时候,inode有可能进入这种状态。唯一可能修复的方法是fsck晴空这个inode(在链表中删除之)。
4、inode Links
连接数是计算每一个inode与其相连的目录项的数目。Fsck从文件系统的root目录开始检查每一个inode的连接数,并沿着目录树依次查找。每个inode的实际link count在遍历的时候计算得到。如果存储的link count非0,而计算的link count为0,则此inode没有对应的目录项。这种情况下,fsck将把这个对应的文件放入lost+found目录中。如果存储的link count与实际计算所得的值非0且不相等,那么可能是inode的link count在有一个目录加入或者删除的时候没有被响应更新。这种情况下,fsck会用计算得到的值更新存储的值。
每个inode都包含一个列表或者是列表的指针,上面记录着这个inode所使用的数据块。因为inode是这些列表,因此,当这些列表存在不一致的情况时,就直接影响到拥有它的inode。
Fsck会将一个inode声明的block number与列表中已经分配的block number比较。如果另一个inode已经声明了一个block number,那么这个block number就被加入到一个duplicate block链表中。否则,已分配的block list中会将这个block number加入。
对任何duplicate blocks,fsck将会遍历inode list找到拥有duplicated block的inode。一般而言,拥有最早修改时间的inode坏掉的可能性比较大,需要被clear。如果是这种情况,fsck将执行操作,clear这两个inodes。操作必须决定,哪个该留,哪个该clear。
Fsck检查每个inode声明的block number的范围,如果block number比文件系统中第一个数据块的块号低,或者比文件系统中的最后一个数据块的块号大,则称为bad block number。一个inode中许多的bad blocks经常是由于一个indirect block没有被写入到文件系统中,发生这种情况的前提是由于硬件异常的产生。如果一个inode含有bad block numbers,fsck会将其clear。
5、node data size
每个inode包含一定数量的data blocks。实际data block的数量是所有allocated data blocks和indirect blocks的总和。Fsck计算实际的data blocks的数量,并与inode 所记录的数值进行比较。如果两者不一致,fsck会进行修正。
每个inode包含了一个32位的size域。这个数是inode对应的文件所包含有的字节数。这个size域的一致性检查是通过计算与inode对应的最大数量的blocks数,与实际inode保存的数值比较。
6、Checking the data with an inode
一个inode可以直接或者间接的reference三种类型的data blocks。所有的referenced blocks必须是同种类型。这三种类型是:plain data blocks,symbolic link data blocks和 directory data blocks。Plain datablocks包含文件中保存的信息。Symbolic link data blocks包含一个link中包含的路径名。Directory data blocks包含目录项。Fsck只能检查directory data blocks的有效性。
Fsck会检查每个directory data block的几种一致性:directory inode指向unallocated inodes,directory inodes的数量比文件系统中的inode数量大,不正确的”.””..”directory inode numbers,没有结合在文件系统中的directories。如果一个directory data block中的inode number references一个unallocated inode,fsck将移除这个directory entry(目录项)。这种情况只发生在存在硬件异常的情况下。
三、Fsck实现步骤
Fsck由5个阶段完成
1、阶段1:检查块和大小消息
此阶段检查inode列表。它会报告在以下情况遇到的错误状态:
.检查inode类型
.设置零链接计数表
.检查坏块或重复块的inode块编号
.检查inode大小
.检查inode格式
2、阶段1B:重新扫描更多DUPS消息
在文件系统中发现重复块时,将重新扫描文件系统,以查找以前请求过该块的inode。
3、阶段2:检查路径名消息
此阶段将删除指向阶段1和1B所找到的坏inode的目录项。它将报告下列原因所导致的错误状态:
.不正确的根inode模式和状态
.目录inode指针超出范围
.目录项指向坏inode
.目录完整性检查
4、阶段3:检查目录链接
此阶段将检查在阶段2中检查的目录,并报告以下原因所导致的错误状态:
.非引用目录
.缺失的或完整的lost+found目录
5、阶段4:检查引用计数消息
此阶段将检查在阶段2和3中获得的链接计数信息。它将报告下列原因所导致的错误状态:
.非引用文件
.缺失的或完整的lost+found目录
.文件、目录、符号链接或特殊文件的链接计数不正确
.非引用文件、符号链接和目录
.文件和目录中存在坏片段或重复片段
.可用inode总计数不正确
6、阶段5:检查柱面组信息
此阶段将检查可用片段和已用inode图。它将报告下列原因导致的错误状态:
.已用inode图中缺少已分配inode
.可用片段图中缺少可用片段
.已用inode图中有可用inode
.可用片段总计数不正确
.已用inode总计数不正确
四、文件系统破坏的原因
导致一个文件系统corrupt的原因有可能有几种,而最经常的就是非正常关机流程和硬件的错误造成的。
造成corrupt的主要原因就是在停止CPU之前没有同步系统数据。如果非正常的启动没有被检测到,比如没有检查文件系统的一致性,没有恢复不一致的数据,允许使用一个corrupt的文件系统监视一种灾难。另外,一部分硬件有可能在任何时候出错,如在磁盘上的一个坏的块,或者是磁盘控制器没有响应等。
对于corrupt文件系统建议马上修护,否则后面修复越来越难阶段1B
五、解决文件系统破坏的办法
1、设备的拔出保护
设备的拔出,必须要先点击,确认才可以拔出
2、从硬件上解决
硬件解决需要提供UPS或者可充电电池,让设备一直处于工作状态;设备电源是带大电容延迟电源+断电侦测。一旦监测到断电,系统马上停止write文件系统,马上flush设备。
3、从系统软件上解决
系统通过测试,如果CPU使用率超过95%则马上降低系统负载或者直接停止部分不重要的写动作
4、从驱动层面解决
硬件增加一个可以写的、高速的耐写设备(容量很小、很贵),每次把修改制定文件map的数据先写入这个文件,然后更新文件系统,文件系统更新完成再清除这个设备的标准。文件系统每次读都要先判断是用那个地方数据是最新的。这种办法有点笨,一般只有芯片厂商修改文件系统来实现。