[PATCH AUTOSEL 6.19-5.15] ext4: mark group extend fast-commit ineligible

Sasha Levin
2026-02-14T21:27:15Z

From: Li Chen <me@linux.beauty>

[ Upstream commit 1f8dd813a1c771b13c303f73d876164bc9b327cc ]

Fast commits only log operations that have dedicated replay support.
EXT4_IOC_GROUP_EXTEND grows the filesystem to the end of the last
block group and updates the same on-disk metadata without going
through the fast commit tracking paths.
In practice these operations are rare and usually followed by further
updates, but mixing them into a fast commit makes the overall
semantics harder to reason about and risks replay gaps if new call
sites appear.

Teach ext4 to mark the filesystem fast-commit ineligible when
EXT4_IOC_GROUP_EXTEND grows the filesystem.
This forces those transactions to fall back to a full commit,
ensuring that the group extension changes are captured by the normal
journal rather than partially encoded in fast commit TLVs.
This change should not affect common workloads but makes online
resize via GROUP_EXTEND safer and easier to reason about under fast
commit.

Testing:
1. prepare:
dd if=/dev/zero of=/root/fc_resize.img bs=1M count=0 seek=256
mkfs.ext4 -O fast_commit -F /root/fc_resize.img
mkdir -p /mnt/fc_resize && mount -t ext4 -o loop /root/fc_resize.img /mnt/fc_resize
2. Extended the filesystem to the end of the last block group using a
helper that calls EXT4_IOC_GROUP_EXTEND on the mounted filesystem
and checked fc_info:
./group_extend_helper /mnt/fc_resize
cat /proc/fs/ext4/loop0/fc_info
shows the "Resize" ineligible reason increased.
3. Fsynced a file on the resized filesystem and confirmed that the fast
commit ineligible counter incremented for the resize transaction:
touch /mnt/fc_resize/file
/root/fsync_file /mnt/fc_resize/file
sync
cat /proc/fs/ext4/loop0/fc_info

Signed-off-by: Li Chen <me@linux.beauty>
Link: https://patch.msgid.link/20251211115146.897420-6-me@linux.beauty
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---

LLM Generated explanations, may be completely bogus:

### 4. DETAILED FINDINGS

This is extremely revealing. The investigation shows:

**A real gap exists:** `EXT4_IOC_RESIZE_FS` already has
`ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_RESIZE, NULL)`, but
`EXT4_IOC_GROUP_EXTEND` (and `EXT4_IOC_GROUP_ADD` in a sibling commit)
do **not**. This is an inconsistency — all three ioctls perform
filesystem geometry changes that are not supported by fast commit
replay.

**No replay support for geometry changes:** The fast commit replay logic
only handles file-level operations (add_range, del_range, link, unlink,
creat, inode). There are NO replay tags for superblock or group
descriptor changes. If `GROUP_EXTEND` runs and a fast commit is used
instead of a full journal commit, the geometry changes would not be
replayed on crash recovery.

**This is a data integrity issue:** If a fast commit transaction
includes both file operations (which are tracked) and geometry changes
from `GROUP_EXTEND` (which are untracked), crash recovery could replay
the file operations against stale filesystem geometry, leading to silent
metadata inconsistency or corruption.

### 5. CLASSIFICATION

This is a **correctness/data integrity fix**, not a feature addition. It
closes a gap where filesystem metadata changes could be lost or
inconsistently replayed after a crash. The `EXT4_FC_REASON_RESIZE` enum
value already exists — only the missing call site is added.

### 6. SCOPE AND RISK

- **Size:** 2 lines added. Minimal.
- **Risk:** Extremely low. The only effect is forcing a full journal
commit instead of a fast commit during `GROUP_EXTEND`. Full commits
are always correct; fast commits are the optimization. This is a
fallback to the safe path.
- **Subsystem:** ext4 filesystem — widely used, data integrity matters
enormously.
- **Could it break anything?** No. A full commit is strictly more
conservative than a fast commit. The worst case is a minor performance
impact during online resize, which is an infrequent operation.

### 7. USER IMPACT

- **Who is affected?** Anyone using ext4 with fast_commit enabled who
performs online resize via `GROUP_EXTEND`. While this is not a common
operation, when it does happen, data integrity on crash recovery is
critical.
- **Severity if triggered:** Without this fix, crash recovery after
`GROUP_EXTEND` + fast commit could result in filesystem metadata
inconsistency — potentially data corruption.
- **Practical likelihood:** Low frequency, but high severity when it
occurs.

### 8. DEPENDENCY CHECK

- The `EXT4_FC_REASON_RESIZE` enum already exists in stable trees (it
was added when `RESIZE_FS` was given this marking).
- The `ext4_fc_mark_ineligible()` function already exists.
- This is a self-contained, standalone fix with no dependencies on other
commits.
- There is a sibling commit for `GROUP_ADD` that would be good to
backport together, but each stands alone.

### 9. STABLE KERNEL RULES ASSESSMENT

| Criterion | Assessment |
|-----------|-----------|
| Obviously correct and tested | Yes — mirrors existing pattern for
RESIZE_FS, tested by author |
| Fixes a real bug | Yes — missing fast-commit ineligibility marking can
lead to incomplete crash recovery |
| Important issue | Yes — data integrity / potential corruption on crash
recovery |
| Small and contained | Yes — 2 lines in one file |
| No new features | Correct — uses existing infrastructure |
| Applies cleanly | Very likely — minimal change to stable code |

### 10. RISK vs BENEFIT

- **Risk:** Near zero. Forces a safe fallback path for a rare operation.
- **Benefit:** Prevents potential filesystem metadata inconsistency
after crash during online resize with fast commit enabled.

### CONCLUSION

This is a small, surgical, correctness fix for a real gap in ext4's fast
commit mechanism. The `RESIZE_FS` ioctl already had this protection, but
`GROUP_EXTEND` was missed. The fix prevents potential data integrity
issues during crash recovery. It uses existing infrastructure
(`EXT4_FC_REASON_RESIZE` and `ext4_fc_mark_ineligible()`), is self-
contained, and has effectively zero regression risk. It meets all stable
kernel criteria.

**YES**

fs/ext4/ioctl.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/fs/ext4/ioctl.c b/fs/ext4/ioctl.c
index 5109b005e0286..e5e197ac7d88b 100644
--- a/fs/ext4/ioctl.c
+++ b/fs/ext4/ioctl.c
@@ -1612,6 +1612,8 @@ static long __ext4_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)

err = ext4_group_extend(sb, EXT4_SB(sb)->s_es, n_blocks_count);
if (EXT4_SB(sb)->s_journal) {
+ ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_RESIZE,
+ NULL);
jbd2_journal_lock_updates(EXT4_SB(sb)->s_journal);
err2 = jbd2_journal_flush(EXT4_SB(sb)->s_journal, 0);
jbd2_journal_unlock_updates(EXT4_SB(sb)->s_journal);
--
2.51.0