一、前言
《抛开代码细节看文件系统组织方式》一文中,主要从UFS上数据入手,通过对比大小不同的两个文件系统,以及一些常见的文件操作,对F2FS在磁盘上分布有了基础的了解。
本篇文章就深入到代码细节,深入分析一下F2FS各个区域中保存内容的细节。
二、superblock相关结构体
2.1 Superblock相关结构体定义
2.2 superblock相关结构体注释说明
2.2.1 struct f2fs_super_block
定义 | 示例值 | 注释说明 |
__le32 magic | 0xF2F52010 | Magic Number F2FS固定值0xf2f52010 |
__le16 major_ver | 1 | |
__le16 minor_ver | 16 | |
__le32 log_sectorsize | 9 | |
__le32 log_sectors_per_block | 3 | |
__le32 log_blocksize | 12 | |
__le32 log_blocks_per_seg | 9 | |
__le32 segs_per_sec | 1 | 每个section包含多少个segment,1表示每个section包含1个segment |
__le32 secs_per_zone | 1 | 每个zone包含多少个section,1表示每个zone包含1个section |
__le32 checksum_offset | 0 | |
__le64 block_count | 25600 | block数量,每个block的size为4K,25600*4K=100MB,包括superblock/CP/SIT/NAT/SSA/MA区域 |
__le32 section_count | 42 | MA区section数量 |
__le32 segment_count | 49 | segment数量,不包含superblock(2MB) |
__le32 segment_count_ckpt | 2 | check point的segment数量,固定为2MB |
__le32 segment_count_sit | 2 | SIT区segment数量,固定为2MB |
__le32 segment_count_nat | 2 | NAT区segment数量,会随分区大小变化而变化 |
__le32 segment_count_ssa | 1 | SSA区segment数量 |
__le32 segment_count_main | 42 | MA区segment数量 |
__le32 segment0_blkaddr | 512 | segment0的blkaddr地址(不包含superblock) |
__le32 cp_blkaddr | 512 | CP区起始blkaddr地址 |
__le32 sit_blkaddr | 1536 | SIT区起始blkaddr地址 |
__le32 nat_blkaddr | 2560 | NAT区起始blkaddr地址 |
__le32 ssa_blkaddr | 3584 | SSA区起始blkaddr地址 |
__le32 main_blkaddr | 4096 | MA区起始blkaddr地址 |
__le32 root_ino | 3 | root inode number |
__le32 node_ino | 1 | node inode number |
__le32 meta_ino | 2 | meta inode number |
__u8 uuid[16] | 0x11,0xB3,0xA9,0x1D,0x83,0xA3,0x46,0xAB,0x8A,0xC3,0x5D,0xE7,0x44,0xC5,0x8A,0x0F | uuid |
__le16 volume_name[MAX_VOLUME_NAME] | | |
__le32 extension_count | 36 | |
__u8 extension_list[F2FS_MAX_EXTENSION][F2FS_EXTENSION_LEN] | "mp", "wm", "og", "jp", "avi", "m4v", "m4p", "mkv", "mov", "webm", "wav", "m4a", "3gp", "opus", "flac", "gif", "png", "svg", "webp", "jar", "deb", "iso", "gz", "xz", "zst", "pdf", "pyc", "ttc", "ttf", "exe | |
__le32 cp_payload | 0x0 | |
__u8 version[VERSION_LEN] | 5.15.123-android13-8-o-gdad242538aa2 | 执行fsck或挂载等操作后文件系统的内核信息 |
__u8 init_version[VERSION_LEN] | 5.15.123-android13-8-o-gdad242538aa2 | 初始化创建文件系统时的内核信息 |
__le32 feature | 0x2499 | 文件系统特定feature,每一个表示一个feature |
__u8 encryption_level | | |
__u8 encrypt_pw_salt[16] | | |
struct f2fs_device devs[MAX_DEVICES] | | |
__le32 qf_ino[F2FS_MAX_QUOTAS] | | |
__u8 hot_ext_count | | |
__le16 s_encoding | | |
__le16 s_encoding_flags | | |
__u8 s_stop_reason[MAX_STOP_REASON] | | |
__u8 reserved[274] | | |
__le32 crc | | |
三、SIT相关结构体
3.1 SIT 关键结构体定义
3.2 SIT关键结构体注释说明
3.2.1 struct f2fs_sit_block结构体
定义 | 注释说明 |
struct f2fs_sit_entry entries[SIT_ENTRY_PER_BLOCK]; | 结构体占用空间为4K,由55个f2fs_sit_entry结构体组成 |
3.2.2 struct f2fs_sit_entry
定义 | 注释说明 |
__le16 vblocks; | vblocks[9:0]表示当前segment有多少个有效的block,vblocks[15:10]表示segment的类型,类型有(hot/warn/cold)*(data/node)这些类型 |
__u8 valid_map[SIT_VBLOCK_MAP_SIZE]; | 8*64=512 bit,512位的位图表示一个segment中block的使用情况,一个segment大小为2MB,包含512个block。 |
__le64 mtime; | segment最后一次GC时间,用于GC相关流程 |
3.3 图解SIT关键结构体
SIT区域中的block(4K)存放的f2fs_sit_block类型的数据结构。每个f2fs_sit_block中由55个f2fs_sit_entry结构体数组组成,每个f2fs_sit_entry管理一个segment。对应的磁盘上的布局结构如下。
四、NAT相关结构体注释说明
4.1 NAT关键结构体定义
4.2 NAT关键结构体注释说明
4.2.1 struct f2fs_nat_block
定义 | 注释说明 |
struct f2fs_nat_entry entries[NAT_ENTRY_PER_BLOCK]; | 结构体占用空间为4K,由455个f2fs_nat_entry结构体组成 |
4.2.2 struct f2fs_nat_entry
定义 | 注释说明 |
__u8 version; | |
__le32 ino; | inode number,也就是文件inode的编号 |
__le32 block_addr; | blk地址 |
4.3图解NAT关键结构体
NAT区域的block(4K)存放的是struct f2fs_nat_block结构体,
五、SSA相关结构体
5.1 SSA关键结构体定义
5.2 SSA关键结构体注释说明
5.2.1 struct f2fs_summary_block
定义 | 注释说明 |
struct f2fs_summary entries[ENTRIES_IN_SUM]; | 每个f2fs_summary管理一个block,所以共512个f2fs_summary结构体 |
struct f2fs_journal journal; | NAT/SIT 操作日志,或拓展信息 |
struct summary_footer footer; | segment类型以及当前结构体的校验和 |
5.2.2 struct f2fs_summary
定义 | 注释说明 |
__le32 nid; | 当前block属于哪个node id |
__u8 version; | |
__le16 ofs_in_node; | node 的offset编号,后面章节分析文件布局时可以看到相关介绍 |
5.2.3 struct f2fs_journal
5.2.4 summary_footer
定义 | 注释 |
unsigned char entry_type; | summary 管理的segment类型 |
__le32 check_sum | 校验和 |
5.3 图解SSA关键结构体
六、MA相关结构体
MA区域(主存储区)主要分为两大类,一类是node类型,另外一类是data类型。node保存的管理数据,data保存的就是通常理解的文件数据。我们重点分析一下node类型的关键结构体,之后再展示一下文件相关的结构体及组织方式。
6.1 node关键数据结构
6.1.1 struct f2fs_inode关键定义
6.1.2 struct direct_node关键数据结构
direct_node结构体保存blk地址
6.1.3 struct indirect_node关键数据结构
Indirect_node类型结构体,主要使用数组保存nid
6.2图解f2fs_node关键数据结构
6.2.1 f2fs_inode类型的f2fs_node
f2fs_inode类型的数据主要有三部分组成
元数据:保存文件的大小,修改时间,文件名等
i_addr:共932个地址,指向当前文件data数据保存的block地址
i_nid:共5个,它指向的是f2fs_node类型的nid,根据使用方法,有分为2个direct类型的node,2个indirect类型的node,1个double-indirect类型的node
6.2.2 direct_node类型的f2fs_node
direct_node类型的f2fs_node,有一个1018个长度的数组,每个元素可以保存一个block地址
6.2.3 indirect_node类型的f2fs_node
indirect_node类型的f2fs_node与direct_node类似,不过indirect_node保存的nid,所以它保存的是对应node的地址。而direct_node保存的是data block的地址。
6.3文件相关结构体及组织方式总览
从上面的介绍,我们总体看一下文件的组织方式。根据文件的大小,这里的direct_node或indirect_node并不是每个文件都需要
另外当文件较小,为了节约存储空间,文件可能还会使用inline保存。也就是将data数据直接保存到f2fs_inode中,如下图