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%)
This commit is contained in:
Christopher Haster
2025-07-16 21:56:17 -05:00
parent a6dff0539c
commit ee3cd1ce88
+14 -5
View File
@@ -5459,8 +5459,8 @@ static inline uint32_t lfs3_rev_btree(lfs3_t *lfs3);
// core btree algorithm // core btree algorithm
// //
// this commits up to the root, but stops if: // this commits up to the root, but stops if:
// 1. we need a new root // 1. we need a new root => LFS3_ERR_RANGE
// 2. we have a shrub root // 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) if (!lfs3_rbyd_trunk(&child)
|| lfs3_rbyd_isshrub(btree)) { || lfs3_rbyd_isshrub(btree)) {
bcommit->bid = rid; 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 // 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, int err = lfs3_btree_commit_(lfs3, &btree_, btree,
&bcommit); &bcommit);
if (err && err != LFS3_ERR_RANGE) { if (err && err != LFS3_ERR_RANGE) {
LFS3_ASSERT(err != LFS3_ERR_EXIST);
return err; return err;
} }
@@ -6900,7 +6903,8 @@ static int lfs3_bshrub_commit(lfs3_t *lfs3, lfs3_bshrub_t *bshrub,
bcommit.rattr_count = rattr_count; bcommit.rattr_count = rattr_count;
int err = lfs3_btree_commit_(lfs3, &bshrub->shrub_, &bshrub->shrub, int err = lfs3_btree_commit_(lfs3, &bshrub->shrub_, &bshrub->shrub,
&bcommit); &bcommit);
if (err && err != LFS3_ERR_RANGE) { if (err && err != LFS3_ERR_RANGE
&& err != LFS3_ERR_EXIST) {
return err; 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 // note that bshrubs can't go straight to splitting, bshrubs are
// always converted to btrees first, which can't fail (shrub < 1/2 // always converted to btrees first, which can't fail (shrub < 1/2
// block + commit < 1/2 block) // 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 // try to commit to shrub root
err = lfs3_bshrub_commitroot_(lfs3, bshrub, err = lfs3_bshrub_commitroot_(lfs3, bshrub,
bcommit.bid, bcommit.rattrs, bcommit.rattr_count); bcommit.bid, bcommit.rattrs, bcommit.rattr_count);