Commit 16d43b97 authored by Li Chen's avatar Li Chen Committed by Theodore Ts'o
Browse files

ext4: mark fs-verity enable fast-commit ineligible



Fast commits only log operations that have dedicated replay support.
Enabling fs-verity builds a Merkle tree and updates inode and orphan
state in ways that are not described by the fast commit replay tags.
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_end_enable_verity() starts its journal transaction.
This forces that transaction to fall back to a full commit, ensuring
that the fs-verity enable changes are captured by the normal journal
rather than partially encoded in fast commit TLVs.
This change should not affect common workloads but makes fs-verity
enable safer and easier to reason about under fast commit.

Testing:
1. prepare:
    dd if=/dev/zero of=/root/fc_verity.img bs=1M count=0 seek=128
    mkfs.ext4 -O fast_commit,verity -F /root/fc_verity.img
    mkdir -p /mnt/fc_verity && mount -t ext4 -o loop /root/fc_verity.img /mnt/fc_verity
2. Enabled fs-verity on a file and verified reason accounting:
    echo "data" > /mnt/fc_verity/verityfile
    /root/enable_verity /mnt/fc_verity/verityfile
    sync
    tail -n 1 /proc/fs/ext4/loop0/fc_info
    "fs-verity enable":     1
3. Enabled fs-verity on a second file, fsynced it, and checked that the
   ineligible commit counter is updated too:
    echo "data2" > /mnt/fc_verity/verityfile2
    /root/enable_verity /mnt/fc_verity/verityfile2
    /root/fsync_file /mnt/fc_verity/verityfile2
    sync
    /proc/fs/ext4/loop0/fc_info shows "fs-verity enable" incremented and
    fc stats ineligible increased accordingly.

Signed-off-by: default avatarLi Chen <me@linux.beauty>
Link: https://patch.msgid.link/20251211115146.897420-3-me@linux.beauty


Signed-off-by: default avatarTheodore Ts'o <tytso@mit.edu>
parent 87e79fa1
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -2303,6 +2303,7 @@ static const char * const fc_ineligible_reasons[] = {
	[EXT4_FC_REASON_INODE_JOURNAL_DATA] = "Data journalling",
	[EXT4_FC_REASON_ENCRYPTED_FILENAME] = "Encrypted filename",
	[EXT4_FC_REASON_MIGRATE] = "Inode format migration",
	[EXT4_FC_REASON_VERITY] = "fs-verity enable",
};

int ext4_fc_info_show(struct seq_file *seq, void *v)
+1 −0
Original line number Diff line number Diff line
@@ -98,6 +98,7 @@ enum {
	EXT4_FC_REASON_INODE_JOURNAL_DATA,
	EXT4_FC_REASON_ENCRYPTED_FILENAME,
	EXT4_FC_REASON_MIGRATE,
	EXT4_FC_REASON_VERITY,
	EXT4_FC_REASON_MAX
};

+2 −0
Original line number Diff line number Diff line
@@ -231,6 +231,8 @@ static int ext4_end_enable_verity(struct file *filp, const void *desc,
		goto cleanup;
	}

	ext4_fc_mark_ineligible(inode->i_sb, EXT4_FC_REASON_VERITY, handle);

	err = ext4_orphan_del(handle, inode);
	if (err)
		goto stop_and_cleanup;
+3 −1
Original line number Diff line number Diff line
@@ -103,6 +103,7 @@ TRACE_DEFINE_ENUM(EXT4_FC_REASON_FALLOC_RANGE);
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_MAX);

#define show_fc_reason(reason)						\
@@ -117,7 +118,8 @@ TRACE_DEFINE_ENUM(EXT4_FC_REASON_MAX);
		{ EXT4_FC_REASON_FALLOC_RANGE,	"FALLOC_RANGE"},	\
		{ EXT4_FC_REASON_INODE_JOURNAL_DATA,	"INODE_JOURNAL_DATA"}, \
		{ EXT4_FC_REASON_ENCRYPTED_FILENAME,	"ENCRYPTED_FILENAME"}, \
		{ EXT4_FC_REASON_MIGRATE,		"MIGRATE"})
		{ EXT4_FC_REASON_MIGRATE,		"MIGRATE"},	\
		{ EXT4_FC_REASON_VERITY,		"VERITY"})

TRACE_DEFINE_ENUM(CR_POWER2_ALIGNED);
TRACE_DEFINE_ENUM(CR_GOAL_LEN_FAST);