From b724567b2a68e510af38042713798aba3c0a40ab Mon Sep 17 00:00:00 2001 From: Auke Kok Date: Tue, 17 Mar 2026 12:01:27 -0700 Subject: [PATCH] Add log_merge_force_partial trigger for testing partial merges. Add a trigger that forces btree_merge() to return -ERANGE after modifying a leaf's worth of items, causing many small partial merges per merge cycle. This is used by tests to reliably reproduce races that depend on partial merges splicing items into fs_root while finalized logs still exist. The trigger check lives inside btree_merge() where it can observe actual item modification progress, rather than overriding the caller's dirty byte limit argument which applies to the whole writer context. Signed-off-by: Auke Kok --- kmod/src/btree.c | 8 ++++++++ kmod/src/triggers.c | 1 + kmod/src/triggers.h | 1 + 3 files changed, 10 insertions(+) diff --git a/kmod/src/btree.c b/kmod/src/btree.c index 7a21afc7..caabc065 100644 --- a/kmod/src/btree.c +++ b/kmod/src/btree.c @@ -2486,6 +2486,14 @@ int scoutfs_btree_merge(struct super_block *sb, mitem = next_mitem(mitem); free_mitem(&rng, tmp); } + + if (mitem && walk_val_len == 0 && + !(walk_flags & (BTW_INSERT | BTW_DELETE)) && + scoutfs_trigger(sb, LOG_MERGE_FORCE_PARTIAL)) { + ret = -ERANGE; + *next_ret = mitem->key; + goto out; + } } ret = 0; diff --git a/kmod/src/triggers.c b/kmod/src/triggers.c index 4616d013..15ddf907 100644 --- a/kmod/src/triggers.c +++ b/kmod/src/triggers.c @@ -46,6 +46,7 @@ static char *names[] = { [SCOUTFS_TRIGGER_SRCH_MERGE_STOP_SAFE] = "srch_merge_stop_safe", [SCOUTFS_TRIGGER_STATFS_LOCK_PURGE] = "statfs_lock_purge", [SCOUTFS_TRIGGER_RECLAIM_SKIP_FINALIZE] = "reclaim_skip_finalize", + [SCOUTFS_TRIGGER_LOG_MERGE_FORCE_PARTIAL] = "log_merge_force_partial", }; bool scoutfs_trigger_test_and_clear(struct super_block *sb, unsigned int t) diff --git a/kmod/src/triggers.h b/kmod/src/triggers.h index 64a798b7..6d70cbea 100644 --- a/kmod/src/triggers.h +++ b/kmod/src/triggers.h @@ -9,6 +9,7 @@ enum scoutfs_trigger { SCOUTFS_TRIGGER_SRCH_MERGE_STOP_SAFE, SCOUTFS_TRIGGER_STATFS_LOCK_PURGE, SCOUTFS_TRIGGER_RECLAIM_SKIP_FINALIZE, + SCOUTFS_TRIGGER_LOG_MERGE_FORCE_PARTIAL, SCOUTFS_TRIGGER_NR, };