From b6a36e75cfdceabd40e76a7c72cd37134e08d72d Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 1 Jul 2025 14:08:24 -0500 Subject: [PATCH] Limited graft traversal scope to lfs3_alloc This drops the LFS3_TSTATE_GRAFT state for just explicitly iterating over graft state in lfs3_alloc. This is cheaper as long as lfs3_alloc is the only traversal we trigger while grafting. We already rely on the lfs3_alloc-specific behavior of never touching cksize/cksum fields anyways. Note both lfs3_alloc_markinuse and lfs3_alloc_markinuse_ already have multiple call sites and can't be inlined due to lookahead population in lfs3_mtree_gc. We also don't need to worry about graft state there as incremental traversals only make progress when bshrubs are at rest. Saves a bit of code: code stack ctx before: 38092 2456 656 after: 38060 (-0.1%) 2456 (+0.0%) 656 (+0.0%) before graft: 37936 2456 636 after graft: 38060 (+0.3%) 2456 (+0.0%) 656 (+3.1%) Actually, surprisingly little code, but anything that simplifies lfs3_mtree_traverse_ is welcome. --- lfs3.c | 39 ++++++++++++++------------------------- 1 file changed, 14 insertions(+), 25 deletions(-) diff --git a/lfs3.c b/lfs3.c index eaba06d3..f16cd07b 100644 --- a/lfs3.c +++ b/lfs3.c @@ -9722,9 +9722,8 @@ enum { LFS3_TSTATE_BTREE = 5, LFS3_TSTATE_OMDIRS = 6, LFS3_TSTATE_OBTREE = 7, - LFS3_TSTATE_GRAFT = 8, #endif - LFS3_TSTATE_DONE = 9, + LFS3_TSTATE_DONE = 8, }; static void lfs3_traversal_init(lfs3_traversal_t *t, uint32_t flags) { @@ -9744,9 +9743,6 @@ static void lfs3_traversal_init(lfs3_traversal_t *t, uint32_t flags) { t->gcksum = 0; } -// needed in lfs3_mtree_traverse_ -static inline lfs3_size_t lfs3_graft_count(lfs3_size_t graft_count); - // low-level traversal _only_ finds blocks static int lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_traversal_t *t, lfs3_tag_t *tag_, lfs3_bptr_t *bptr) { @@ -9861,10 +9857,9 @@ static int lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_traversal_t *t, err = lfs3_mtree_lookup(lfs3, t->b.o.mdir.mid, &t->b.o.mdir); if (err) { - // end of mtree? all that's left is any graft state + // end of mtree? guess we're done if (err == LFS3_ERR_NOENT) { - t->u.gt = 0; - lfs3_t_settstate(&t->b.o.flags, LFS3_TSTATE_GRAFT); + lfs3_t_settstate(&t->b.o.flags, LFS3_TSTATE_DONE); continue; } return err; @@ -10030,21 +10025,6 @@ static int lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_traversal_t *t, continue; #endif - // traverse through in-flight grafts - case LFS3_TSTATE_GRAFT:; - // done? - if (t->u.gt >= lfs3_graft_count(lfs3->graft_count)) { - lfs3_t_settstate(&t->b.o.flags, LFS3_TSTATE_DONE); - continue; - } - - if (tag_) { - *tag_ = LFS3_TAG_DATA; - } - bptr->data = lfs3->graft[t->u.gt]; - t->u.gt += 1; - return 0; - case LFS3_TSTATE_DONE:; return LFS3_ERR_NOENT; @@ -10382,8 +10362,7 @@ static void lfs3_alloc_markinuse(lfs3_t *lfs3, lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr->data.u.buffer; lfs3_alloc_markinuse_(lfs3, rbyd->blocks[0]); - } else if (tag == LFS3_TAG_BLOCK - || tag == LFS3_TAG_DATA) { + } else if (tag == LFS3_TAG_BLOCK) { lfs3_alloc_markinuse_(lfs3, lfs3_bptr_block(bptr)); } else { @@ -10458,6 +10437,9 @@ static lfs3_sblock_t lfs3_alloc_findfree(lfs3_t *lfs3) { } #endif +// needed in lfs3_mtree_traverse_ +static inline lfs3_size_t lfs3_graft_count(lfs3_size_t graft_count); + #if !defined(LFS3_RDONLY) && !defined(LFS3_2BONLY) static lfs3_sblock_t lfs3_alloc(lfs3_t *lfs3, bool erase) { while (true) { @@ -10539,6 +10521,13 @@ static lfs3_sblock_t lfs3_alloc(lfs3_t *lfs3, bool erase) { lfs3_alloc_markinuse(lfs3, tag, &bptr); } + // mask out any in-flight graft state + for (lfs3_size_t i = 0; + i < lfs3_graft_count(lfs3->graft_count); + i++) { + lfs3_alloc_markinuse_(lfs3, lfs3->graft[i].u.disk.block); + } + // mark anything not seen as free lfs3_alloc_markfree(lfs3); }