From 6d5be2922a98ad4cc2ac53edf330bfc85904b0ef Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sun, 2 Feb 2025 18:24:43 -0600 Subject: [PATCH] Rearranged lfsr_mdir_commit prologue/epilogue a bit Mainly to make our bshrub-in-mdir assert stricter (we need to update mdirs first to assert bshrubs end up in the right mdirs), but also to make lfsr_mdir_commit epilogue mirror the prologue a bit better. In this function especially, readability is important. And hey, code changes no worse for the wear: code stack ctx before: 36424 2608 640 after: 36432 (+0.0%) 2608 (+0.0%) 640 (+0.0%) --- lfs.c | 64 ++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 35 insertions(+), 29 deletions(-) diff --git a/lfs.c b/lfs.c index 49ce18d1..5e6cd6e5 100644 --- a/lfs.c +++ b/lfs.c @@ -8135,6 +8135,18 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // xor our old cksum lfs->gcksum ^= mdir->rbyd.cksum; + // stage any bshrubs + for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { + if (lfsr_o_isbshrub(o->flags)) { + // a bshrub outside of its mdir means something has gone + // horribly wrong + LFS_ASSERT(!lfsr_bshrub_isbshrub(&((lfsr_obshrub_t*)o)->bshrub) + || ((lfsr_obshrub_t*)o)->bshrub.u.bshrub.blocks[0] + == o->mdir.rbyd.blocks[0]); + ((lfsr_obshrub_t*)o)->bshrub_ = ((lfsr_obshrub_t*)o)->bshrub; + } + } + // create a copy lfsr_mdir_t mdir_[2]; mdir_[0] = *mdir; @@ -8148,16 +8160,6 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, if (lfsr_mdir_cmp(&o->mdir, mdir) == 0) { o->mdir.rbyd.eoff = -1; } - - // stage any bshrubs - if (lfsr_o_isbshrub(o->flags)) { - // a bshrub outside of its mdir means something has gone - // horribly wrong - LFS_ASSERT(!lfsr_bshrub_isbshrub(&((lfsr_obshrub_t*)o)->bshrub) - || ((lfsr_obshrub_t*)o)->bshrub.u.bshrub.blocks[0] - == o->mdir.rbyd.blocks[0]); - ((lfsr_obshrub_t*)o)->bshrub_ = ((lfsr_obshrub_t*)o)->bshrub; - } } // attempt to commit/compact the mdir normally @@ -8605,14 +8607,6 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // success? update in-device state, we must not error at this point! // /////////////////////////////////////////////////////////////////////// - // we may have touched any number of mdirs, so assume uncompacted - // until lfsr_gc can prove otherwise - lfs->flags |= LFS_I_COMPACT; - - // update any gstate changes - lfsr_fs_commitgdelta(lfs); - lfsr_fs_flushgdelta(lfs); - // play out any rats that affect internal state mid_ = mdir->mid; for (lfs_size_t i = 0; i < rat_count; i++) { @@ -8637,16 +8631,6 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, mid_ = lfsr_rat_nextrid(rats[i], mid_); } - // update any staged bshrubs - for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { - if (lfsr_o_isbshrub(o->flags)) { - ((lfsr_obshrub_t*)o)->bshrub = ((lfsr_obshrub_t*)o)->bshrub_; - } - } - - // mark all traversals as dirty - lfsr_fs_mkdirty(lfs); - // if mroot/mtree changed, clobber any mroot/mtree traversals if (lfsr_mdir_cmp(&mroot_, &lfs->mroot) != 0 || lfsr_btree_cmp(&mtree_, &lfs->mtree) != 0) { @@ -8700,6 +8684,28 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfsr_mdir_sync(&lfs->mroot, &mroot_); lfs->mtree = mtree_; + // update any staged bshrubs + for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { + if (lfsr_o_isbshrub(o->flags)) { + // a bshrub outside of its mdir means something has gone + // horribly wrong + LFS_ASSERT(!lfsr_bshrub_isbshrub(&((lfsr_obshrub_t*)o)->bshrub_) + || ((lfsr_obshrub_t*)o)->bshrub_.u.bshrub.blocks[0] + == o->mdir.rbyd.blocks[0]); + ((lfsr_obshrub_t*)o)->bshrub = ((lfsr_obshrub_t*)o)->bshrub_; + } + } + + // update any gstate changes + lfsr_fs_commitgdelta(lfs); + + // mark all traversals as dirty + lfsr_fs_mkdirty(lfs); + + // we may have touched any number of mdirs, so assume uncompacted + // until lfsr_fs_gc can prove otherwise + lfs->flags |= LFS_I_COMPACT; + #ifdef LFS_DEBUGMDIRCOMMITS LFS_DEBUG("Committed mdir %"PRId32" " "0x{%"PRIx32",%"PRIx32"}.%"PRIx32" w%"PRId32", " @@ -12897,7 +12903,7 @@ static int lfs_init(lfs_t *lfs, uint32_t flags, // default to an empty lookahead | LFS_I_LOOKAHEAD // default to assuming we need compaction somewhere, worst case - // this just makes lfsr_gc read more than is strictly needed + // this just makes lfsr_fs_gc read more than is strictly needed | LFS_I_COMPACT // default to needing a ckmeta/ckdata scan | LFS_I_CKMETA