Ext4 filesystem: extent, flex_bg, sparse_super
Part 1 — Ext4 filesystem: data blocks, super blocks, inode structure
Part 3 — Ext4 file system: Delayed allocation, dirty data blocks
You can examine your filesystem with dumpe2fs:
I created the ext4 filesystem with the default parameters of mkfs.ext4 (see /etc/mke2fs.conf).
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
In this part, I’ll walk through only a couple of features of ext4.
ext2/ext3 uses the traditional indirect scheme: Direct blocks, indirect blocks, double indirect blocks, triple indirect blocks, etc.
In the traditional indirect block map, if you need to allocate 500 contiguous data blocks to a file, the file system maps the address of 500 data blocks. Also, if you want to read a big file, the file system will traverse through all indirect blocks.
In Ext4, the indirect map has been replaced with the extent (or extents) tree. Let’s say, the file system needs to allocate 500 contiguous data blocks to a file, ext4 file system will store the first block’s address and the number of contiguous data blocks. Ext4 will hold multiple blocks ranges if the file is fragmented.
Extent tree looks like:
I have created two files in ext 4: a.txt (10 MB), b.txt (500 MB). I looked at the file structure via debugfs:
I created the same files with the same sizes on ext2:
If you want to dive into the inode structure, you might want to use inode_dump:
0xf30a is the magic value for the extent header (see). You should see the magic value as 0af3 as all fields in ext4 are stored as little-endian. If the inode has f30a, it means the inode has the extent feature. The following values match with the struct ext4_extent_header.
eh_magic: extent header magic value
eh_entries: number of valid entries in the extent tree
eh_max: total number of entries that can be stored in the extent tree
eh_depth: depth of the extent node (it can be at most 5)
Let’s say, you want to debug your inode blocks. You can view an inode block.
First of all, you need to know the block range. In this case, from 34328 to 34342 are allocated:
I read block number 34341 via block_dump:
Or you can read a block via dd:
You can get the extent tree mappings via fiemap(see):
You can view extent offsets via filefrag:
You can display the extent tree with its levels via debugfs:
A block group consists of contiguous blocks combined. A flexible block group consists of a contiguous block group.
Each block group has inode bitmap, data block bitmap, group descriptor table (GDT), (sometimes superblock), etc. if flex_bg is enabled in ext4, the bitmap, GDT, superblock, etc of each block will be stored in the first group. Thus, only data blocks will be allocated in the block groups.
Number of groups: 16777216 / 32768 = 512
Number of flexible groups: 512 / 16 = 32
If sparse_super is enabled, the block group numbers 0, 1, and powers of 3, 5, and 7 will have backup superblocks. (e.g.: 343, 243, 125, 81, etc.).
What are the group flags?
INODE_UNINT: Inode bitmap and Inode table not initialized yet.
BLOCK_UNINT: Block bitmap has not yet been initialized.
ITABLE_ZEROED: Inode bitmap table zeroed (Assuming not all nodes are used initially).