Flipped btree/bshrub logic so commit__ implicitly finds rbyd

This does a few things:

- Deduplicates bshrub/btree rbyd lookups when rbyd is not explicitly
  provided -- note this is by far the most common case.

- Moves the mid-level rbyd allocation out of the stack-hot-path.

  Assuming lfsr_mtree_gc is never in the stack-hot-path, which seems
  unlikely.

- Reduces pointer chasing in lfsr_btree_commit__, giving the compiler
  more flexibility + assumptions and hopefully allowing it to optimize
  better.

  This may also be disentangling several cross-layer struct references,
  which is probably a good thing.

The result is rather significant stack savings for what is a minor
refactor:

           code          stack
  before: 35440           2800
  after:  35268 (-0.5%)   2680 (-4.3%)

This doesn't quite get us back to pre-commit_-rbyd levels, but it's
pretty close:

                                   code          stack
  before commit_-rbyd:            34652           2640
  commit_-rbyd-explicit (before): 35440 (+2.3%)   2800 (+6.1%)
  commit_-rbyd-implicit (after):  35268 (+1.8%)   2680 (+1.5%)
This commit is contained in:
Christopher Haster
2024-07-01 16:33:30 -05:00
parent e2ec25e511
commit 7f4384fa27
+147 -161
View File
@@ -4306,12 +4306,40 @@ typedef struct lfsr_bscratch {
//
static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
lfsr_bscratch_t *bscratch,
lfsr_bid_t bid, lfsr_rbyd_t *rbyd, lfsr_srid_t *rid_,
const lfsr_attr_t **attrs_, lfs_size_t *attr_count_) {
LFS_ASSERT(bid <= (lfsr_bid_t)btree->weight);
lfsr_srid_t rid = *rid_;
const lfsr_attr_t *attrs = *attrs_;
lfs_size_t attr_count = *attr_count_;
lfsr_bid_t *bid, lfsr_rbyd_t *rbyd, lfsr_srid_t rid,
const lfsr_attr_t **attrs, lfs_size_t *attr_count) {
lfsr_bid_t bid_ = *bid;
LFS_ASSERT(bid_ <= (lfsr_bid_t)btree->weight);
const lfsr_attr_t *attrs_ = *attrs;
lfs_size_t attr_count_ = *attr_count;
// if rbyd is NULL, lookup which leaf our bid resides
//
// for lfsr_btree_commit operations to work out, we need to
// limit our bid to an rid in the tree, which is what this min
// is doing
lfsr_rbyd_t rbyd_;
lfsr_srid_t rid_;
if (!rbyd) {
rbyd_ = *btree;
rid_ = bid_;
if (btree->weight > 0) {
lfsr_srid_t rid__;
int err = lfsr_btree_lookupnext_(lfs, btree,
lfs_min(bid_, btree->weight-1),
&bid_, &rbyd_, &rid__, NULL, NULL, NULL);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
return err;
}
// adjust rid
rid_ -= (bid_-rid__);
}
} else {
rbyd_ = *rbyd;
rid_ = rid;
}
// tail-recursively commit to btree
while (true) {
@@ -4319,16 +4347,16 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
lfsr_rbyd_t parent = {.trunk=0, .weight=0};
lfsr_srid_t pid = 0;
// are we root?
if (rbyd->blocks[0] == btree->blocks[0]
|| !lfsr_rbyd_trunk(rbyd)) {
if (rbyd_.blocks[0] == btree->blocks[0]
|| !lfsr_rbyd_trunk(&rbyd_)) {
// new root? shrub root? yield the final root commit to
// higher-level btree/bshrub logic
if (!lfsr_rbyd_trunk(rbyd)
if (!lfsr_rbyd_trunk(&rbyd_)
|| lfsr_rbyd_isshrub(btree)) {
*rid_ = rid;
*attrs_ = attrs;
*attr_count_ = attr_count;
return (!lfsr_rbyd_trunk(rbyd)) ? LFS_ERR_RANGE : 0;
*bid = rid_;
*attrs = attrs_;
*attr_count = attr_count_;
return (!lfsr_rbyd_trunk(&rbyd_)) ? LFS_ERR_RANGE : 0;
}
// mark btree as unerased in case of failure, our btree rbyd and
@@ -4337,7 +4365,7 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
btree->eoff = -1;
} else {
int err = lfsr_btree_parent(lfs, btree, bid, rbyd,
int err = lfsr_btree_parent(lfs, btree, bid_, &rbyd_,
&parent, &pid);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
@@ -4352,10 +4380,10 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
// unfetched
//
// a funny benefit is we cache the root of our btree this way
if (!lfsr_rbyd_isfetched(rbyd)) {
int err = lfsr_rbyd_fetchck(lfs, rbyd,
rbyd->blocks[0], lfsr_rbyd_trunk(rbyd),
rbyd->cksum);
if (!lfsr_rbyd_isfetched(&rbyd_)) {
int err = lfsr_rbyd_fetchck(lfs, &rbyd_,
rbyd_.blocks[0], lfsr_rbyd_trunk(&rbyd_),
rbyd_.cksum);
if (err) {
return err;
}
@@ -4364,9 +4392,9 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
// is rbyd erased? can we sneak our commit into any remaining
// erased bytes? note that the btree trunk field prevents this from
// interacting with other references to the rbyd
lfsr_rbyd_t rbyd_ = *rbyd;
int err = lfsr_rbyd_commit(lfs, &rbyd_, rid,
attrs, attr_count);
lfsr_rbyd_t rbyd__ = rbyd_;
int err = lfsr_rbyd_commit(lfs, &rbyd__, rid_,
attrs_, attr_count_);
if (err) {
if (err == LFS_ERR_RANGE || err == LFS_ERR_CORRUPT) {
goto compact;
@@ -4379,7 +4407,7 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
compact:;
// estimate our compacted size
lfsr_srid_t split_rid;
lfs_ssize_t estimate = lfsr_rbyd_estimate(lfs, rbyd, -1, -1,
lfs_ssize_t estimate = lfsr_rbyd_estimate(lfs, &rbyd_, -1, -1,
&split_rid);
if (estimate < 0) {
return estimate;
@@ -4445,14 +4473,14 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
}
// try the left sibling
if (pid-(lfsr_srid_t)rbyd->weight >= 0) {
if (pid-(lfsr_srid_t)rbyd_.weight >= 0) {
// try looking up the sibling
lfsr_srid_t sibling_rid;
lfsr_tag_t sibling_tag;
lfsr_rid_t sibling_weight;
lfsr_data_t sibling_data;
err = lfsr_rbyd_lookupnext(lfs, &parent,
pid-rbyd->weight, LFSR_TAG_NAME,
pid-rbyd_.weight, LFSR_TAG_NAME,
&sibling_rid, &sibling_tag, &sibling_weight,
&sibling_data);
if (err) {
@@ -4490,13 +4518,13 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
< lfs->cfg->block_size/2) {
// if we're merging our left sibling, swap our rbyds
// so our sibling is on the right
bid -= sibling.weight;
rid += sibling.weight;
pid -= rbyd->weight;
bid_ -= sibling.weight;
rid_ += sibling.weight;
pid -= rbyd_.weight;
rbyd_ = sibling;
sibling = *rbyd;
*rbyd = rbyd_;
rbyd__ = sibling;
sibling = rbyd_;
rbyd_ = rbyd__;
goto merge;
}
@@ -4505,13 +4533,13 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
compact_relocate:;
// allocate a new rbyd
err = lfsr_rbyd_alloc(lfs, &rbyd_);
err = lfsr_rbyd_alloc(lfs, &rbyd__);
if (err) {
return err;
}
// try to compact
err = lfsr_rbyd_compact(lfs, &rbyd_, rbyd, -1, -1);
err = lfsr_rbyd_compact(lfs, &rbyd__, &rbyd_, -1, -1);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
// bad prog? try another block
@@ -4523,8 +4551,8 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
// append any pending attrs, it's up to upper
// layers to make sure these always fit
err = lfsr_rbyd_commit(lfs, &rbyd_, rid,
attrs, attr_count);
err = lfsr_rbyd_commit(lfs, &rbyd__, rid_,
attrs_, attr_count_);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
// bad prog? try another block
@@ -4539,17 +4567,17 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
split:;
// we should have something to split here
LFS_ASSERT(split_rid > 0
&& split_rid < (lfsr_srid_t)rbyd->weight);
&& split_rid < (lfsr_srid_t)rbyd_.weight);
split_relocate_l:;
// allocate a new rbyd
err = lfsr_rbyd_alloc(lfs, &rbyd_);
err = lfsr_rbyd_alloc(lfs, &rbyd__);
if (err) {
return err;
}
// copy over tags < split_rid
err = lfsr_rbyd_compact(lfs, &rbyd_, rbyd, -1, split_rid);
err = lfsr_rbyd_compact(lfs, &rbyd__, &rbyd_, -1, split_rid);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
// bad prog? try another block
@@ -4563,8 +4591,8 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
//
// upper layers should make sure this can't fail by limiting the
// maximum commit size
err = lfsr_rbyd_appendattrs(lfs, &rbyd_, rid, -1, split_rid,
attrs, attr_count);
err = lfsr_rbyd_appendattrs(lfs, &rbyd__, rid_, -1, split_rid,
attrs_, attr_count_);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
// bad prog? try another block
@@ -4575,7 +4603,7 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
}
// finalize commit
err = lfsr_rbyd_appendcksum(lfs, &rbyd_);
err = lfsr_rbyd_appendcksum(lfs, &rbyd__);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
// bad prog? try another block
@@ -4593,7 +4621,7 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
}
// copy over tags >= split_rid
err = lfsr_rbyd_compact(lfs, &sibling, rbyd, split_rid, -1);
err = lfsr_rbyd_compact(lfs, &sibling, &rbyd_, split_rid, -1);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
// bad prog? try another block
@@ -4607,8 +4635,8 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
//
// upper layers should make sure this can't fail by limiting the
// maximum commit size
err = lfsr_rbyd_appendattrs(lfs, &sibling, rid, split_rid, -1,
attrs, attr_count);
err = lfsr_rbyd_appendattrs(lfs, &sibling, rid_, split_rid, -1,
attrs_, attr_count_);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
// bad prog? try another block
@@ -4631,9 +4659,9 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
// did one of our siblings drop to zero? yes this can happen! revert
// to a normal commit in that case
if (rbyd_.weight == 0 || sibling.weight == 0) {
if (rbyd_.weight == 0) {
rbyd_ = sibling;
if (rbyd__.weight == 0 || sibling.weight == 0) {
if (rbyd__.weight == 0) {
rbyd__ = sibling;
}
goto recurse;
}
@@ -4651,66 +4679,66 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
}
// prepare commit to parent, tail recursing upwards
LFS_ASSERT(rbyd_.weight > 0);
LFS_ASSERT(rbyd__.weight > 0);
LFS_ASSERT(sibling.weight > 0);
attr_count = 0;
attr_count_ = 0;
// new root?
if (!lfsr_rbyd_trunk(&parent)) {
bscratch->attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_BRANCH, +rbyd_.weight,
bscratch->attrs[attr_count_++] = LFSR_ATTR(
LFSR_TAG_BRANCH, +rbyd__.weight,
LFSR_DATA_BRANCH_(
&rbyd_,
&rbyd__,
&bscratch->buf[0*LFSR_BRANCH_DSIZE]));
bscratch->attrs[attr_count++] = LFSR_ATTR(
bscratch->attrs[attr_count_++] = LFSR_ATTR(
LFSR_TAG_BRANCH, +sibling.weight,
LFSR_DATA_BRANCH_(
&sibling,
&bscratch->buf[1*LFSR_BRANCH_DSIZE]));
if (lfsr_tag_suptype(split_tag) == LFSR_TAG_NAME) {
bscratch->attrs[attr_count++] = LFSR_ATTR_CAT_(
bscratch->attrs[attr_count_++] = LFSR_ATTR_CAT_(
LFSR_TAG_NAME, 0,
&bscratch->split_data, 1);
}
// split root?
} else {
bid -= pid - (rbyd->weight-1);
bscratch->attrs[attr_count++] = LFSR_ATTR(
bid_ -= pid - (rbyd_.weight-1);
bscratch->attrs[attr_count_++] = LFSR_ATTR(
LFSR_TAG_BRANCH, 0,
LFSR_DATA_BRANCH_(
&rbyd_,
&rbyd__,
&bscratch->buf[0*LFSR_BRANCH_DSIZE]));
if (rbyd_.weight != rbyd->weight) {
bscratch->attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_GROW, -rbyd->weight + rbyd_.weight,
if (rbyd__.weight != rbyd_.weight) {
bscratch->attrs[attr_count_++] = LFSR_ATTR(
LFSR_TAG_GROW, -rbyd_.weight + rbyd__.weight,
LFSR_DATA_NULL());
}
bscratch->attrs[attr_count++] = LFSR_ATTR(
bscratch->attrs[attr_count_++] = LFSR_ATTR(
LFSR_TAG_BRANCH, +sibling.weight,
LFSR_DATA_BRANCH_(
&sibling,
&bscratch->buf[1*LFSR_BRANCH_DSIZE]));
if (lfsr_tag_suptype(split_tag) == LFSR_TAG_NAME) {
bscratch->attrs[attr_count++] = LFSR_ATTR_CAT_(
bscratch->attrs[attr_count_++] = LFSR_ATTR_CAT_(
LFSR_TAG_NAME, 0,
&bscratch->split_data, 1);
}
}
attrs = bscratch->attrs;
attrs_ = bscratch->attrs;
*rbyd = parent;
rid = pid;
rbyd_ = parent;
rid_ = pid;
continue;
merge:;
merge_relocate:;
// allocate a new rbyd
err = lfsr_rbyd_alloc(lfs, &rbyd_);
err = lfsr_rbyd_alloc(lfs, &rbyd__);
if (err) {
return err;
}
// merge the siblings together
err = lfsr_rbyd_appendcompactrbyd(lfs, &rbyd_, rbyd, -1, -1);
err = lfsr_rbyd_appendcompactrbyd(lfs, &rbyd__, &rbyd_, -1, -1);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
// bad prog? try another block
@@ -4720,7 +4748,7 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
return err;
}
err = lfsr_rbyd_appendcompactrbyd(lfs, &rbyd_, &sibling, -1, -1);
err = lfsr_rbyd_appendcompactrbyd(lfs, &rbyd__, &sibling, -1, -1);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
// bad prog? try another block
@@ -4730,7 +4758,7 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
return err;
}
err = lfsr_rbyd_appendcompaction(lfs, &rbyd_, 0);
err = lfsr_rbyd_appendcompaction(lfs, &rbyd__, 0);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
// bad prog? try another block
@@ -4742,8 +4770,8 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
// append any pending attrs, it's up to upper
// layers to make sure these always fit
err = lfsr_rbyd_commit(lfs, &rbyd_, rid,
attrs, attr_count);
err = lfsr_rbyd_commit(lfs, &rbyd__, rid_,
attrs_, attr_count_);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
// bad prog? try another block
@@ -4756,46 +4784,46 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
// we must have a parent at this point, but is our parent the root
// and is the root degenerate?
LFS_ASSERT(lfsr_rbyd_trunk(&parent));
if (rbyd->weight+sibling.weight == btree->weight) {
if (rbyd_.weight+sibling.weight == btree->weight) {
// collapse the root, decreasing the height of the tree
*btree = rbyd_;
*attr_count_ = 0;
*btree = rbyd__;
*attr_count = 0;
return 0;
}
// prepare commit to parent, tail recursing upwards
LFS_ASSERT(rbyd_.weight > 0);
attr_count = 0;
bid -= pid - (rbyd->weight-1);
bscratch->attrs[attr_count++] = LFSR_ATTR(
LFS_ASSERT(rbyd__.weight > 0);
attr_count_ = 0;
bid_ -= pid - (rbyd_.weight-1);
bscratch->attrs[attr_count_++] = LFSR_ATTR(
LFSR_TAG_RM, -sibling.weight, LFSR_DATA_NULL());
bscratch->attrs[attr_count++] = LFSR_ATTR(
bscratch->attrs[attr_count_++] = LFSR_ATTR(
LFSR_TAG_BRANCH, 0,
LFSR_DATA_BRANCH_(&rbyd_, bscratch->buf));
if (rbyd_.weight != rbyd->weight) {
bscratch->attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_GROW, -rbyd->weight + rbyd_.weight,
LFSR_DATA_BRANCH_(&rbyd__, bscratch->buf));
if (rbyd__.weight != rbyd_.weight) {
bscratch->attrs[attr_count_++] = LFSR_ATTR(
LFSR_TAG_GROW, -rbyd_.weight + rbyd__.weight,
LFSR_DATA_NULL());
}
attrs = bscratch->attrs;
attrs_ = bscratch->attrs;
*rbyd = parent;
rid = pid + sibling.weight;
rbyd_ = parent;
rid_ = pid + sibling.weight;
continue;
recurse:;
// done?
if (!lfsr_rbyd_trunk(&parent)) {
*btree = rbyd_;
*attr_count_ = 0;
*btree = rbyd__;
*attr_count = 0;
return 0;
}
// is our parent the root and is the root degenerate?
if (rbyd->weight == btree->weight) {
if (rbyd_.weight == btree->weight) {
// collapse the root, decreasing the height of the tree
*btree = rbyd_;
*attr_count_ = 0;
*btree = rbyd__;
*attr_count = 0;
return 0;
}
@@ -4803,36 +4831,37 @@ static int lfsr_btree_commit__(lfs_t *lfs, lfsr_btree_t *btree,
//
// note that since we defer merges to compaction time, we can
// end up removing an rbyd here
attr_count = 0;
bid -= pid - (rbyd->weight-1);
if (rbyd_.weight == 0) {
bscratch->attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_RM, -rbyd->weight, LFSR_DATA_NULL());
attr_count_ = 0;
bid_ -= pid - (rbyd_.weight-1);
if (rbyd__.weight == 0) {
bscratch->attrs[attr_count_++] = LFSR_ATTR(
LFSR_TAG_RM, -rbyd_.weight, LFSR_DATA_NULL());
} else {
bscratch->attrs[attr_count++] = LFSR_ATTR(
bscratch->attrs[attr_count_++] = LFSR_ATTR(
LFSR_TAG_BRANCH, 0,
LFSR_DATA_BRANCH_(&rbyd_, bscratch->buf));
if (rbyd_.weight != rbyd->weight) {
bscratch->attrs[attr_count++] = LFSR_ATTR(
LFSR_TAG_GROW, -rbyd->weight + rbyd_.weight,
LFSR_DATA_BRANCH_(&rbyd__, bscratch->buf));
if (rbyd__.weight != rbyd_.weight) {
bscratch->attrs[attr_count_++] = LFSR_ATTR(
LFSR_TAG_GROW, -rbyd_.weight + rbyd__.weight,
LFSR_DATA_NULL());
}
}
attrs = bscratch->attrs;
attrs_ = bscratch->attrs;
*rbyd = parent;
rid = pid;
rbyd_ = parent;
rid_ = pid;
continue;
}
}
// commit to btree with optional rbyd
static int lfsr_btree_commit_(lfs_t *lfs, lfsr_btree_t *btree,
lfsr_bid_t bid, lfsr_rbyd_t *rbyd, lfsr_srid_t rid,
const lfsr_attr_t *attrs, lfs_size_t attr_count) {
// try to commit to the btree
lfsr_bscratch_t bscratch;
int err = lfsr_btree_commit__(lfs, btree, &bscratch,
bid, rbyd, &rid, &attrs, &attr_count);
&bid, rbyd, rid, &attrs, &attr_count);
if (err && err != LFS_ERR_RANGE) {
return err;
}
@@ -4842,12 +4871,13 @@ static int lfsr_btree_commit_(lfs_t *lfs, lfsr_btree_t *btree,
LFS_ASSERT(attr_count > 0);
relocate:;
err = lfsr_rbyd_alloc(lfs, rbyd);
lfsr_rbyd_t rbyd_;
err = lfsr_rbyd_alloc(lfs, &rbyd_);
if (err) {
return err;
}
err = lfsr_rbyd_commit(lfs, rbyd, rid, attrs, attr_count);
err = lfsr_rbyd_commit(lfs, &rbyd_, bid, attrs, attr_count);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
// bad prog? try another block
@@ -4857,7 +4887,7 @@ static int lfsr_btree_commit_(lfs_t *lfs, lfsr_btree_t *btree,
return err;
}
*btree = *rbyd;
*btree = rbyd_;
}
LFS_ASSERT(lfsr_rbyd_trunk(btree));
@@ -4876,28 +4906,7 @@ static int lfsr_btree_compact_(lfs_t *lfs, lfsr_btree_t *btree,
// commit to a btree, this is atomic
static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
lfsr_bid_t bid, const lfsr_attr_t *attrs, lfs_size_t attr_count) {
// lookup in which leaf our bids resides
//
// for lfsr_btree_commit operations to work out, we need to
// limit our bid to an rid in the tree, which is what this min
// is doing
lfsr_rbyd_t rbyd = *btree;
lfsr_srid_t rid = bid;
if (btree->weight > 0) {
lfsr_srid_t rid_;
int err = lfsr_btree_lookupnext_(lfs, btree,
lfs_min(bid, btree->weight-1),
&bid, &rbyd, &rid_, NULL, NULL, NULL);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
return err;
}
// adjust rid
rid -= (bid-rid_);
}
return lfsr_btree_commit_(lfs, btree, bid, &rbyd, rid,
return lfsr_btree_commit_(lfs, btree, bid, NULL, -1,
attrs, attr_count);
}
@@ -5624,6 +5633,7 @@ static int lfsr_bshrub_traverse(lfs_t *lfs,
static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
const lfsr_attr_t *attrs, lfs_size_t attr_count);
// commit to bshrub with optional rbyd
static int lfsr_bshrub_commit_(lfs_t *lfs,
lfsr_mdir_t *mdir, lfsr_bshrub_t *bshrub,
lfsr_bid_t bid, lfsr_rbyd_t *rbyd, lfsr_srid_t rid,
@@ -5652,7 +5662,7 @@ static int lfsr_bshrub_commit_(lfs_t *lfs,
// try to commit to the btree
lfsr_bscratch_t bscratch;
int err = lfsr_btree_commit__(lfs, &bshrub->u.btree, &bscratch,
bid, rbyd, &rid, &attrs, &attr_count);
&bid, rbyd, rid, &attrs, &attr_count);
if (err && err != LFS_ERR_RANGE) {
return err;
}
@@ -5717,7 +5727,7 @@ static int lfsr_bshrub_commit_(lfs_t *lfs,
int err = lfsr_mdir_commit(lfs, mdir, LFSR_ATTRS(
LFSR_ATTR_SHRUBCOMMIT(
LFSR_TAG_SHRUBCOMMIT, 0,
&bshrub->u.bshrub, rid, attrs, attr_count)));
&bshrub->u.bshrub, bid, attrs, attr_count)));
if (err) {
return err;
}
@@ -5743,15 +5753,15 @@ static int lfsr_bshrub_commit_(lfs_t *lfs,
relocate:;
// convert to btree
err = lfsr_rbyd_alloc(lfs, rbyd);
lfsr_rbyd_t rbyd_;
err = lfsr_rbyd_alloc(lfs, &rbyd_);
if (err) {
return err;
}
// note this may be a new root
if (!alloc) {
err = lfsr_rbyd_compact(lfs, rbyd,
&bshrub->u.btree, -1, -1);
err = lfsr_rbyd_compact(lfs, &rbyd_, &bshrub->u.btree, -1, -1);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
// bad prog? try another block
@@ -5762,8 +5772,7 @@ relocate:;
}
}
err = lfsr_rbyd_commit(lfs, rbyd, rid,
attrs, attr_count);
err = lfsr_rbyd_commit(lfs, &rbyd_, bid, attrs, attr_count);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
// bad prog? try another block
@@ -5773,7 +5782,7 @@ relocate:;
return err;
}
bshrub->u.btree = *rbyd;
bshrub->u.btree = rbyd_;
return 0;
}
@@ -5793,30 +5802,7 @@ static int lfsr_bshrub_commit(lfs_t *lfs,
lfsr_bid_t bid, const lfsr_attr_t *attrs, lfs_size_t attr_count) {
// file must be a bshrub/btree here
LFS_ASSERT(lfsr_bshrub_isbshruborbtree(bshrub));
// TODO can we dedup the lookup logic?
// lookup in which leaf our bids resides
//
// for lfsr_btree_commit operations to work out, we need to
// limit our bid to an rid in the tree, which is what this min
// is doing
lfsr_rbyd_t rbyd = bshrub->u.btree;
lfsr_srid_t rid = bid;
if (bshrub->u.btree.weight > 0) {
lfsr_srid_t rid_;
int err = lfsr_btree_lookupnext_(lfs, &bshrub->u.btree,
lfs_min(bid, bshrub->u.btree.weight-1),
&bid, &rbyd, &rid_, NULL, NULL, NULL);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
return err;
}
// adjust rid
rid -= (bid-rid_);
}
return lfsr_bshrub_commit_(lfs, mdir, bshrub, bid, &rbyd, rid,
return lfsr_bshrub_commit_(lfs, mdir, bshrub, bid, NULL, -1,
attrs, attr_count);
}