Linux EXT4 FS development
 help / color / mirror / Atom feed
From: Li Chen <me@linux.beauty>
To: linux-ext4@vger.kernel.org, "Theodore Ts'o" <tytso@mit.edu>,
	Andreas Dilger <adilger.kernel@dilger.ca>,
	linux-kernel@vger.kernel.org
Cc: Harshad Shirwadkar <harshadshirwadkar@gmail.com>,
	Li Chen <me@linux.beauty>
Subject: [RFC PATCH 2/4] ext4: add dax_fc_bytelog mount option
Date: Thu, 26 Feb 2026 18:17:30 +0800	[thread overview]
Message-ID: <20260226101736.2271952-3-me@linux.beauty> (raw)
In-Reply-To: <20260226101736.2271952-1-me@linux.beauty>

Add dax_fc_bytelog={off,on,force} to control the DAX ByteLog fast commit
backend.
Initialize the ByteLog ring before fast commit replay and release it on
unmount.

Signed-off-by: Li Chen <me@linux.beauty>
---
 fs/ext4/super.c | 77 ++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 76 insertions(+), 1 deletion(-)

diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 504148b2142b..3645456a61dd 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -1368,6 +1368,7 @@ static void ext4_put_super(struct super_block *sb)
 	sbi->s_ea_block_cache = NULL;
 
 	ext4_stop_mmpd(sbi);
+	ext4_fc_bytelog_release(sb);
 
 	brelse(sbi->s_sbh);
 	sb->s_fs_info = NULL;
@@ -1685,6 +1686,8 @@ enum {
 	Opt_max_dir_size_kb, Opt_nojournal_checksum, Opt_nombcache,
 	Opt_no_prefetch_block_bitmaps, Opt_mb_optimize_scan,
 	Opt_errors, Opt_data, Opt_data_err, Opt_jqfmt, Opt_dax_type,
+	Opt_dax_fc_bytelog, Opt_dax_fc_bytelog_off, Opt_dax_fc_bytelog_on,
+	Opt_dax_fc_bytelog_force,
 #ifdef CONFIG_EXT4_DEBUG
 	Opt_fc_debug_max_replay, Opt_fc_debug_force
 #endif
@@ -1724,6 +1727,13 @@ static const struct constant_table ext4_param_dax[] = {
 	{}
 };
 
+static const struct constant_table ext4_param_dax_fc_bytelog[] = {
+	{"off",		Opt_dax_fc_bytelog_off},
+	{"on",		Opt_dax_fc_bytelog_on},
+	{"force",	Opt_dax_fc_bytelog_force},
+	{}
+};
+
 /*
  * Mount option specification
  * We don't use fsparam_flag_no because of the way we set the
@@ -1780,6 +1790,8 @@ static const struct fs_parameter_spec ext4_param_specs[] = {
 	fsparam_flag	("i_version",		Opt_removed),
 	fsparam_flag	("dax",			Opt_dax),
 	fsparam_enum	("dax",			Opt_dax_type, ext4_param_dax),
+	fsparam_enum("dax_fc_bytelog", Opt_dax_fc_bytelog,
+		     ext4_param_dax_fc_bytelog),
 	fsparam_u32	("stripe",		Opt_stripe),
 	fsparam_flag	("delalloc",		Opt_delalloc),
 	fsparam_flag	("nodelalloc",		Opt_nodelalloc),
@@ -1965,6 +1977,7 @@ ext4_sb_read_encoding(const struct ext4_super_block *es)
 #define EXT4_SPEC_s_fc_debug_max_replay		(1 << 17)
 #define EXT4_SPEC_s_sb_block			(1 << 18)
 #define EXT4_SPEC_mb_optimize_scan		(1 << 19)
+#define EXT4_SPEC_s_dax_fc_bytelog		BIT(20)
 
 struct ext4_fs_context {
 	char		*s_qf_names[EXT4_MAXQUOTAS];
@@ -2370,6 +2383,26 @@ static int ext4_parse_param(struct fs_context *fc, struct fs_parameter *param)
 		ext4_msg(NULL, KERN_INFO, "dax option not supported");
 		return -EINVAL;
 #endif
+	case Opt_dax_fc_bytelog:
+		switch (result.uint_32) {
+		case Opt_dax_fc_bytelog_off:
+			ctx_clear_mount_opt2(ctx, EXT4_MOUNT2_DAX_FC_BYTELOG);
+			ctx_clear_mount_opt2(ctx,
+					     EXT4_MOUNT2_DAX_FC_BYTELOG_FORCE);
+			break;
+		case Opt_dax_fc_bytelog_on:
+			ctx_set_mount_opt2(ctx, EXT4_MOUNT2_DAX_FC_BYTELOG);
+			ctx_clear_mount_opt2(ctx,
+					     EXT4_MOUNT2_DAX_FC_BYTELOG_FORCE);
+			break;
+		case Opt_dax_fc_bytelog_force:
+			ctx_set_mount_opt2(ctx, EXT4_MOUNT2_DAX_FC_BYTELOG);
+			ctx_set_mount_opt2(ctx,
+					   EXT4_MOUNT2_DAX_FC_BYTELOG_FORCE);
+			break;
+		}
+		ctx->spec |= EXT4_SPEC_s_dax_fc_bytelog;
+		return 0;
 	case Opt_data_err:
 		if (result.uint_32 == Opt_data_err_abort)
 			ctx_set_mount_opt(ctx, m->mount_opt);
@@ -2819,7 +2852,22 @@ static int ext4_check_opt_consistency(struct fs_context *fc,
 			    !(sbi->s_mount_opt2 & EXT4_MOUNT2_DAX_INODE))) {
 			goto fail_dax_change_remount;
 		}
-	}
+
+		if (ctx->spec & EXT4_SPEC_s_dax_fc_bytelog) {
+			bool new_on = ctx_test_mount_opt2(ctx,
+					EXT4_MOUNT2_DAX_FC_BYTELOG);
+			bool new_force = ctx_test_mount_opt2(ctx,
+					EXT4_MOUNT2_DAX_FC_BYTELOG_FORCE);
+			bool cur_on = test_opt2(sb, DAX_FC_BYTELOG);
+			bool cur_force = test_opt2(sb, DAX_FC_BYTELOG_FORCE);
+
+				if (new_on != cur_on || new_force != cur_force) {
+					ext4_msg(NULL, KERN_ERR,
+						 "can't change dax_fc_bytelog mount option while remounting");
+					return -EINVAL;
+				}
+			}
+		}
 
 	return ext4_check_quota_consistency(fc, sb);
 }
@@ -3038,6 +3086,12 @@ static int _ext4_show_options(struct seq_file *seq, struct super_block *sb,
 	} else if (test_opt2(sb, DAX_INODE)) {
 		SEQ_OPTS_PUTS("dax=inode");
 	}
+	if (test_opt2(sb, DAX_FC_BYTELOG)) {
+		if (test_opt2(sb, DAX_FC_BYTELOG_FORCE))
+			SEQ_OPTS_PUTS("dax_fc_bytelog=force");
+		else
+			SEQ_OPTS_PUTS("dax_fc_bytelog=on");
+	}
 
 	if (sbi->s_groups_count >= MB_DEFAULT_LINEAR_SCAN_THRESHOLD &&
 			!test_opt2(sb, MB_OPTIMIZE_SCAN)) {
@@ -4950,6 +5004,8 @@ static int ext4_load_and_init_journal(struct super_block *sb,
 			"Failed to set fast commit journal feature");
 		goto out;
 	}
+	if (test_opt2(sb, JOURNAL_FAST_COMMIT))
+		ext4_fc_bytelog_init(sb, sbi->s_journal);
 
 	/* We have now updated the journal if required, so we can
 	 * validate the data journaling mode. */
@@ -6124,10 +6180,29 @@ static int ext4_load_journal(struct super_block *sb,
 		char *save = kmalloc(EXT4_S_ERR_LEN, GFP_KERNEL);
 		__le16 orig_state;
 		bool changed = false;
+		int fc_err;
 
 		if (save)
 			memcpy(save, ((char *) es) +
 			       EXT4_S_ERR_START, EXT4_S_ERR_LEN);
+
+		/*
+		 * Map the ByteLog ring before fast-commit replay so that
+		 * EXT4_FC_TAG_DAX_BYTELOG_ANCHOR records can be processed
+		 * during jbd2_journal_load().
+		 *
+		 * For filesystems with the INCOMPAT_DAX_FC_BYTELOG feature
+		 * bit set, failing to initialize the ByteLog ring must be
+		 * treated as fatal.
+		 */
+		if (test_opt2(sb, JOURNAL_FAST_COMMIT)) {
+			fc_err = ext4_fc_bytelog_init(sb, journal);
+			if (fc_err && ext4_has_feature_dax_fc_bytelog(sb)) {
+				kfree(save);
+				err = fc_err;
+				goto err_out;
+			}
+		}
 		err = jbd2_journal_load(journal);
 		if (save && memcmp(((char *) es) + EXT4_S_ERR_START,
 				   save, EXT4_S_ERR_LEN)) {
-- 
2.52.0


  parent reply	other threads:[~2026-02-26 10:18 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-02-26 10:17 [RFC PATCH 0/4] ext4: Byte-granular ByteLog optimizes DAX fast commits Li Chen
2026-02-26 10:17 ` [RFC PATCH 1/4] ext4: introduce DAX fast commit ByteLog backend Li Chen
2026-02-26 10:17 ` Li Chen [this message]
2026-02-26 10:17 ` [RFC PATCH 3/4] ext4: fast_commit: write TLVs into DAX ByteLog Li Chen
2026-02-26 10:17 ` [RFC PATCH 4/4] ext4: fast_commit: replay DAX ByteLog records Li Chen

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=20260226101736.2271952-3-me@linux.beauty \
    --to=me@linux.beauty \
    --cc=adilger.kernel@dilger.ca \
    --cc=harshadshirwadkar@gmail.com \
    --cc=linux-ext4@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.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