The mke2fs
utility is used to create ext2, ext3, and ext4 filesystems. Depending on the preferred filesystem, you can run mkfs.XXX <device>
, where XXX can be ext2, ext3, or ext4, indicating the specific filesystem type to be created. This utility is included in the e2fsprogs
rpm package.
When you run mkfs.ext4
, it writes important data onto the disk that provides information about the structure of the filesystem. mkfs.ext4
creates several data structures on the disk, which include:
In this blog, we explore how many blocks or how much memory is allocated for each of these data structures. Additionally, we will delve into the calculation that determines the memory allocated for each specific structure.
/etc/mke2fs.conf
is a configuration file for mke2fs
. It contains default settings for ext2, ext3, and ext4 filesystems. This file can be modified to change the default settings, or you can to override them by specifying preferred options as command line arguments when using the mkfs
command.
Let’s examine the contents of the /etc/mke2fs.conf
file.
Note: The contents relevant to the ext4 filesystem are displayed
[defaults] base_features = sparse_super,large_file,filetype,resize_inode,dir_index,ext_attr default_mntopts = acl,user_xattr enable_periodic_fsck = 0 blocksize = 4096 inode_size = 256 inode_ratio = 16384 [fs_types] ... ext4 = { features = has_journal,extent,huge_file,flex_bg,metadata_csum,64bit,dir_nlink,extra_isize inode_size = 256 } ...
By default, the features base_features
, and features
are enabled in mkfs.ext4
. However, you can disable or enable these features when you run mkfs.ext4
. Periodic fsck is disabled by default. The default block size is set to 4096 bytes, the inode size is 256 bytes, and the inode ratio is 16384.
The values blocksize
, inode_size
, and inode_ratio
are important as they determine the number of blocks, block groups, and inodes in a filesystem. Among these, blocksize
and inode_size
are self-explanatory, but inode_ratio
needs some explanation.
The inode_ratio
parameter indicates the number of bytes for which an inode is created. That is, an inode is created for every inode_ratio
bytes. In our case, with an inode_ratio
of 16384, mkfs.ext4
creates an inode for every 16384 bytes.
For example, on a 1GiB device, running mkfs.ext4
would create 65536 inodes in the filesystem, because 1GiB/16384 = 65536. That is, an inode is created for every 16384 bytes.
Therefore, the number of inodes in a filesystem is determined by the formula (filesystem size)/(inode_ratio)
.
The ext4 Superblock has a size of 1024 bytes. In a filesytem with a 4k bytes block size, Superblock is placed at 1025th byte of the device, the first 1024 bytes are reserved for installation of boot sectors and other purposes. And the remaining 2048 bytes are unused.
The Block group descriptor stores important statistics related to its corresponding block group. The number of block group descriptors matches the number of block groups present in the filesystem. The collection of all block group descriptors is referred to as the Group Descriptor Table (GDT). The block immediately following the Superblock is used by the GDT, and the entire block is allocated solely for this purpose.
The Block bitmap tracks the usage of all blocks in the filesystem. When a block is in use or reserved for something, the corresponding bit in the block bitmap is set.
Similarly, the Inode bitmap tracks the status of inodes. If an inode is in use, its corresponding bit in the inode bitmap is set.
Each block group in the filesystem has its own block bitmap and inode bitmap. Therefore, the number of block bitmaps is equal to the number of inode bitmaps, which is also equal to the number of block groups.
Since each bitmap occupies a block of memory, the total number of blocks allocated for the bitmaps is equal to twice the number of block groups.
The Inode table is a table of all the inodes in a block group. The size of each inode table is determined by multiplying the number of inodes in the block group by the size of each individual inode.
For example, let’s consider a 1 Gib filesystem with a blocksize of 4k (4096 bytes), an inode_ratio
of 16384, and an inode_size
of 256 bytes. In this case, there are 8192 inodes in each block group. Therefore, the size of each inode table will be 2 Mib (8192 * 256).
To calculate the total number of blocks reserved for all the inode tables, you need to divide the product of the number of block groups and the size of each inode table with the blocksize. (size of each inode table) * (number of block groups)/blocksize
.
In a filesystem with the journaling feature, some blocks are set aside for journaling. The exact number of reserved blocks depends on the size of the filesystem. The following table shows the number of blocks reserved for filesystems of various sizes. The first block within these reserved blocks is initialized with the journal superblock.
When the sparse_super
feature is enabled, backup copies of the superblock and group descriptor table (GDT) are stored in the block groups numbering in powers of 3, 5, 7 (For example: 3, 9, 25, 27, 49,.. etc). On the other hand, if the sparse_super
feature is disabled, backup copies of the superblock and GDT are stored in all block groups of the filesystem.
The /proc/fs/ext4/<device-name>/mb_groups
file provides information about the filesystem’s buddy system. It also gives details about the number of free blocks available in the filesystem.
The columns in the mb_groups
file are as follows:
By examining the contents of the mb_groups
file in a fresh filesystem, we can understand how the blocks are being used for different purposes.
Let’s examine two examples of a filesystem with a size of 1GiB, where one has the sparse_super
feature enabled and the other has it disabled.
The image displays the contents of mb_groups
on a newly created filesystem with the sparse_super
feature enabled.
Here’s an analysis of the block usage in each block group:
Block Group 0:
s_reserved_gdt_blocks
member of ext4_super_block, these are part of resize inode
)
Block Groups 1, 3, 5, 7:
Block group 4: A 1 GiB FS has 524288 blocks, thus 8192 blocks allocated for journal purposes (See the table in journal section).
Block group 2, 6: No blocks are used in these block groups.
The image shows the contents of mb_groups
on a newly created filesystem with the sparse_super
feature disabled.
Here’s an analysis of the block usage in each block group:
Block Group 0:
resize_inode
is not supported when sparse_super
is disabled.)
Block Group 3:
Block Groups 1, 2, 4, 5, 6, 7:
We took a closer look at the different data structures created by the mkfs
command and their memory allocation. These include important components like the superblock, group descriptors, block and inode bitmaps, inode tables, journal superblocks, and more. Knowing the amount of memory reserved/allocated for these different things allows us to understand the filesystem internals better.
mke2fs
, mke2fs.conf
Previous Post
Next Post