trv: Reordered gbmap traversal before mdir iteration

This is in preparation for some traversal simplification ideas, which
rely on all auxiliary/non-file btrees being visitable before file
btrees.

In theory the order of file vs auxiliary btrees doesn't really matter,
other than the number of different routes from mtree/mroot -> gbmap/file
btrees being a bit of a pain.

Note this is not true for the mtree, which must come first for
lfs3_mount to work.

---

Adds a bit of code when building with the gbmap:

                 code          stack          ctx
  before:       36480           2304          660
  after:        36476 (-0.0%)   2304 (+0.0%)  660 (+0.0%)

                 code          stack          ctx
  gbmap before: 39464           2320          772
  gbmap after:  39524 (+0.2%)   2320 (+0.0%)  772 (+0.0%)

                 code          stack          ctx
  gc before:    36552           2304          804
  gc after:     36548 (-0.0%)   2304 (+0.0%)  804 (+0.0%)
This commit is contained in:
Christopher Haster
2025-10-27 02:01:24 -05:00
parent ee519f43b5
commit 9e006fd7dc
2 changed files with 329 additions and 279 deletions
+79 -71
View File
@@ -10045,13 +10045,13 @@ enum lfs3_tstate {
LFS3_TSTATE_MROOTANCHOR = 0, LFS3_TSTATE_MROOTANCHOR = 0,
LFS3_TSTATE_MROOTCHAIN = 1, LFS3_TSTATE_MROOTCHAIN = 1,
LFS3_TSTATE_MTREE = 2, LFS3_TSTATE_MTREE = 2,
LFS3_TSTATE_MDIRS = 3, LFS3_TSTATE_GBMAP = 3,
LFS3_TSTATE_MDIR = 4, LFS3_TSTATE_GBMAP_P = 4,
LFS3_TSTATE_BTREE = 5, LFS3_TSTATE_MDIRS = 5,
LFS3_TSTATE_HANDLES = 6, LFS3_TSTATE_MDIR = 6,
LFS3_TSTATE_HBTREE = 7, LFS3_TSTATE_BTREE = 7,
LFS3_TSTATE_GBMAP = 8, LFS3_TSTATE_HANDLES = 8,
LFS3_TSTATE_GBMAP_P = 9, LFS3_TSTATE_HBTREE = 9,
LFS3_TSTATE_DONE = 10, LFS3_TSTATE_DONE = 10,
}; };
@@ -10114,12 +10114,25 @@ static lfs3_stag_t lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_mtrv_t *mtrv,
LFS3_TAG_MASK8 | LFS3_TAG_STRUCT, LFS3_TAG_MASK8 | LFS3_TAG_STRUCT,
&data); &data);
if (tag < 0) { if (tag < 0) {
// if we have no mtree (inlined mdir), we need to
// traverse any files in our mroot next
if (tag == LFS3_ERR_NOENT) { if (tag == LFS3_ERR_NOENT) {
mtrv->b.h.mdir.mid = 0; // if we have no mtree (inlined mdir), we need to
lfs3_t_settstate(&mtrv->b.h.flags, LFS3_TSTATE_MDIR); // traverse any auxiliary btrees next
if (LFS3_IFDEF_GBMAP(
lfs3_f_isgbmap(lfs3->flags)
&& !lfs3_t_ismtreeonly(mtrv->b.h.flags),
false)) {
#ifdef LFS3_GBMAP
mtrv->b.shrub = lfs3->gbmap.b;
lfs3_btrv_init(&mtrv->btrv);
lfs3_t_settstate(&mtrv->b.h.flags, LFS3_TSTATE_GBMAP);
continue; continue;
#endif
// or any files in our mroot
} else {
mtrv->b.h.mdir.mid = 0;
lfs3_t_settstate(&mtrv->b.h.flags, LFS3_TSTATE_MDIRS);
continue;
}
} }
return tag; return tag;
} }
@@ -10193,30 +10206,23 @@ static lfs3_stag_t lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_mtrv_t *mtrv,
err = lfs3_mtree_lookup(lfs3, mtrv->b.h.mdir.mid, err = lfs3_mtree_lookup(lfs3, mtrv->b.h.mdir.mid,
&mtrv->b.h.mdir); &mtrv->b.h.mdir);
if (err) { if (err) {
// end of mtree? // end of mtree? guess we're done
if (err == LFS3_ERR_NOENT) { if (err == LFS3_ERR_NOENT) {
if (LFS3_IFDEF_GBMAP(
lfs3_f_isgbmap(lfs3->flags),
false)) {
#ifdef LFS3_GBMAP
// transition to traversing the gbmap if there is one
mtrv->b.shrub = lfs3->gbmap.b;
lfs3_btrv_init(&mtrv->btrv);
lfs3_t_settstate(&mtrv->b.h.flags, LFS3_TSTATE_GBMAP);
continue;
#endif
} else {
// guess we're done // guess we're done
lfs3_t_settstate(&mtrv->b.h.flags, LFS3_TSTATE_DONE); lfs3_t_settstate(&mtrv->b.h.flags, LFS3_TSTATE_DONE);
continue; continue;
} }
}
return err; return err;
} }
// transition to traversing the mdir // transition to traversing the mdir
lfs3_t_settstate(&mtrv->b.h.flags, LFS3_TSTATE_MDIR); lfs3_t_settstate(&mtrv->b.h.flags, LFS3_TSTATE_MDIR);
// wait, no mtree? don't repeat the mroot
if (lfs3->mtree.r.weight == 0) {
continue;
}
bptr_->d.u.buffer = (const uint8_t*)&mtrv->b.h.mdir; bptr_->d.u.buffer = (const uint8_t*)&mtrv->b.h.mdir;
return LFS3_TAG_MDIR; return LFS3_TAG_MDIR;
@@ -10299,10 +10305,10 @@ static lfs3_stag_t lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_mtrv_t *mtrv,
// traverse any bshrubs/btrees we see, this includes the mtree // traverse any bshrubs/btrees we see, this includes the mtree
// and any file btrees/bshrubs // and any file btrees/bshrubs
case LFS3_TSTATE_MTREE:; case LFS3_TSTATE_MTREE:;
case LFS3_TSTATE_BTREE:;
case LFS3_TSTATE_HBTREE:;
case LFS3_TSTATE_GBMAP:; case LFS3_TSTATE_GBMAP:;
case LFS3_TSTATE_GBMAP_P:; case LFS3_TSTATE_GBMAP_P:;
case LFS3_TSTATE_BTREE:;
case LFS3_TSTATE_HBTREE:;
// traverse through our bshrub/btree // traverse through our bshrub/btree
tag = lfs3_bshrub_traverse(lfs3, &mtrv->b, &mtrv->btrv, tag = lfs3_bshrub_traverse(lfs3, &mtrv->b, &mtrv->btrv,
NULL, NULL, &data); NULL, NULL, &data);
@@ -10310,9 +10316,52 @@ static lfs3_stag_t lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_mtrv_t *mtrv,
if (tag == LFS3_ERR_NOENT) { if (tag == LFS3_ERR_NOENT) {
// clear the bshrub state // clear the bshrub state
lfs3_bshrub_init(&mtrv->b); lfs3_bshrub_init(&mtrv->b);
// end of mtree? start iterating over mdirs // end of mtree? have a gbmap? not mtreeonly? start
if (lfs3_t_tstate(mtrv->b.h.flags) // iterating over the gbmap
== LFS3_TSTATE_MTREE) { if (LFS3_IFDEF_GBMAP(
lfs3_f_isgbmap(lfs3->flags)
&& lfs3_t_tstate(mtrv->b.h.flags)
== LFS3_TSTATE_MTREE
&& !lfs3_t_ismtreeonly(mtrv->b.h.flags),
false)) {
#ifdef LFS3_GBMAP
mtrv->b.shrub = lfs3->gbmap.b;
lfs3_btrv_init(&mtrv->btrv);
lfs3_t_settstate(&mtrv->b.h.flags, LFS3_TSTATE_GBMAP);
continue;
#endif
// end of gbmap? check if we also have an outdated on-disk
// gbmap that doesn't match the active gbmap
//
// we need to include this in case the gbmap is rebuilt
// multiple times before an mdir commit
} else if (LFS3_IFDEF_GBMAP(
lfs3_f_isgbmap(lfs3->flags)
&& lfs3_t_tstate(mtrv->b.h.flags)
== LFS3_TSTATE_GBMAP
&& lfs3_btree_cmp(
&lfs3->gbmap.b_p,
&lfs3->gbmap.b) != 0,
false)) {
#ifdef LFS3_GBMAP
mtrv->b.shrub = lfs3->gbmap.b_p;
lfs3_btrv_init(&mtrv->btrv);
lfs3_t_settstate(&mtrv->b.h.flags,
LFS3_TSTATE_GBMAP_P);
continue;
#endif
// end of mtree and auxiliary btrees? start
// iterating over mdirs
} else if (lfs3_t_tstate(mtrv->b.h.flags)
== LFS3_TSTATE_MTREE
|| LFS3_IFDEF_GBMAP(
lfs3_t_tstate(mtrv->b.h.flags)
== LFS3_TSTATE_GBMAP,
false)
|| LFS3_IFDEF_GBMAP(
lfs3_t_tstate(mtrv->b.h.flags)
== LFS3_TSTATE_GBMAP_P,
false)) {
mtrv->b.h.mdir.mid = 0; mtrv->b.h.mdir.mid = 0;
lfs3_t_settstate(&mtrv->b.h.flags, LFS3_TSTATE_MDIRS); lfs3_t_settstate(&mtrv->b.h.flags, LFS3_TSTATE_MDIRS);
continue; continue;
@@ -10328,44 +10377,6 @@ static lfs3_stag_t lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_mtrv_t *mtrv,
mtrv->h = mtrv->h->next; mtrv->h = mtrv->h->next;
lfs3_t_settstate(&mtrv->b.h.flags, LFS3_TSTATE_HANDLES); lfs3_t_settstate(&mtrv->b.h.flags, LFS3_TSTATE_HANDLES);
continue; continue;
// end of gbmap? check if we also have an outdated on-disk
// gbmap
//
// we need to include this in case the gbmap is rebuilt
// multiple times before an mdir commit
} else if (LFS3_IFDEF_GBMAP(
lfs3_f_isgbmap(lfs3->flags)
&& lfs3_t_tstate(mtrv->b.h.flags)
== LFS3_TSTATE_GBMAP,
false)) {
#ifdef LFS3_GBMAP
// if on-disk gbmap does not match the active gbmap,
// transition to traversing the on-disk gbmap
if (lfs3_btree_cmp(
&lfs3->gbmap.b_p,
&lfs3->gbmap.b) != 0) {
mtrv->b.shrub = lfs3->gbmap.b_p;
lfs3_btrv_init(&mtrv->btrv);
lfs3_t_settstate(&mtrv->b.h.flags,
LFS3_TSTATE_GBMAP_P);
continue;
// otherwise guess we're done
} else {
lfs3_t_settstate(&mtrv->b.h.flags,
LFS3_TSTATE_DONE);
continue;
}
#endif
// end of on-disk gbmap? guess we're done
} else if (LFS3_IFDEF_GBMAP(
lfs3_f_isgbmap(lfs3->flags)
&& lfs3_t_tstate(mtrv->b.h.flags)
== LFS3_TSTATE_GBMAP_P,
false)) {
#ifdef LFS3_GBMAP
lfs3_t_settstate(&mtrv->b.h.flags, LFS3_TSTATE_DONE);
continue;
#endif
} else { } else {
LFS3_UNREACHABLE(); LFS3_UNREACHABLE();
} }
@@ -17156,13 +17167,10 @@ static void lfs3_trv_clobber(lfs3_t *lfs3, lfs3_trv_t *trv) {
lfs3_bshrub_init(&trv->gc.t.b); lfs3_bshrub_init(&trv->gc.t.b);
trv->gc.t.h = NULL; trv->gc.t.h = NULL;
// opened mdir? skip to next omdir // opened mdir? skip to next omdir
} else if (lfs3_t_tstate(trv->gc.t.b.h.flags) < LFS3_TSTATE_GBMAP) { } else if (lfs3_t_tstate(trv->gc.t.b.h.flags) < LFS3_TSTATE_DONE) {
lfs3_t_settstate(&trv->gc.t.b.h.flags, LFS3_TSTATE_HANDLES); lfs3_t_settstate(&trv->gc.t.b.h.flags, LFS3_TSTATE_HANDLES);
lfs3_bshrub_init(&trv->gc.t.b); lfs3_bshrub_init(&trv->gc.t.b);
trv->gc.t.h = (trv->gc.t.h) ? trv->gc.t.h->next : NULL; trv->gc.t.h = (trv->gc.t.h) ? trv->gc.t.h->next : NULL;
// auxiliary btrees? just say we're done
} else if (lfs3_t_tstate(trv->gc.t.b.h.flags) < LFS3_TSTATE_DONE) {
lfs3_t_settstate(&trv->gc.t.b.h.flags, LFS3_TSTATE_DONE);
// done traversals should never need clobbering // done traversals should never need clobbering
} else { } else {
LFS3_UNREACHABLE(); LFS3_UNREACHABLE();
+302 -260
View File
File diff suppressed because it is too large Load Diff