From 0fa33b77761fb73485b7575e9f84a2df851dc669 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 8 Feb 2024 22:51:43 -0600 Subject: [PATCH] Cleaned up post-mdir-commit state updates a bit This code is a bit tricky since we need to reference the current mdir to know how to update other opened mdirs, but then also update the current mdir, which could also be in the list of opened mdirs. I think a hear a functional language user laughing in the distance... code stack before: 33764 2832 after: 33716 (-0.1%) 2832 (+0.0%) --- lfs.c | 109 ++++++++++++++++++++++++++-------------------------------- 1 file changed, 49 insertions(+), 60 deletions(-) diff --git a/lfs.c b/lfs.c index ebfb5140..14196d9e 100644 --- a/lfs.c +++ b/lfs.c @@ -6192,10 +6192,9 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // reset gdelta for new commit lfsr_fs_flushgdelta(lfs); - + // parse out any pending gstate, these will get automatically + // xored with on-disk gdeltas in lower-level functions for (lfs_size_t i = 0; i < attr_count; i++) { - // parse out any pending gstate, these will get automatically - // xored with on-disk gdeltas in lower-level functions if (attrs[i].tag == LFSR_TAG_GRM) { // encode to disk lfsr_grm_t *grm = lfsr_attr_grm(&attrs[i]); @@ -6397,7 +6396,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, uint8_t mdir_buf[LFSR_MPTR_DSIZE]; uint8_t msibling_buf[LFSR_MPTR_DSIZE]; err = lfsr_btree_commit(lfs, &mtree_.u.btree, - lfsr_mid_bid(lfs, mdir_.mid), LFSR_ATTRS( + lfsr_mid_bid(lfs, mdir->mid), LFSR_ATTRS( LFSR_ATTR( MDIR, 0, FROMMPTR(lfsr_mdir_mptr(&mdir_), mdir_buf)), @@ -6416,8 +6415,8 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, } else if (err == LFS_ERR_NOENT) { LFS_DEBUG("Dropping mdir %"PRId32" " "0x{%"PRIx32",%"PRIx32"}", - mdir_.mid >> lfs->mleaf_bits, - mdir_.rbyd.blocks[0], mdir_.rbyd.blocks[1]); + mdir->mid >> lfs->mleaf_bits, + mdir->rbyd.blocks[0], mdir->rbyd.blocks[1]); // consume gstate so we don't lose any info err = lfsr_fs_consumegdelta(lfs, mdir); @@ -6437,7 +6436,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // update our mtree err = lfsr_btree_commit(lfs, &mtree_.u.btree, - lfsr_mid_bid(lfs, mdir_.mid), LFSR_ATTRS( + lfsr_mid_bid(lfs, mdir->mid), LFSR_ATTRS( LFSR_ATTR(RM, -lfsr_mleafweight(lfs), NULL()))); if (err) { return err; @@ -6466,7 +6465,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // update our mtree uint8_t mdir_buf[LFSR_MPTR_DSIZE]; err = lfsr_btree_commit(lfs, &mtree_.u.btree, - lfsr_mid_bid(lfs, mdir_.mid), LFSR_ATTRS( + lfsr_mid_bid(lfs, mdir->mid), LFSR_ATTRS( LFSR_ATTR( MDIR, 0, FROMMPTR(lfsr_mdir_mptr(&mdir_), mdir_buf)))); @@ -6659,56 +6658,24 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, } } - // success? update in-device state, we must not error at this point - - // update any opened mdirs in our mroot - for (lfsr_opened_t *o = lfs->opened; o; o = o->next) { - if (lfsr_mdir_cmp(&o->mdir, &lfs->mroot) == 0) { - o->mdir.rbyd = mroot_.rbyd; - - // update staged changes - if (o->type == LFS_TYPE_REG) { - lfsr_file_t *file = (lfsr_file_t*)o; - file->bshrub = file->bshrub_; - } - } - } - - // update mroot and mtree - lfs->mroot = mroot_; - lfs->mtree = mtree_; - // gstate must have been committed by a lower-level function at this point LFS_ASSERT(lfsr_grm_iszero(lfs->grm_d)); - // TODO merge with attr updates below? + // success? update in-device state, we must not error at this point + + // play out any attrs that affect internal state + lfsr_smid_t mid = mdir->mid; for (lfs_size_t i = 0; i < attr_count; i++) { - // update any gstate + // update any gstate changes if (attrs[i].tag == LFSR_TAG_GRM) { lfs->grm = *lfsr_attr_grm(&attrs[i]); // keep track of the exact encoding on-disk lfsr_data_fromgrm(&lfs->grm, lfs->grm_g); } - } - for (lfsr_opened_t *o = lfs->opened; - o; - o = o->next) { - // update staged changes - if (o->type == LFS_TYPE_REG) { - lfsr_file_t *file = (lfsr_file_t*)o; - file->bshrub = file->bshrub_; - } - - // avoid double updating current mdir - if (&o->mdir == mdir) { - continue; - } - - // first play out any attrs that change our mid - lfsr_srid_t mid = mdir->mid; - for (lfs_size_t i = 0; i < attr_count; i++) { + // adjust any opened mdirs + for (lfsr_opened_t *o = lfs->opened; o; o = o->next) { // adjust opened mdirs? if (lfsr_mdir_cmp(&o->mdir, mdir) == 0 && o->mdir.mid >= mid) { @@ -6734,7 +6701,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, ((lfsr_dir_t*)(o-1))->pos -= attrs[i].delta; } } - } else if (o->mdir.mid > mdir->mid) { + } else if (o->mdir.mid > mid) { // adjust dir position? if (o->type == LFS_TYPE_DIR) { ((lfsr_dir_t*)o)->pos += attrs[i].delta; @@ -6742,18 +6709,36 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, ((lfsr_dir_t*)(o-1))->pos -= attrs[i].delta; } } - - // adjust mid - mid += attrs[i].delta; - if (lfsr_attr_isinsert(&attrs[i])) { - mid -= 1; - } } - // update any opened mdirs if we had a split or drop + // adjust mid + mid += attrs[i].delta; + if (lfsr_attr_isinsert(&attrs[i])) { + mid -= 1; + } + } + + // update any staged bsprouts/bshrubs + for (lfsr_opened_t *o = lfs->opened; o; o = o->next) { + if (o->type == LFS_TYPE_REG) { + lfsr_file_t *file = (lfsr_file_t*)o; + file->bshrub = file->bshrub_; + } + } + + // update internal mdir state + for (lfsr_opened_t *o = lfs->opened; o; o = o->next) { + // avoid double updating the current mdir + if (&o->mdir == mdir) { + continue; + } + + // update any splits/drops if (lfsr_mdir_cmp(&o->mdir, mdir) == 0) { + LFS_ASSERT(mdir->mid != -1 || mdir == &lfs->mroot); if (mdelta > 0 - && lfsr_mid_rid(lfs, o->mdir.mid) >= mdir_.rbyd.weight) { + && lfsr_mid_rid(lfs, o->mdir.mid) + >= mdir_.rbyd.weight) { o->mdir.mid += lfsr_mleafweight(lfs) - mdir_.rbyd.weight; o->mdir.rbyd = msibling_.rbyd; } else { @@ -6765,16 +6750,20 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, } // update mdir to follow requested rid - if (mdir->mid == -1) { - mdir->rbyd = lfs->mroot.rbyd; - } else if (mdelta > 0 - && lfsr_mid_rid(lfs, mdir->mid) >= mdir_.rbyd.weight) { + LFS_ASSERT(mdir->mid != -1 || mdir == &lfs->mroot); + if (mdelta > 0 + && lfsr_mid_rid(lfs, mdir->mid) + >= mdir_.rbyd.weight) { mdir->mid += lfsr_mleafweight(lfs) - mdir_.rbyd.weight; mdir->rbyd = msibling_.rbyd; } else { mdir->rbyd = mdir_.rbyd; } + // update mroot and mtree + lfs->mroot = mroot_; + lfs->mtree = mtree_; + return 0; }