40

Linux 文件系统 EXT4 的前世今生

 5 years ago
source link: https://www.oschina.net/translate/introduction-ext4-filesystem?amp%3Butm_medium=referral
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

在先前关于Linux文件系统的文章中,我写了一份说明书去介绍Linux文件系统,里面有一些高级的概念,比如说,一切都是文件。我很想去深入地讨论更多EXT文件系统的特性的信息。所以,首先让我们来回答这个问题:什么是文件系统?一个文件系统应该遵循以下特点:

1. 数据存储: 文件系统主要的功能是结构化存储和取回数据。

2. 命名空间: 提供一套命名和组织的方法,就是命名和结构化数据的规则。

3. 安全模型: 一种访问控制的策略。

4. API: 系统操控文件系统对象的函数,就像操作文件夹和文件一样。

5. 实现: 一个实现以上功能的软件。

这篇文章集中与上面清单的第一项,还有探究元数据结构---在EXT文件系统中提供数据存储的逻辑框架。

EXT文件系统历史

虽然是为Linux编写的,但EXT文件系统起源于Minix操作系统,而Minix文件系统早在1987年首次发布,比Linux还早五年就已经发布了。如果我们查看EXT文件系统家族从其Minix根开始的历史和技术演变,就会更容易理解EXT4文件系统。

Minix

当编写原始Linux内核,Linus Torvalds需要一个文件系统,但是不想开发它。因此他简单的使用了 Minix文件系统 ,这是 Andrew S. Tanenbaum 开发的,而且是Tanenbaum 的Minix操作系统的一部分。 Minix 是类Unix操作系统,为教育使用而开发。它的代码开放使用,而且合理的授权给Torvalds,允许他将它用于Linux的初代版本。

Minix结构如下,其中大部分位于文件系统生成的分区中:

  • 引导扇区(boot sector) 安装于硬盘的第一个扇区。引导块(boot block)包含一个非常小的引导记录和一个分区表。

  • 每一个分区中的第一个块是 超级块(superblock) ,它包含了定义其他文件系统结构的元数据,并将它们定位在分配给分区的物理磁盘上。

  • 节点位图块(inode bitmap block) ,它确定了哪个节点在使用以及哪个节点是空闲的。

  • 节点(inodes) ,它们在磁盘上有它们自己的空间。每个节点包含了一个文件的信息,包括数据块的位置,即文件所属的区域。

  • 区域位图(zone bitmap) 跟踪记录数据区域的使用和释放。

  • 数据区域(data zone) ,数据实际上存储的位置。

对于位图的两个类型来说,一个bit代表了一个特有的数据区域或者一个特有的节点。如果这个bit是0,这个区域或者节点是空闲的而且可供使用,但是如果这个bit是1,这个数据区域或者节点是在使用中的。

节点 是什么?它是索引节点(index-node)的缩写,一个节点是在磁盘上的一个256字节的块,而且它存储文件相关的数据。这些数据包括文件的大小;文件的用户和所属组的用户ID;文件模式(即访问权限);以及三个时间戳具体说明了时间,包括:文件最后访问时间,最后修改时间,以及节点中的数据最后修改时间。

节点也包含了:指向硬盘上文件数据所在的位置。在Minix和EXT1-3文件系统中,它是一个数据区域和块的列表。Minix文件系统节点支持9个数据块,7个直接指针和2个间接指针。如果你想了解的更多,这有一个很好的PDF详细描述了 Minix文件系统结构 ,以及在Wikipedia上对 节点指针结构 的快速概述。

最初的 EXT 文件系统(Extended)由 Rémy Card 编写,并于1992年与Linux一起发布,以规避Minix文件系统的一些大小限制。其中主要的结构变化是基于Unix文件系统(UFS)的文件系统元数据,该结构也被称为伯克利快速文件系统(FFS)。我发现很少有关于此EXT文件系统的可考究的发布信息,显然是因为它存在重大问题,并很快被EXT2文件系统所取代。

EXT2 文件系统非常成功。它在Linux发行版中被使用了很多年,并且它是我在1997年左右开始使用Red Hat Linux 5.0时遇到的第一个文件系统。EXT2文件系统与EXT文件系统具有基本相同的元数据结构,但EXT2更具前瞻性,因为在元数据结构之间保留大量磁盘空间以供未来使用。

像Minix一样,EXT2在其安装的硬盘的第一个扇区中有一个 引导扇区 ,其中包括一个非常小的引导记录和一个分区表。在引导扇区后面有一些预留空间,它跨越引导记录和硬盘上通常位于下一个柱面边界上的第一个分区之间的空间。 GRUB2 (可能还有GRUB1)使用这个空间作为其启动代码的一部分。

每个EXT2分区中的空间被划分为多个柱面组,可以更加精细地管理数据空间。 根据我的经验,组大小通常约为8MB。下面的图1显示了柱面组的基本结构。柱面中的数据分配单元是块,其大小通常为4K。

Ize6N3N.jpg!web

图1:EXT文件系统中柱面组的结构

柱面组中的第一个块是一个超级块,它包含定义其他文件系统结构并将其定位在物理磁盘上的元数据。 分区中的一些附加组将具有备份超级块,但不是全部。 损坏的超级块可以使用 dd 等磁盘实用程序将备份超级块的内容复制到主超级块。 它并不经常发生,但是多年前曾经有一个受损的超级块,我可以使用其中一个备份超级块来恢复其内容。 幸运的是,我已经预见到并使用 dumpe2fs 命令转储我系统上分区的描述符信息。

下面是dumpe2fs命令的部分输出。它显示了超级块中包含的元数据,以及关于文件系统中前两个柱面组的数据。

# dumpe2fs /dev/sda1
Filesystem volume name:   boot 
Last mounted on:          /boot 
Filesystem UUID:          79fc5ed8-5bbc-4dfe-8359-b7b36be6eed3 
Filesystem magic number:  0xEF53 
Filesystem revision #:    1 (dynamic) 
Filesystem features:      has_journal ext_attr resize_inode dir_index filetype needs_recovery extent 64bit flex_bg sparse_super large_file huge_file dir nlink extra_isize 
Filesystem flags:         signed_directory_hash 
Default mount options:    user_xattr acl 
Filesystem state:         clean 
Errors behavior:          Continue 
Filesystem OS type:       Linux 
Inode count:              122160 
Block count:              488192 
Reserved block count:     24409 
Free blocks:              376512 
Free inodes:              121690 
First block:              0 
Block size:               4096 
Fragment size:            4096 
Group descriptor size:    64 
Reserved GDT blocks:      238 
Blocks per group:         32768 
Fragments per group:      32768 
Inodes per group:         8144 
Inode blocks per group:   509 
Flex block group size:    16 
Filesystem created:       Tue Feb  7 09:33:34 2017 
Last mount time:          Sat Apr 29 21:42:01 2017 
Last write time:          Sat Apr 29 21:42:01 2017 
Mount count:              25 
Maximum mount count:      -1 
Last checked:             Tue Feb  7 09:33:34 2017 
Check interval:           0 (<none>) 
Lifetime writes:          594 MB 
Reserved blocks uid:      0 (user root) 
Reserved blocks gid:      0 (group root) 
First inode:              11 
Inode size:               256 
Required extra isize:     32 
Desired extra isize:      32 
Journal inode:            8 
Default directory hash:   half_md4 
Directory Hash Seed:      c780bac9-d4bf-4f35-b695-0fe35e8d2d60 
Journal backup:           inode blocks 
Journal features:         journal_64bit 
Journal size:             32M 
Journal length:           8192 
Journal sequence:         0x00000213 
Journal start:            0 


Group 0: (Blocks 0-32767) 
 Primary superblock at 0, Group descriptors at 1-1 
 Reserved GDT blocks at 2-239 
 Block bitmap at 240 (+240) 
 Inode bitmap at 255 (+255) 
 Inode table at 270-778 (+270) 
 24839 free blocks, 7676 free inodes, 16 directories 
 Free blocks: 7929-32767 
 Free inodes: 440, 470-8144 
Group 1: (Blocks 32768-65535) 
 Backup superblock at 32768, Group descriptors at 32769-32769 
 Reserved GDT blocks at 32770-33007 
 Block bitmap at 241 (bg #0 + 241) 
 Inode bitmap at 256 (bg #0 + 256)
 Inode table at 779-1287 (bg #0 + 779) 
 8668 free blocks, 8142 free inodes, 2 directories 
 Free blocks: 33008-33283, 33332-33791, 33974-33975, 34023-34092, 34094-34104, 34526-34687, 34706-34723, 34817-35374, 35421-35844, 35935-36355, 36357-36863, 38912-39935, 39940-40570, 42620-42623, 42655, 42674-42687, 42721-42751, 42798-42815, 42847, 42875-42879, 42918-42943, 42975, 43000-43007, 43519, 43559-44031, 44042-44543, 44545-45055, 45116-45567, 45601-45631, 45658-45663, 45689-45695, 45736-45759, 45802-45823, 45857-45887, 45919, 45950-45951, 45972-45983, 46014-46015, 46057-46079, 46112-46591, 46921-47103, 49152-49395, 50027-50355, 52237-52255, 52285-52287, 52323-52351, 52383, 52450-52479, 52518-52543, 52584-52607, 52652-52671, 52734-52735, 52743-53247 
 Free inodes: 8147-16288 
Group 2: (Blocks 65536-98303) 
 Block bitmap at 242 (bg #0 + 242) 
 Inode bitmap at 257 (bg #0 + 257) 
 Inode table at 1288-1796 (bg #0 + 1288) 
 6326 free blocks, 8144 free inodes, 0 directories 
 Free blocks: 67042-67583, 72201-72994, 80185-80349, 81191-81919, 90112-94207 
 Free inodes: 16289-24432 
Group 3: (Blocks 98304-131071)

<snip>

每个 柱面组 都有自己的inode位图,该位图用于确定使用哪些inode,以及该组中哪些是空闲的。inode在每个组中都有自己的空间。每个inode都包含有关一个文件的信息,包括属于该文件的数据块的位置。块位图跟踪文件系统中使用和释放的数据块。注意,上面显示的输出中有大量关于文件系统的数据。在很大的文件系统中,组数据可以长达数百页。组元数据包括组中所有空闲数据块的列表。

EXT文件系统实现了保证文件碎片最小化的数据分配策略。减少磁盘碎片化可改善文件系统的性能。这些策略将在下文的EXT4部分中进行介绍。

在某些情况下,我曾遇到的EXT2文件系统的最大问题是在崩溃后可能需要几个小时才能恢复,因为 fsck (file system check)程序需要很长时间才能找到并纠正文件系统中的任何不一致。它曾在我的一台计算机上花费了28个小时的时间,以实现在发生崩溃到重新启动时完全恢复磁盘 -并且这是在磁盘大小为数百兆字节下测试的结果。

EXT3 文件系统的唯一目标是克服 fsck 程序需要大量时间来完全恢复因文件更新操作期间发生的不正确关闭而损坏的磁盘结构的问题。EXT文件系统的唯一增加是 journal ,它预先记录了将对文件系统执行的改动。磁盘结构的其余部分和EXT2中是相同的。

EXT3中的journal并不是直接将数据写入磁盘的数据区域,而是将文件数据及其元数据写入到磁盘上的指定区域。一旦数据安全地存储在硬盘上,它就可以合并到目标文件或附加到目标文件中,而这几乎不会丢失数据。由于该数据被提交到磁盘的数据区域,因此需更新journal以便在发生系统故障时文件系统保持一致状态,然后该journal中的所有数据都被提交。在下次启动时,将检查文件系统是否存在不一致性,然后将journal中剩余的数据提交到磁盘的数据区域以完成对目标文件的更新。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK