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.
This commit is contained in:
Christopher Haster
2025-07-01 14:08:24 -05:00
parent 1bf2a4b520
commit b6a36e75cf
+14 -25
View File
@@ -9722,9 +9722,8 @@ enum {
LFS3_TSTATE_BTREE = 5, LFS3_TSTATE_BTREE = 5,
LFS3_TSTATE_OMDIRS = 6, LFS3_TSTATE_OMDIRS = 6,
LFS3_TSTATE_OBTREE = 7, LFS3_TSTATE_OBTREE = 7,
LFS3_TSTATE_GRAFT = 8,
#endif #endif
LFS3_TSTATE_DONE = 9, LFS3_TSTATE_DONE = 8,
}; };
static void lfs3_traversal_init(lfs3_traversal_t *t, uint32_t flags) { 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; 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 // low-level traversal _only_ finds blocks
static int lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_traversal_t *t, static int lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_traversal_t *t,
lfs3_tag_t *tag_, lfs3_bptr_t *bptr) { 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, err = lfs3_mtree_lookup(lfs3, t->b.o.mdir.mid,
&t->b.o.mdir); &t->b.o.mdir);
if (err) { 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) { if (err == LFS3_ERR_NOENT) {
t->u.gt = 0; lfs3_t_settstate(&t->b.o.flags, LFS3_TSTATE_DONE);
lfs3_t_settstate(&t->b.o.flags, LFS3_TSTATE_GRAFT);
continue; continue;
} }
return err; return err;
@@ -10030,21 +10025,6 @@ static int lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_traversal_t *t,
continue; continue;
#endif #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:; case LFS3_TSTATE_DONE:;
return LFS3_ERR_NOENT; 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_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr->data.u.buffer;
lfs3_alloc_markinuse_(lfs3, rbyd->blocks[0]); lfs3_alloc_markinuse_(lfs3, rbyd->blocks[0]);
} else if (tag == LFS3_TAG_BLOCK } else if (tag == LFS3_TAG_BLOCK) {
|| tag == LFS3_TAG_DATA) {
lfs3_alloc_markinuse_(lfs3, lfs3_bptr_block(bptr)); lfs3_alloc_markinuse_(lfs3, lfs3_bptr_block(bptr));
} else { } else {
@@ -10458,6 +10437,9 @@ static lfs3_sblock_t lfs3_alloc_findfree(lfs3_t *lfs3) {
} }
#endif #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) #if !defined(LFS3_RDONLY) && !defined(LFS3_2BONLY)
static lfs3_sblock_t lfs3_alloc(lfs3_t *lfs3, bool erase) { static lfs3_sblock_t lfs3_alloc(lfs3_t *lfs3, bool erase) {
while (true) { while (true) {
@@ -10539,6 +10521,13 @@ static lfs3_sblock_t lfs3_alloc(lfs3_t *lfs3, bool erase) {
lfs3_alloc_markinuse(lfs3, tag, &bptr); 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 // mark anything not seen as free
lfs3_alloc_markfree(lfs3); lfs3_alloc_markfree(lfs3);
} }