Preventing Sparse Allocation in ext4 Loopback Filesystems
Introduction
When creating ext4 filesystems on loopback devices (image files), you may encounter unexpected behavior where a fully allocated image file becomes sparse after mounting. This article explains why this happens and how to prevent it.
Problem
When creating an ext4 filesystem on a fully allocated file and then mounting it, some blocks may be unexpectedly optimized or trimmed, potentially resulting in a sparse file. This behavior can be problematic in situations where you need the backing file to remain fully allocated to ensure the mounted filesystem stays robust against ENOSPC (no space left on device) errors on the host filesystem.
Symptoms
The issue can be observed through the following sequence:
-
Create an allocated file of roughly 5 GB:
fallocate -l 5368709120 cache.img
-
Confirm the allocation:
stat "--printf=%b\n" cache.img # Output: 10485784
-
Create an ext4 filesystem:
mkfs.ext4 -E nodiscard cache.img
-
Check allocation again:
stat "--printf=%b\n" cache.img # Output: 10485784
-
Mount the filesystem:
mount -o defaults,nodiscard cache.img /mnt/test
-
After a short period, check allocation:
stat "--printf=%b\n" cache.img # Output: 10321936
Notice that the number of allocated blocks may decrease after mounting, indicating that the file has become sparse despite using the nodiscard
option.
Resolution
To prevent ext4 from sparsifying the loopback file during the first mount, use the following options when creating the filesystem:
mkfs.ext4 -E nodiscard,lazy_itable_init=0,lazy_journal_init=0 cache.img
These options disable the lazy initialization features that defer part of the filesystem creation to the kernel at first mount time, which can cause the sparsification.
Root Cause
The issue can occur because ext4's default behavior includes lazy initialization of the inode table and journal. When using the default settings:
mkfs.ext4
creates the filesystem but defers some initialization work- During the first mount, the kernel completes the initialization
- As part of this process, certain I/O patterns or optimizations may lead to blocks being treated as sparse, depending on the host filesystem and configuration
The lazy_itable_init=0
and lazy_journal_init=0
options force more complete initialization during filesystem creation, helping to prevent deferred work that could result in sparsification.
Notes
- This behavior is specific to ext4 filesystems. Other filesystems like XFS do not typically exhibit this behavior.
- The
nodiscard
mount option alone may be insufficient to prevent this behavior in all cases. - While disabling lazy initialization can prevent sparsification, it may increase the time required to create the filesystem.
References
Rocky Linux Filesystem Guide
ext4 mkfs documentation
ext4 mount options