From 838a4beee1b742f539ce1bb39b1f03c7d4c2e173 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sun, 27 Jul 2025 22:03:29 -0500 Subject: [PATCH] bmap: Moved gbmap traversal to the end This avoids issues with the different traversal paths with an mtree vs inline-mtree. Previously this was broken when the mtree was inlined. This order also makes more sense if we want to check mdirs before we consider the gstate to be trustworthy enough for gbmap traversal. --- lfs3.c | 63 ++++++++++++++++++++++---------------------- tests/test_bmap.toml | 4 --- 2 files changed, 31 insertions(+), 36 deletions(-) diff --git a/lfs3.c b/lfs3.c index 5a72ff6e..8667fb2c 100644 --- a/lfs3.c +++ b/lfs3.c @@ -9963,12 +9963,12 @@ enum lfs3_tstate { #ifndef LFS3_2BONLY LFS3_TSTATE_MROOTCHAIN = 1, LFS3_TSTATE_MTREE = 2, - LFS3_TSTATE_BMAP = 3, - LFS3_TSTATE_MDIRS = 4, - LFS3_TSTATE_MDIR = 5, - LFS3_TSTATE_BTREE = 6, - LFS3_TSTATE_HANDLES = 7, - LFS3_TSTATE_HBTREE = 8, + LFS3_TSTATE_MDIRS = 3, + LFS3_TSTATE_MDIR = 4, + LFS3_TSTATE_BTREE = 5, + LFS3_TSTATE_HANDLES = 6, + LFS3_TSTATE_HBTREE = 7, + LFS3_TSTATE_BMAP = 8, #endif LFS3_TSTATE_DONE = 9, }; @@ -10110,10 +10110,19 @@ static lfs3_stag_t lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_trv_t *trv, err = lfs3_mtree_lookup(lfs3, trv->b.h.mdir.mid, &trv->b.h.mdir); if (err) { - // end of mtree? guess we're done + // end of mtree? if (err == LFS3_ERR_NOENT) { + #ifdef LFS3_BMAP + // transition to traversing the bmap if there is one + trv->b.shrub = lfs3->gbmap.b; + trv->bid = -2; + lfs3_t_settstate(&trv->b.h.flags, LFS3_TSTATE_BMAP); + continue; + #else + // guess we're done lfs3_t_settstate(&trv->b.h.flags, LFS3_TSTATE_DONE); continue; + #endif } return err; } @@ -10202,9 +10211,9 @@ static lfs3_stag_t lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_trv_t *trv, // and any file btrees/bshrubs #ifndef LFS3_2BONLY case LFS3_TSTATE_MTREE:; - case LFS3_TSTATE_BMAP:; case LFS3_TSTATE_BTREE:; case LFS3_TSTATE_HBTREE:; + case LFS3_TSTATE_BMAP:; // traverse through our bshrub/btree tag = lfs3_bshrub_traverse(lfs3, &trv->b, trv->bid+1, &trv->bid, NULL, &data); @@ -10212,26 +10221,9 @@ static lfs3_stag_t lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_trv_t *trv, if (tag == LFS3_ERR_NOENT) { // clear the bshrub state lfs3_bshrub_init(&trv->b); - // end of mtree? have a bmap? not mtreeonly? start - // iterating over bmap - if (LFS3_IFDEF_BMAP( - lfs3_t_tstate(trv->b.h.flags) - == LFS3_TSTATE_MTREE - && !lfs3_t_ismtreeonly(trv->b.h.flags), - false)) { - #ifdef LFS3_BMAP - trv->b.shrub = lfs3->gbmap.b; - trv->bid = -2; - lfs3_t_settstate(&trv->b.h.flags, LFS3_TSTATE_BMAP); - continue; - #endif - // end of mtree and bmap? start iterating over mdirs - } else if (lfs3_t_tstate(trv->b.h.flags) - == LFS3_TSTATE_MTREE - || LFS3_IFDEF_BMAP( - lfs3_t_tstate(trv->b.h.flags) - == LFS3_TSTATE_BMAP, - false)) { + // end of mtree? start iterating over mdirs + if (lfs3_t_tstate(trv->b.h.flags) + == LFS3_TSTATE_MTREE) { trv->b.h.mdir.mid = 0; lfs3_t_settstate(&trv->b.h.flags, LFS3_TSTATE_MDIRS); continue; @@ -10242,12 +10234,16 @@ static lfs3_stag_t lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_trv_t *trv, lfs3_t_settstate(&trv->b.h.flags, LFS3_TSTATE_HANDLES); continue; // end of opened btree? go to next opened file - } else if (lfs3_m_isrdonly(lfs3->flags) - || lfs3_t_tstate(trv->b.h.flags) - == LFS3_TSTATE_HBTREE) { + } else if (lfs3_t_tstate(trv->b.h.flags) + == LFS3_TSTATE_HBTREE) { trv->h = trv->h->next; lfs3_t_settstate(&trv->b.h.flags, LFS3_TSTATE_HANDLES); continue; + // end of bmap? guess we're done + } else if (lfs3_t_tstate(trv->b.h.flags) + == LFS3_TSTATE_BMAP) { + lfs3_t_settstate(&trv->b.h.flags, LFS3_TSTATE_DONE); + continue; } else { LFS3_UNREACHABLE(); } @@ -16875,12 +16871,15 @@ static void lfs3_trv_clobber(lfs3_t *lfs3, lfs3_trv_t *trv) { trv->h = NULL; #endif // opened mdir? skip to next omdir - } else if (lfs3_t_tstate(trv->b.h.flags) < LFS3_TSTATE_DONE) { + } else if (lfs3_t_tstate(trv->b.h.flags) < LFS3_TSTATE_BMAP) { lfs3_t_settstate(&trv->b.h.flags, LFS3_IFDEF_2BONLY( LFS3_TSTATE_DONE, LFS3_TSTATE_HANDLES)); lfs3_bshrub_init(&trv->b); trv->h = (trv->h) ? trv->h->next : NULL; + // auxiliary btrees? just say we're done + } else if (lfs3_t_tstate(trv->b.h.flags) < LFS3_TSTATE_DONE) { + lfs3_t_settstate(&trv->b.h.flags, LFS3_TSTATE_DONE); // done traversals should never need clobbering } else { LFS3_UNREACHABLE(); diff --git a/tests/test_bmap.toml b/tests/test_bmap.toml index c436c1d9..96ab895f 100644 --- a/tests/test_bmap.toml +++ b/tests/test_bmap.toml @@ -2,10 +2,6 @@ after = ['test_btree', 'test_mtree'] ifdef = 'LFS3_BMAP' -# maximize lookahead buffer, we don't actually gc so we only get one pass -# of the disk for these tests -defines.LOOKAHEAD_SIZE = '(BLOCK_COUNT+8-1) / 8' - # test simple set operations [cases.test_bmap_set_split] in = 'lfs3.c'