调试环境 代码语言: javascript
复制 $ modprobe -v ext4
$ dd if=/dev/zero of=/tmp/disk1 count=30 bs=1M
$ losetup --show -f /tmp/disk1
/dev/loop0
$ mkfs.ext4 /dev/loop0
$ mount /tmp/disk1 /mnt/disk1
关于超级快基本知识 当使用者适应mkfs.ext4 /dev/sdb
时候,系统按照ext4内部的布局规则写入写入先关数据。mount
时候按照内置的布局规则读取这些信息。ext4中涉及的的数据分为两大类,一类是数据
;另外一类是元数据
。 默认扇区大小是512个字节,而磁盘文件系统一般是按照block为单位管理磁盘,默认是4k大小。ext4文件系统为了减少碎片,使文件内容尽量落在相邻的block(这么做为了提高seek性能,尤其是在机械盘呢上)来提高访问的效率,ext4引入了block group
,每个block group
包含多个block,其中一个block用来这个block group中block使用情况。ext4把相邻的block group组成标记为一个flex_bg(flexible block group)。一个blex_bg中所有的block group的data block bitmap
、inode bitmap
、inode table
存放在flex_bg的第一个block group,这样在flex_bg中除过第一个block group,其他的都可以存储实际的数据(其中有些block group还是要存储冗余的ext super block和group descriptors).ext4 super block和grouup descriptors会在每个block group中进行复制。下面简单介绍下block group
的格式: group 0 padding:第一个block group特有的,存储机器的启动信息;除过第一个block group有padding外,其他的block是没有的。 ext4 super block:包含整个磁盘的系统信息 group descriptors:所有block group的信息,每一个group descriptor和一个block group一一对应。这个包含block bimap/inode bitmap/ block从属的block group信息等;占用block是由磁盘大小决定 reserved gdt blocks:方便未来扩展而预留的空间 data block bitmap:存放block group的使用情况的位图。 inode bitmap:当前block group中inode使用情况位图 inode table:描述block group内所有inode的信息,占用大小是由block group中inode数乘以inode大小 data block:存储实际文件数据的block ext4超级块内容分析 在内核中vfs
层定义了通用的struct super_block
超级块,这个超级块中的s_fs_info
指向ext4磁盘文件系统的struct ext4_sb_info
的超级块。 代码语言: javascript
复制 // 内核定义的通用超级块
struct super_block {
// 省略字段
}
// 具体磁盘文件系统ext4的超级块
struct ext4_sb_info {
// 每个 group descriptor 大小
unsigned long s_desc_size;
// 每个block的inode数量
unsigned long s_inodes_per_block;
// 每个block group中的block数量
unsigned long s_blocks_per_group;
unsigned long s_clusters_per_group;
// 每个block group中inode数量
unsigned long s_inodes_per_group;/* Number of inodes in a group */
// 每个block group中inode table数量
unsigned long s_itb_per_group; /* Number of inode table blocks per group */
// 省略其他字段
}
ext4
文件系统中每个块组
会有一个数据机构来描述它,内核使用struct ext4_group_desc
结构来描述每个块组
信息。dumpe2fs
工具转储磁盘时候,Group 0
到Group N
信息都是来自读取struct ext4_group_desc
。代码语言: javascript
复制 struct ext4_group_desc
{
// 数据块位图所在的block号
__le32 bg_block_bitmap_lo;
// inode位图所在的的数据块
__le32 bg_inode_bitmap_lo;
// inode table所在数据块
__le32 bg_inode_table_lo;
// 空闲数据块数量
__le16 bg_free_blocks_count_lo;
// 空闲inodes数量
__le16 bg_free_inodes_count_lo;
// 当前目录的数量
__le16 bg_used_dirs_count_lo;
// falg信息
__le16 bg_flags;
__le32 bg_exclude_bitmap_lo; /* Exclude bitmap for snapshots */
// crc32c(s_uuid grp_num bbitmap) 低位校验
__le16 bg_block_bitmap_csum_lo;/* crc32c(s_uuid grp_num bbitmap) LE */
__le16 bg_inode_bitmap_csum_lo;/* crc32c(s_uuid grp_num ibitmap) LE */
__le16 bg_itable_unused_lo; /* Unused inodes count */
__le16 bg_checksum; /* crc16(sb_uuid group desc) */
__le32 bg_block_bitmap_hi; /* Blocks bitmap block MSB */
__le32 bg_inode_bitmap_hi; /* Inodes bitmap block MSB */
__le32 bg_inode_table_hi; /* Inodes table block MSB */
__le16 bg_free_blocks_count_hi;/* Free blocks count MSB */
__le16 bg_free_inodes_count_hi;/* Free inodes count MSB */
__le16 bg_used_dirs_count_hi; /* Directories count MSB */
__le16 bg_itable_unused_hi; /* Unused inodes count MSB */
__le32 bg_exclude_bitmap_hi; /* Exclude bitmap block MSB */
// crc32c(s_uuid grp_num bbitmap) 高位校验
__le16 bg_block_bitmap_csum_hi;
__le16 bg_inode_bitmap_csum_hi;
__u32 bg_reserved;
};
mkfs.ext4
初始化过程,磁盘大小是30M,一共是标号从0~3
的4个block group
,当使用mkfs.ext4
内核关联一个进程static struct task_struct *ext4_lazyinit_task
来做初始化。代码语言: javascript
复制 static int ext4_run_lazyinit_thread(void)
{
// 启动内核线程,调用ext4_lazyinit_thread 函数铏初始化
ext4_lazyinit_task = kthread_run(ext4_lazyinit_thread,
ext4_li_info, "ext4lazyinit");
if (IS_ERR(ext4_lazyinit_task)) {
int err = PTR_ERR(ext4_lazyinit_task);
ext4_clear_request_list();
kfree(ext4_li_info);
ext4_li_info = NULL;
printk(KERN_CRIT "EXT4-fs: error %d creating inode table "
"initialization threadn",
err);
return err;
}
ext4_li_info->li_state |= EXT4_LAZYINIT_RUNNING;
return 0;
}
/********调用的函数路径******/
ext4_lazyinit_thread [ext4]() {
// 加载block group
ext4_get_group_desc [ext4]();
// 初始化inode table
ext4_init_inode_table [ext4]() {
// 获取block group desc结构
ext4_get_group_desc [ext4]();
// 启动日志
ext4_journal_check_start [ext4]();
// 获取未使用的inode table数量
ext4_itable_unused_count [ext4]();
// 设置 block group中的标记位 bg_inode_table_hi
ext4_inode_table [ext4]();
// 设置 block group的crc
ext4_group_desc_csum_set [ext4]() {
ext4_group_desc_csum [ext4]();
}
}
ext4_get_group_desc [ext4]();
ext4_init_inode_table [ext4]() {
ext4_get_group_desc [ext4]();
ext4_journal_check_start [ext4]();
ext4_inode_table [ext4]();
ext4_group_desc_csum_set [ext4]() {
ext4_group_desc_csum [ext4]();
}
}
ext4_get_group_desc [ext4]();
ext4_init_inode_table [ext4]() {
ext4_get_group_desc [ext4]();
ext4_journal_check_start [ext4]();
ext4_inode_table [ext4]();
ext4_group_desc_csum_set [ext4]() {
ext4_group_desc_csum [ext4]();
}
}
ext4_get_group_desc [ext4]();
ext4_init_inode_table [ext4]() {
ext4_get_group_desc [ext4]();
ext4_journal_check_start [ext4]();
ext4_inode_table [ext4]();
ext4_group_desc_csum_set [ext4]() {
ext4_group_desc_csum [ext4]();
}
}
ext4_remove_li_request.part.119 [ext4]();
}
使用mkfs.ext4
命令后,初始化了磁盘的超级块。dumpe2fs
把整个超级快dump出来,这里 磁盘大小一共是30M
,dump出来后如下: 代码语言: javascript
复制 $ dumpe2fs /dev/loop0
// 文件系统元数据
dumpe2fs 1.45.6 (20-Mar-2020)
Filesystem volume name: <none>
Last mounted on: <not available>
Filesystem UUID: d0b48bf3-4aab-4019-8617-6f4fe1a20268
Filesystem magic number: 0xEF53
Filesystem revision #: 1 (dynamic)
Filesystem features: has_journal ext_attr resize_inode dir_index filetype extent 64bit flex_bg sparse_super large_file huge_file dir_nlink extra_isize metadata_csum
Filesystem flags: signed_directory_hash
Default mount options: user_xattr acl
Filesystem state: clean
Errors behavior: Continue
Filesystem OS type: Linux
Inode count: 7680
Block count: 30720
Reserved block count: 1536
Free blocks: 27990
Free inodes: 7669
First block: 1
Block size: 1024
Fragment size: 1024
Group descriptor size: 64
Reserved GDT blocks: 239
Blocks per group: 8192
Fragments per group: 8192
Inodes per group: 1920
Inode blocks per group: 240
Flex block group size: 16
Filesystem created: Sun Mar 27 19:18:41 2022
Last mount time: n/a
Last write time: Sun Mar 27 19:18:41 2022
Mount count: 0
Maximum mount count: -1
Last checked: Sun Mar 27 19:18:41 2022
Check interval: 0 (<none>)
Lifetime writes: 261 kB
Reserved blocks uid: 0 (user root)
Reserved blocks gid: 0 (group root)
First inode: 11
Inode size: 128
Journal inode: 8
Default directory hash: half_md4
Directory Hash Seed: 46745eac-889b-4456-91bc-989742111935
Journal backup: inode blocks
Checksum type: crc32c
Checksum: 0xda84b217
Journal features: (none)
Journal size: 1024k
Journal length: 1024
Journal sequence: 0x00000001
Journal start: 0
// 一共3个 block group,每个block group的block bitmap和inode bitmap都在第一个block group中存储
// block group 0 存储了其他block group的数据块位图、inode位图、inode table.
Group 0: (Blocks 1-8192) csum 0x2efa
Primary superblock at 1, Group descriptors at 2-2
Reserved GDT blocks at 3-241
// block bitmap和inode bitmap 都存储在第一个block group中
Block bitmap at 242 ( 241), csum 0x9d8af453
Inode bitmap at 246 ( 245), csum 0x494ef22a
Inode table at 250-489 ( 249)
6969 free blocks, 1909 free inodes, 2 directories, 1909 unused inodes
Free blocks: 1224-8192
Free inodes: 12-1920
Group 1: (Blocks 8193-16384) csum 0xcb52 [INODE_UNINIT, BLOCK_UNINIT]
Backup superblock at 8193, Group descriptors at 8194-8194
Reserved GDT blocks at 8195-8433
// 数据块的位图
Block bitmap at 243 (bg #0 242), csum 0x00000000
// inode的位图
Inode bitmap at 247 (bg #0 246), csum 0x00000000
// inode table
Inode table at 490-729 (bg #0 489)
// 空闲块
7951 free blocks, 1920 free inodes, 0 directories, 1920 unused inodes
Free blocks: 8434-16384
Free inodes: 1921-3840
Group 2: (Blocks 16385-24576) csum 0xb0d5 [INODE_UNINIT]
Block bitmap at 244 (bg #0 243), csum 0x1364dcda
Inode bitmap at 248 (bg #0 247), csum 0x00000000
Inode table at 730-969 (bg #0 729)
7168 free blocks, 1920 free inodes, 0 directories, 1920 unused inodes
Free blocks: 17409-24576
Free inodes: 3841-5760
Group 3: (Blocks 24577-30719) csum 0x05de [INODE_UNINIT]
Backup superblock at 24577, Group descriptors at 24578-24578
Reserved GDT blocks at 24579-24817
Block bitmap at 245 (bg #0 244), csum 0x628642b2
Inode bitmap at 249 (bg #0 248), csum 0x00000000
Inode table at 970-1209 (bg #0 969)
5902 free blocks, 1920 free inodes, 0 directories, 1920 unused inodes
Free blocks: 24818-30719
Free inodes: 5761-7680