From: Li Chen <me@linux.beauty>
To: "Theodore Ts'o" <tytso@mit.edu>,
Andreas Dilger <adilger.kernel@dilger.ca>,
Steven Rostedt <rostedt@goodmis.org>,
Masami Hiramatsu <mhiramat@kernel.org>,
Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
linux-ext4@vger.kernel.org, linux-kernel@vger.kernel.org,
linux-trace-kernel@vger.kernel.org
Cc: Li Chen <me@linux.beauty>
Subject: [RFC 3/5] ext4: mark move extents fast-commit ineligible
Date: Thu, 11 Dec 2025 19:51:40 +0800 [thread overview]
Message-ID: <20251211115146.897420-4-me@linux.beauty> (raw)
In-Reply-To: <20251211115146.897420-1-me@linux.beauty>
Fast commits only log operations that have dedicated replay support.
EXT4_IOC_MOVE_EXT swaps extents between regular files and may copy
data, rewriting the affected inodes' block mapping layout 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 for the
journal transactions used by move_extent_per_page() when
EXT4_IOC_MOVE_EXT runs.
This forces those transactions to fall back to a full commit,
ensuring that these multi-inode extent swaps are captured by the
normal journal rather than partially encoded in fast commit TLVs.
This change should not affect common workloads but makes online
defragmentation safer and easier to reason about under fast commit.
Testing:
1. prepare:
dd if=/dev/zero of=/root/fc_move.img bs=1M count=0 seek=256
mkfs.ext4 -O fast_commit -F /root/fc_move.img
mkdir -p /mnt/fc_move && mount -t ext4 -o loop \
/root/fc_move.img /mnt/fc_move
2. Created two files, ran EXT4_IOC_MOVE_EXT via e4defrag, and checked
the ineligible reason statistics:
fallocate -l 64M /mnt/fc_move/file1
cp /mnt/fc_move/file1 /mnt/fc_move/file2
e4defrag /mnt/fc_move/file1
cat /proc/fs/ext4/loop0/fc_info
shows "Move extents": > 0 and fc stats ineligible > 0.
Signed-off-by: Li Chen <me@linux.beauty>
---
fs/ext4/fast_commit.c | 1 +
fs/ext4/fast_commit.h | 1 +
fs/ext4/move_extent.c | 1 +
include/trace/events/ext4.h | 4 +++-
4 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/fs/ext4/fast_commit.c b/fs/ext4/fast_commit.c
index 242b69e5fe13..0ef2154a2b1f 100644
--- a/fs/ext4/fast_commit.c
+++ b/fs/ext4/fast_commit.c
@@ -2304,6 +2304,7 @@ static const char * const fc_ineligible_reasons[] = {
[EXT4_FC_REASON_ENCRYPTED_FILENAME] = "Encrypted filename",
[EXT4_FC_REASON_MIGRATE] = "Inode format migration",
[EXT4_FC_REASON_VERITY] = "fs-verity enable",
+ [EXT4_FC_REASON_MOVE_EXT] = "Move extents",
};
int ext4_fc_info_show(struct seq_file *seq, void *v)
diff --git a/fs/ext4/fast_commit.h b/fs/ext4/fast_commit.h
index 20f65135208f..2f77a37fb101 100644
--- a/fs/ext4/fast_commit.h
+++ b/fs/ext4/fast_commit.h
@@ -99,6 +99,7 @@ enum {
EXT4_FC_REASON_ENCRYPTED_FILENAME,
EXT4_FC_REASON_MIGRATE,
EXT4_FC_REASON_VERITY,
+ EXT4_FC_REASON_MOVE_EXT,
EXT4_FC_REASON_MAX
};
diff --git a/fs/ext4/move_extent.c b/fs/ext4/move_extent.c
index 4b091c21908f..5a5e91078528 100644
--- a/fs/ext4/move_extent.c
+++ b/fs/ext4/move_extent.c
@@ -287,6 +287,7 @@ move_extent_per_page(struct file *o_filp, struct inode *donor_inode,
*err = PTR_ERR(handle);
return 0;
}
+ ext4_fc_mark_ineligible(sb, EXT4_FC_REASON_MOVE_EXT, handle);
orig_blk_offset = orig_page_offset * blocks_per_page +
data_offset_in_page;
diff --git a/include/trace/events/ext4.h b/include/trace/events/ext4.h
index 224ab12ee83f..56e60080e759 100644
--- a/include/trace/events/ext4.h
+++ b/include/trace/events/ext4.h
@@ -104,6 +104,7 @@ TRACE_DEFINE_ENUM(EXT4_FC_REASON_INODE_JOURNAL_DATA);
TRACE_DEFINE_ENUM(EXT4_FC_REASON_ENCRYPTED_FILENAME);
TRACE_DEFINE_ENUM(EXT4_FC_REASON_MIGRATE);
TRACE_DEFINE_ENUM(EXT4_FC_REASON_VERITY);
+TRACE_DEFINE_ENUM(EXT4_FC_REASON_MOVE_EXT);
TRACE_DEFINE_ENUM(EXT4_FC_REASON_MAX);
#define show_fc_reason(reason) \
@@ -119,7 +120,8 @@ TRACE_DEFINE_ENUM(EXT4_FC_REASON_MAX);
{ EXT4_FC_REASON_INODE_JOURNAL_DATA, "INODE_JOURNAL_DATA"}, \
{ EXT4_FC_REASON_ENCRYPTED_FILENAME, "ENCRYPTED_FILENAME"}, \
{ EXT4_FC_REASON_MIGRATE, "MIGRATE"}, \
- { EXT4_FC_REASON_VERITY, "VERITY"})
+ { EXT4_FC_REASON_VERITY, "VERITY"}, \
+ { EXT4_FC_REASON_MOVE_EXT, "MOVE_EXT"})
TRACE_DEFINE_ENUM(CR_POWER2_ALIGNED);
TRACE_DEFINE_ENUM(CR_GOAL_LEN_FAST);
--
2.51.0
next prev parent reply other threads:[~2025-12-11 11:52 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-12-11 11:51 [RFC 0/5] ext4: mark more ops fast-commit ineligible Li Chen
2025-12-11 11:51 ` [RFC 1/5] ext4: mark inode format migration " Li Chen
2025-12-11 11:51 ` [RFC 2/5] ext4: mark fs-verity enable " Li Chen
2025-12-11 11:51 ` Li Chen [this message]
2025-12-11 11:51 ` [RFC 4/5] ext4: mark group add " Li Chen
2025-12-11 11:51 ` [RFC 5/5] ext4: mark group extend " Li Chen
2026-01-19 2:58 ` Theodore Tso
2026-01-19 3:03 ` Theodore Tso
2026-01-19 12:37 ` Li Chen
2026-01-28 18:05 ` [RFC 0/5] ext4: mark more ops " Theodore Ts'o
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251211115146.897420-4-me@linux.beauty \
--to=me@linux.beauty \
--cc=adilger.kernel@dilger.ca \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=mhiramat@kernel.org \
--cc=rostedt@goodmis.org \
--cc=tytso@mit.edu \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox