ext4文件系统解析

1. 简介

Ext4,全称为第四扩展文件系统(Fourth Extended File System),是Linux操作系统中最常用的文件系统之一。它是对先前的Ext2和Ext3文件系统进行改进和增强而设计的。
相较于ext2/ext3,ext4添加了日志功能来增强文件系统的可靠性和稳定性。
相较于ext3的最多支持3级索引导致文件大小和总文件数都受限制,ext4添加了extent数据结构(类似于NTFS中的run list,是一种B+树结构),可以支持更大的文件和理论上无限的文件数量。并且extend结构相比ext3的多级索引结构,检索速度也更快。
ext4增加了flex_bg特性来将多个块组中的Data Bitmap、Inode Bitmap和Inode Table集成到一起,来加速检索的功能。
ext4还增加了sparse_super特性,来稀疏超级块的备份分布,提升性能。

2. 结构

整个磁盘由MBR/GPT和ext4分区组成。ext4分区则由多个块组(Block Group,BG)组成。块组则由Super Block,GPT、Reserved GPT、Data Bitmap、Inocde Bitmap、Inode Table、Data构成。
● Block,ext文件系统中最小操作单位(类似NTFS/FAT中的簇),默认4KB,其大小记录在Super Block上。
● Inode, 索引节点(Index node),每个文件、目录和系统文件(如journal)都有唯一的索引节点号。Inode Table结构体上有记录其对应文件的创建时间、大小、权限以及内容块地址等信息。
● BG,块组(Block Group),为了提升索引的速度,会将多个块归为一组,称为块组。
● Super Block,记录着ext4分区的全局信息,文件系统特性,Block大小,Block数量,GDT大小,Inode数量,Inode大小,BG包含的Block数量,GDT大小,保留GPT块数,Flex Block数,Journal Inode等信息。
● GDP,块组描述表(Group Descriptor Table),记录每个块组(block group)开始和结束的block号码,以及说明每个区段(inodemap、blockmap、inode table)分别介于哪些block号码之间。
● Reserved GDT,其会备份GDP、Super Block、Inode Table等信息,用以在文件系统损坏时进行恢复。
● Data Bitmap,用Bit来标记Block是否使用。在启用了flex_bg特性后,Data Bitmap区描述多个块组中的Block对应的使用与否。
● Inode Bitmap,用Bit来标记Inode Table项是否使用。在启用了flex_bg特性后,Inode Bitmap区描述多个块组中的Inode使用与否。
● Inode Table,Inode Table区记录所有的Inode Table项,每一项对应一个文件/文件夹。Inode Table数量与Data Block数量在文件系统创建时,按一定比例分配,相关信息记录在Super Block上。比例关系可以在创建时设置。
● Data Block区,存储文件夹和文件的内容。
● journal,Journal Inode一般为8,其记录着文件的操作记录,用以在发生异常时通过回滚来恢复数据完整性等,Journal一般会采用缓存机制来提升性能。
● bg_count=(sb.block_count + sb.blocks_of_group - 1)/sb.blocks_of_group
● GDT_block_count=(bg_count*sb.gdt_size + sb.block_size - 1)/sb.block_size
● 特殊Inode

1 损坏数据块链表
2 根目录
3 ACL索引
4 ACL数据
5 引导装载程序
6 未删除的目录
7 预留的块组描述符inode
8日志inode
11 第一个非预留的inode,通常是lost + found目录

ext4的基本结构如下图:
ext4文件系统解析_第1张图片

3. extent

/*
 * This is the extent on-disk structure.
 * It's used at the bottom of the tree.
 */
struct ext4_extent {
	__le32	ee_block;	/* first logical block extent covers */
	__le16	ee_len;		/* number of blocks covered by extent */
	__le16	ee_start_hi;	/* high 16 bits of physical block */
	__le32	ee_start_lo;	/* low 32 bits of physical block */
};

/*
 * This is index on-disk structure.
 * It's used at all the levels except the bottom.
 */
struct ext4_extent_idx {
	__le32	ei_block;	/* index covers logical blocks from 'block' */
	__le32	ei_leaf_lo;	/* pointer to the physical block of the next *
				 * level. leaf or next index could be there */
	__le16	ei_leaf_hi;	/* high 16 bits of physical block */
	__u16	ei_unused;
};

/*
 * Each block (leaves and indexes), even inode-stored has header.
 */
struct ext4_extent_header {
	__le16	eh_magic;	/* probably will support different formats */
	__le16	eh_entries;	/* number of valid entries */
	__le16	eh_max;		/* capacity of store in entries */
	__le16	eh_depth;	/* has tree real underlying blocks? */
	__le32	eh_generation;	/* generation of the tree */
};

extend特性是通过ext4_extent结构体来记录实际文件内容存放信息。
Inode Table结构体上存放着4个ext4_extent,每个ext4_extent结构体对应1个BG(1个Block的Bit总共有40968)的32768个Block,327684KB=128MB。4个ext4_extent对应4个BG,总共512MB。除去元文件信息,剩余的数据信息480MB左右。
ext4文件系统解析_第2张图片
超过480MB的文件则会启用树形结构,Inode Table上则存放ext4_extent_idx,其指向Data Block。Data Block上记录ext4_extent信息,总共可以存放340个ext4_extent结构,则340*128MB=42.5GB,4个Data Block则是170GB。添加一级索引就可以描述170GB文件,一般情况都够用。
ext4文件系统解析_第3张图片

4. 示例

遍历硬盘所有文件。

  1. 获取GDT信息,GDT在Block 2,偏移为1。
    ext4文件系统解析_第4张图片
  2. 读取Inode Table block号。
    ext4文件系统解析_第5张图片
  3. 读取Inode Table
    ext4文件系统解析_第6张图片
    ext4文件系统解析_第7张图片根据ext4_extent获取ee_start_hi=0x2426,此Block对应根目录的内容。
  4. 获取根目录信息
    ext4文件系统解析_第8张图片
    上述信息记录的是ext4_dir_entry_2结构信息
    ext4文件系统解析_第9张图片
    参考结构体,解决inode和文件/文件夹名如下:
    ext4文件系统解析_第10张图片
  5. 检索小文文件
    abc.txt的Inode为13,Inode Table Block为0x426,那么13对应的实际偏移应该是:
    0x4264096 + 12256=4353024 # 因为inode是从1开始的,所以13应对的偏移为12
    ext4文件系统解析_第11张图片
    上面256的数据即为ext4_inode结构体(相关结构体的详细描述见Linux内核代码),绿线框12Byte即为ext4_extent。
    ext4文件系统解析_第12张图片
    可以获取Inode13对应的内容Block为1,对应的地址为0x8601,获取内容如下,正是写入的内容。
    ext4文件系统解析_第13张图片
  6. 检索大文件
    file.txt为1GB的文件,其Inode为12。计算其ext4_inode偏移为:
    0x4264096 + 11256=4352768 # 因为inode是从1开始的,所以12应对的偏移为11
    ext4文件系统解析_第14张图片
    红线对应的内容为ext4_extent_header,eh_entries为1表示当前只有1项有效,eh_depth为1,表示有子项,则当前内容为ext4_extent_idx。
    ext4文件系统解析_第15张图片
    解析ext4_extent_idx结构体,指向的物理块地址为0x3fbf01,这个块上描述的就是ext4_extent_header+大量的ext4_extent。
    ext4文件系统解析_第16张图片
    ext4文件系统解析_第17张图片
    上图绿线为ext4_extent_header,后面的红线及其他的都是ext4_extent。
    ext4文件系统解析_第18张图片
    ext4文件系统解析_第19张图片
  7. 检索目录
    qerdir目录的Inode为131073,通过sb.Inodes_per_group=8192,可以(131073+8191)/8192=17,偏移为131073%8192=1。再通过GDT中记录的Group17对应的Inode table at 524320-524831 。
    ext4文件系统解析_第20张图片
    上图红线对应ext4_extent即为目录的内容信息,其物理块地址为0x82020,其内容如下,只有bbb.txt一个文件,符合预期。
    ext4文件系统解析_第21张图片
    bbb.txt对应的Inode为0x20003(131075)。
    ext4文件系统解析_第22张图片
    其对应的Inode table中ext4_extent如下,其物理地址为0x88001:
    ext4文件系统解析_第23张图片
    0x88001的内容如下,符合预期:
    ext4文件系统解析_第24张图片

5. 总结

写文件操作时,除了更新Data区处,还会相应更新GDT、Inode Bitmap、Block Bitmap、目录区、Inode Table区。
● 针对小于480MB的文件,GDT、目录区、Inode Bitmap,更新较少。Block Bitmap会不停记录使用了的Block,更新较多,Inode Table会不停记录已经使用了的Block数,也更新较多。
● 针对超过480MB的文件,尤其是更大的文件,其会启用extent子节点表。也即在文件大小超过480MB时,会将文件数据块地址信息记录在extent块上,extent块上会不停地更新新占用的Block地址信息。extent块一般分配在分区中间。

6. 代码

代码会显示每个Flex Group的大小,以及文件系统所占大小。
代码
ext4文件系统解析_第25张图片

你可能感兴趣的:(存储,windows,linux,运维)