From ee3cd1ce886b6eed2ab731e9d583acce1b7c5b69 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Wed, 16 Jul 2025 21:56:17 -0500 Subject: [PATCH] btree: Brought back LFS3_ERR_EXIST when hitting a shrub root - LFS3_ERR_RANGE => need to split btree - LFS3_ERR_EXIST => hit a shrub root The distinct "hit shrub root" vs "split btree" error codes are a bit more self documenting and let us assert during test time that we never actually split bshrub roots. Maybe this will be reverted after some use, but in the short term better safe than sorry. --- This comes at a small code cost, I guess loading from constant pools is expensive (though, tbf, lfs3_btree_commit_ is a _big_ function, maybe the size makes constant pools trickier?). I'm guessing it's the constant pools because the changes in lfs3_bshrub_commit had no effect: code stack ctx before: 36800 2368 656 after: 36832 (+0.1%) 2368 (+0.0%) 656 (+0.0%) --- lfs3.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/lfs3.c b/lfs3.c index 6c78e1a4..1677c8df 100644 --- a/lfs3.c +++ b/lfs3.c @@ -5459,8 +5459,8 @@ static inline uint32_t lfs3_rev_btree(lfs3_t *lfs3); // core btree algorithm // // this commits up to the root, but stops if: -// 1. we need a new root -// 2. we have a shrub root +// 1. we need a new root => LFS3_ERR_RANGE +// 2. we hit a shrub root => LFS3_ERR_EXIST // // --- // @@ -5533,7 +5533,9 @@ static int lfs3_btree_commit_(lfs3_t *lfs3, if (!lfs3_rbyd_trunk(&child) || lfs3_rbyd_isshrub(btree)) { bcommit->bid = rid; - return LFS3_ERR_RANGE; + return (!lfs3_rbyd_trunk(&child)) + ? LFS3_ERR_RANGE + : LFS3_ERR_EXIST; } // mark btree as unerased in case of failure, our btree rbyd and @@ -6153,6 +6155,7 @@ static int lfs3_btree_commit(lfs3_t *lfs3, lfs3_btree_t *btree, int err = lfs3_btree_commit_(lfs3, &btree_, btree, &bcommit); if (err && err != LFS3_ERR_RANGE) { + LFS3_ASSERT(err != LFS3_ERR_EXIST); return err; } @@ -6900,7 +6903,8 @@ static int lfs3_bshrub_commit(lfs3_t *lfs3, lfs3_bshrub_t *bshrub, bcommit.rattr_count = rattr_count; int err = lfs3_btree_commit_(lfs3, &bshrub->shrub_, &bshrub->shrub, &bcommit); - if (err && err != LFS3_ERR_RANGE) { + if (err && err != LFS3_ERR_RANGE + && err != LFS3_ERR_EXIST) { return err; } @@ -6910,7 +6914,12 @@ static int lfs3_bshrub_commit(lfs3_t *lfs3, lfs3_bshrub_t *bshrub, // note that bshrubs can't go straight to splitting, bshrubs are // always converted to btrees first, which can't fail (shrub < 1/2 // block + commit < 1/2 block) - if (err == LFS3_ERR_RANGE) { + if (err == LFS3_ERR_RANGE + || err == LFS3_ERR_EXIST) { + // bshrubs can't go straight to splitting + LFS3_ASSERT(!lfs3_bshrub_isbshrub(bshrub) + || err != LFS3_ERR_RANGE); + // try to commit to shrub root err = lfs3_bshrub_commitroot_(lfs3, bshrub, bcommit.bid, bcommit.rattrs, bcommit.rattr_count);