From 849c9f25cae1b1eb2129f40c956c90442b41e7e8 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 23 May 2024 22:52:00 -0500 Subject: [PATCH] Combined lfsr_mdir_commit's mdir_+msibling_ into mdir_[2] I think this fits a bit better with the new ordering requirement for mdir splits. I also explored the same transformation in lfsr_btree_commit_, but decided against it for two reasons: 1. It saves roughly the same amount of code, but increases the RAM cost, probably due to decreased flexibility on where/when to allocate the structs. lfsr_btree_commit_ is and likely always will be on the stack hot-path, so this is a bit important. 2. The naming may be confusing. Unlike in lfsr_mdir_commit, sibling in lfsr_btree_commit_ serves multiple roles, including the previous sibling for btree merges. I imagine renaming sibling -> rbyd_[1] would make that whole sequence quite difficult to read... At least in lfsr_mdir_commit this saves a bit a code: code stack before: 33482 2640 +btree: 33398 (-0.3%) 2664 (+0.9%) after: 33438 (-0.1%) 2640 (+0.0%) --- lfs.c | 159 ++++++++++++++++++++++++++-------------------------------- 1 file changed, 71 insertions(+), 88 deletions(-) diff --git a/lfs.c b/lfs.c index 6dea1ae6..a4b65348 100644 --- a/lfs.c +++ b/lfs.c @@ -5747,8 +5747,6 @@ static int lfsr_mdir_suplookup(lfs_t *lfs, const lfsr_mdir_t *mdir, .u.mptr.weight=(LFSR_MTREE_ISMPTR | (_weight)), \ .u.mptr.mptr=_mptr}) -#define LFSR_MTREE_DSIZE LFS_MAX(LFSR_MPTR_DSIZE, LFSR_BTREE_DSIZE) - static inline bool lfsr_mtree_isnull(const lfsr_mtree_t *mtree) { return mtree->u.weight == (LFSR_MTREE_ISMPTR | 0); } @@ -6642,7 +6640,8 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfsr_fs_preparegdelta(lfs); // create a copy - lfsr_mdir_t mdir_ = *mdir; + lfsr_mdir_t mdir_[2]; + mdir_[0] = *mdir; // mark our mdir as unerased in case we fail mdir->rbyd.eoff = -1; // mark any copies of our mdir as unerased in case we fail @@ -6663,7 +6662,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // attempt to commit/compact the mdir normally lfsr_srid_t split_rid; - int err = lfsr_mdir_commit_(lfs, &mdir_, -1, -1, &split_rid, + int err = lfsr_mdir_commit_(lfs, &mdir_[0], -1, -1, &split_rid, mdir->mid, attrs, attr_count); if (err && err != LFS_ERR_RANGE @@ -6674,10 +6673,9 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // handle possible mtree updates, this gets a bit messy lfsr_mdir_t mroot_ = lfs->mroot; if (lfsr_mdir_cmp(mdir, &lfs->mroot) == 0) { - mroot_.rbyd = mdir_.rbyd; + mroot_.rbyd = mdir_[0].rbyd; } lfsr_mtree_t mtree_ = lfs->mtree; - lfsr_mdir_t msibling_; lfsr_smid_t mdelta = 0; // need to split? if (err == LFS_ERR_RANGE) { @@ -6697,58 +6695,40 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, } } - // order the split compacts so that that mdir containing our mid - // is committed last, this is a bit of a hack but necessary so - // shrubs are staged correctly for (int i = 0; i < 2; i++) { - if ((i == 0) ^ (lfsr_mid_rid(lfs, mdir->mid) >= split_rid)) { - // compact into new mdir tags >= split_rid - err = lfsr_mdir_alloc__(lfs, &msibling_, - lfs_smax32(mdir->mid, 0)); - if (err) { - goto failed; - } + // order the split compacts so that that mdir containing our mid + // is committed last, this is a bit of a hack but necessary so + // shrubs are staged correctly + bool left = lfsr_mid_rid(lfs, mdir->mid) < split_rid; - err = lfsr_mdir_compact__(lfs, &msibling_, - mdir, split_rid, -1); - if (err) { - LFS_ASSERT(err != LFS_ERR_RANGE); - goto failed; - } + // alloc and compact into new mdirs + err = lfsr_mdir_alloc__(lfs, &mdir_[i^left], + lfs_smax32(mdir->mid, 0)); + if (err) { + goto failed; + } - err = lfsr_mdir_commit__(lfs, &msibling_, split_rid, -1, - mdir->mid, attrs, attr_count); - if (err && err != LFS_ERR_NOENT) { - LFS_ASSERT(err != LFS_ERR_RANGE); - goto failed; - } + err = lfsr_mdir_compact__(lfs, &mdir_[i^left], + mdir, + ((i^left) == 0) ? 0 : split_rid, + ((i^left) == 0) ? split_rid : -1); + if (err) { + LFS_ASSERT(err != LFS_ERR_RANGE); + goto failed; + } - } else { - // compact into new mdir tags < split_rid - err = lfsr_mdir_alloc__(lfs, &mdir_, - lfs_smax32(mdir->mid, 0)); - if (err) { - goto failed; - } - - err = lfsr_mdir_compact__(lfs, &mdir_, - mdir, 0, split_rid); - if (err) { - LFS_ASSERT(err != LFS_ERR_RANGE); - goto failed; - } - - err = lfsr_mdir_commit__(lfs, &mdir_, 0, split_rid, - mdir->mid, attrs, attr_count); - if (err && err != LFS_ERR_NOENT) { - LFS_ASSERT(err != LFS_ERR_RANGE); - goto failed; - } + err = lfsr_mdir_commit__(lfs, &mdir_[i^left], + ((i^left) == 0) ? 0 : split_rid, + ((i^left) == 0) ? split_rid : -1, + mdir->mid, attrs, attr_count); + if (err && err != LFS_ERR_NOENT) { + LFS_ASSERT(err != LFS_ERR_RANGE); + goto failed; } } // adjust our sibling's mid after committing attrs - msibling_.mid += lfsr_mleafweight(lfs); + mdir_[1].mid += lfsr_mleafweight(lfs); LFS_DEBUG("Splitting mdir %"PRId32" " "0x{%"PRIx32",%"PRIx32"} " @@ -6756,39 +6736,39 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, "0x{%"PRIx32",%"PRIx32"}", mdir->mid >> lfs->mleaf_bits, mdir->rbyd.blocks[0], mdir->rbyd.blocks[1], - mdir_.rbyd.blocks[0], mdir_.rbyd.blocks[1], - msibling_.rbyd.blocks[0], msibling_.rbyd.blocks[1]); + mdir_[0].rbyd.blocks[0], mdir_[0].rbyd.blocks[1], + mdir_[1].rbyd.blocks[0], mdir_[1].rbyd.blocks[1]); // because of defered commits, children can be reduced to zero // when splitting, need to catch this here // both siblings reduced to zero - if (mdir_.rbyd.weight == 0 && msibling_.rbyd.weight == 0) { + if (mdir_[0].rbyd.weight == 0 && mdir_[1].rbyd.weight == 0) { LFS_DEBUG("Dropping mdir %"PRId32" " "0x{%"PRIx32",%"PRIx32"}", - mdir_.mid >> lfs->mleaf_bits, - mdir_.rbyd.blocks[0], mdir_.rbyd.blocks[1]); + mdir_[0].mid >> lfs->mleaf_bits, + mdir_[0].rbyd.blocks[0], mdir_[0].rbyd.blocks[1]); LFS_DEBUG("Dropping mdir %"PRId32" " "0x{%"PRIx32",%"PRIx32"}", - msibling_.mid >> lfs->mleaf_bits, - msibling_.rbyd.blocks[0], msibling_.rbyd.blocks[1]); + mdir_[1].mid >> lfs->mleaf_bits, + mdir_[1].rbyd.blocks[0], mdir_[1].rbyd.blocks[1]); goto drop; // one sibling reduced to zero - } else if (mdir_.rbyd.weight == 0) { + } else if (mdir_[0].rbyd.weight == 0) { LFS_DEBUG("Dropping mdir %"PRId32" " "0x{%"PRIx32",%"PRIx32"}", - mdir_.mid >> lfs->mleaf_bits, - mdir_.rbyd.blocks[0], mdir_.rbyd.blocks[1]); - mdir_.rbyd = msibling_.rbyd; + mdir_[0].mid >> lfs->mleaf_bits, + mdir_[0].rbyd.blocks[0], mdir_[0].rbyd.blocks[1]); + mdir_[0].rbyd = mdir_[1].rbyd; goto relocate; // other sibling reduced to zero - } else if (msibling_.rbyd.weight == 0) { + } else if (mdir_[1].rbyd.weight == 0) { LFS_DEBUG("Dropping mdir %"PRId32" " "0x{%"PRIx32",%"PRIx32"}", - msibling_.mid >> lfs->mleaf_bits, - msibling_.rbyd.blocks[0], msibling_.rbyd.blocks[1]); + mdir_[1].mid >> lfs->mleaf_bits, + mdir_[1].rbyd.blocks[0], mdir_[1].rbyd.blocks[1]); goto relocate; } @@ -6800,7 +6780,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // note we need to do this after playing out pending attrs in // case they introduce a new name! lfsr_data_t split_data; - err = lfsr_rbyd_sublookup(lfs, &msibling_.rbyd, 0, LFSR_TAG_NAME, + err = lfsr_rbyd_sublookup(lfs, &mdir_[1].rbyd, 0, LFSR_TAG_NAME, NULL, &split_data); if (err) { LFS_ASSERT(err != LFS_ERR_NOENT); @@ -6814,21 +6794,22 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, goto failed; } - uint8_t mdir_buf[LFSR_MPTR_DSIZE]; - uint8_t msibling_buf[LFSR_MPTR_DSIZE]; + uint8_t mdir_buf[2*LFSR_MPTR_DSIZE]; err = lfsr_btree_commit(lfs, &mtree_.u.btree, 0, LFSR_ATTRS( LFSR_ATTR( LFSR_TAG_MDIR, +lfsr_mleafweight(lfs), LFSR_DATA_MPTR_( - lfsr_mdir_mptr(&mdir_), mdir_buf)), + lfsr_mdir_mptr(&mdir_[0]), + &mdir_buf[0*LFSR_MPTR_DSIZE])), LFSR_ATTR_CAT_( LFSR_TAG_NAME, +lfsr_mleafweight(lfs), &split_data, 1), LFSR_ATTR( LFSR_TAG_MDIR, 0, LFSR_DATA_MPTR_( - lfsr_mdir_mptr(&msibling_), msibling_buf)))); + lfsr_mdir_mptr(&mdir_[1]), + &mdir_buf[1*LFSR_MPTR_DSIZE])))); if (err) { goto failed; } @@ -6838,21 +6819,22 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // mark as unerased in case of failure lfs->mtree.u.btree.eoff = -1; - uint8_t mdir_buf[LFSR_MPTR_DSIZE]; - uint8_t msibling_buf[LFSR_MPTR_DSIZE]; + uint8_t mdir_buf[2*LFSR_MPTR_DSIZE]; err = lfsr_btree_commit(lfs, &mtree_.u.btree, lfsr_mid_bid(lfs, mdir->mid), LFSR_ATTRS( LFSR_ATTR( LFSR_TAG_MDIR, 0, LFSR_DATA_MPTR_( - lfsr_mdir_mptr(&mdir_), mdir_buf)), + lfsr_mdir_mptr(&mdir_[0]), + &mdir_buf[0*LFSR_MPTR_DSIZE])), LFSR_ATTR_CAT_( LFSR_TAG_NAME, +lfsr_mleafweight(lfs), &split_data, 1), LFSR_ATTR( LFSR_TAG_MDIR, 0, LFSR_DATA_MPTR_( - lfsr_mdir_mptr(&msibling_), msibling_buf)))); + lfsr_mdir_mptr(&mdir_[1]), + &mdir_buf[1*LFSR_MPTR_DSIZE])))); if (err) { goto failed; } @@ -6892,19 +6874,19 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, } // need to relocate? - } else if (lfsr_mdir_cmp(&mdir_, mdir) != 0 + } else if (lfsr_mdir_cmp(&mdir_[0], mdir) != 0 && lfsr_mdir_cmp(mdir, &lfs->mroot) != 0) { LFS_DEBUG("Relocating mdir %"PRId32" " "0x{%"PRIx32",%"PRIx32"} -> 0x{%"PRIx32",%"PRIx32"}", mdir->mid >> lfs->mleaf_bits, mdir->rbyd.blocks[0], mdir->rbyd.blocks[1], - mdir_.rbyd.blocks[0], mdir_.rbyd.blocks[1]); + mdir_[0].rbyd.blocks[0], mdir_[0].rbyd.blocks[1]); relocate:; // new mtree? if (lfsr_mtree_ismptr(&lfs->mtree)) { mtree_ = LFSR_MTREE_MPTR( - *lfsr_mdir_mptr(&mdir_), + *lfsr_mdir_mptr(&mdir_[0]), lfsr_mleafweight(lfs)); } else { @@ -6918,7 +6900,8 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, LFSR_ATTR( LFSR_TAG_MDIR, 0, LFSR_DATA_MPTR_( - lfsr_mdir_mptr(&mdir_), mdir_buf)))); + lfsr_mdir_mptr(&mdir_[0]), + mdir_buf)))); if (err) { goto failed; } @@ -6943,9 +6926,9 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, if (lfsr_mid_bid(lfs, lfs->grm.mids[j]) == lfsr_mid_bid(lfs, lfs_smax32(mdir->mid, 0))) { if (lfsr_mid_rid(lfs, lfs->grm.mids[j]) - >= (lfsr_srid_t)mdir_.rbyd.weight) { + >= (lfsr_srid_t)mdir_[0].rbyd.weight) { lfs->grm.mids[j] - += lfsr_mleafweight(lfs) - mdir_.rbyd.weight; + += lfsr_mleafweight(lfs) - mdir_[0].rbyd.weight; } } else if (lfs->grm.mids[j] > mdir->mid) { lfs->grm.mids[j] += mdelta; @@ -7072,7 +7055,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // success? update in-device state, we must not error at this point // toss our cksum into the filesystem seed for pseudorandom numbers - lfs->seed ^= mdir_.rbyd.cksum; + lfs->seed ^= mdir_[0].rbyd.cksum; // update any gstate changes lfsr_fs_commitgdelta(lfs); @@ -7124,11 +7107,11 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, LFS_ASSERT(mdir->mid != -1 || mdir == &lfs->mroot); if (mdelta > 0 && lfsr_mid_rid(lfs, o->mdir.mid) - >= (lfsr_srid_t)mdir_.rbyd.weight) { - o->mdir.mid += lfsr_mleafweight(lfs) - mdir_.rbyd.weight; - o->mdir.rbyd = msibling_.rbyd; + >= (lfsr_srid_t)mdir_[0].rbyd.weight) { + o->mdir.mid += lfsr_mleafweight(lfs) - mdir_[0].rbyd.weight; + o->mdir.rbyd = mdir_[1].rbyd; } else { - o->mdir.rbyd = mdir_.rbyd; + o->mdir.rbyd = mdir_[0].rbyd; } } else if (o->mdir.mid > mdir->mid) { o->mdir.mid += mdelta; @@ -7139,11 +7122,11 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, LFS_ASSERT(mdir->mid != -1 || mdir == &lfs->mroot); if (mdelta > 0 && lfsr_mid_rid(lfs, mdir->mid) - >= (lfsr_srid_t)mdir_.rbyd.weight) { - mdir->mid += lfsr_mleafweight(lfs) - mdir_.rbyd.weight; - mdir->rbyd = msibling_.rbyd; + >= (lfsr_srid_t)mdir_[0].rbyd.weight) { + mdir->mid += lfsr_mleafweight(lfs) - mdir_[0].rbyd.weight; + mdir->rbyd = mdir_[1].rbyd; } else { - mdir->rbyd = mdir_.rbyd; + mdir->rbyd = mdir_[0].rbyd; } // update mroot and mtree