From dbc457bde1e6b7a450c07427404ef957ba6506cf Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 30 Dec 2025 01:37:54 -0600 Subject: [PATCH] trv: Fixed issue with not clobbering mroot chain mdirs This was introduced with the simplified traversal clobbering logic. Previously, traversal clobbering was a bit more aggressive, relying on the explicit tstate state machine. This was replaced by implicit mid-related state, which looks like it may have introduced some holes. In this case, lfs3_mdir_commit was failing to clobber non-active mroot chain mdirs. Non-active mroots are particularly tricky because we (1) don't track these in-RAM, (2) only reach them during traversals, and (3) require heavy wear-leveling writes for them to even appear in in system. --- The solution here is an extra check in lfs3_mdir_commit_'s post-commit state updates to update any mid<=-1 mroots to the new active mroot. This clobbers mroot chain traversals by skipping non-active mroots, but this is unavoidable since lfs3_mdir_commit_ could always introduce new/relocate mroot chain mroots. Note this should match the previous state-machine dependent behavior. Code changes: code stack ctx before: 35144 2136 660 after: 35152 (+0.0%) 2136 (+0.0%) 660 (+0.0%) code stack ctx gbmap before: 38380 2144 776 gbmap after: 38392 (+0.0%) 2144 (+0.0%) 776 (+0.0%) code stack ctx preerase before: 38920 2168 796 preerase after: 38928 (+0.0%) 2168 (+0.0%) 796 (+0.0%) --- lfs3.c | 3 +++ tests/test_trvs.toml | 19 +++++++++---------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lfs3.c b/lfs3.c index b2cc497b..150fdc86 100644 --- a/lfs3.c +++ b/lfs3.c @@ -9371,6 +9371,9 @@ static int lfs3_mdir_commit_(lfs3_t *lfs3, lfs3_mdir_t *mdir, } } else if (h->mdir.mid > mdir->mid) { h->mdir.mid += mdelta; + // and any mroot updates, though this clobbers chain mroots + } else if (h->mdir.mid <= -1) { + lfs3_mdir_sync(&h->mdir, &mroot_); } } diff --git a/tests/test_trvs.toml b/tests/test_trvs.toml index b736abd3..b4742784 100644 --- a/tests/test_trvs.toml +++ b/tests/test_trvs.toml @@ -4103,6 +4103,9 @@ code = ''' assert(tinfo.btype == LFS3_BTYPE_BTREE); assert(tinfo.block == 2); } + // traverse mtree + lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; + assert(tinfo.btype == LFS3_BTYPE_BTREE); // traverse mdir lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_MDIR); @@ -4762,11 +4765,6 @@ code = ''' // still traverse inlined mroots, so if this breaks in the future // I wouldn't worry too much about it // - // traverse an mdir - lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; - assert(tinfo.btype == LFS3_BTYPE_MDIR); - lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; - assert(tinfo.btype == LFS3_BTYPE_MDIR); // traverse gbmap if (GBMAP) { lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; @@ -6078,11 +6076,6 @@ code = ''' lfs3_trv_close(&lfs3, &trv) => 0; goto done; } - // traverse mdir - lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; - assert(tinfo.btype == LFS3_BTYPE_MDIR); - lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; - assert(tinfo.btype == LFS3_BTYPE_MDIR); // traverse mtree lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_BTREE); @@ -7766,6 +7759,9 @@ code = ''' assert(tinfo.btype == LFS3_BTYPE_BTREE); assert(tinfo.block == 2); } + // traverse mtree + lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; + assert(tinfo.btype == LFS3_BTYPE_BTREE); // traverse mdirs lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_MDIR); @@ -8946,6 +8942,9 @@ code = ''' assert(tinfo.btype == LFS3_BTYPE_BTREE); assert(tinfo.block == 2); } + // traverse mtree + lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; + assert(tinfo.btype == LFS3_BTYPE_BTREE); // traverse mdirs lfs3_trv_read(&lfs3, &trv, &tinfo) => 0; assert(tinfo.btype == LFS3_BTYPE_MDIR);