Changed btree merge to merge siblings via compaction
This extends lfsr_rbyd_compact to support compaction of any number of
rbyds (though we only ever compact 1 or 2), and leverages this to
compact both siblings during btree merges.
This should improve erased storage utilization for btree merges, help
maintain a better balance in the tree (since more merges can complete
successfully), and hopefully lessen the impact of repeated merge+splits.
Since merges are now compacted, we can also be sure the combined merge
fits in 1/2 our block (hand-waving the split name for now, though this
does need to be considered when determining btree commit limits). This
lets us move the merge code entirely before writing out the attr-list,
making this operation more in line with split/compact and offering more
chance as code deduplication.
code stack
before: 20626 1728
after: 20634 (+0.0%) 1712 (-0.9%)
This also ironically discards the previous work to find a simple
estimate of upper bound of uncompacted rbyds, though I'm sure that will
useful again at some point in the future.
This commit is contained in:
@@ -3003,9 +3003,9 @@ static int lfsr_rbyd_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int lfsr_rbyd_compact(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
static int lfsr_rbyd_compact_(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
||||||
lfs_ssize_t start_rid, lfs_ssize_t end_rid,
|
lfs_ssize_t start_rid, lfs_ssize_t end_rid,
|
||||||
const lfsr_rbyd_t *source) {
|
const lfsr_rbyd_t *const *rbyds, lfs_size_t rbyd_count) {
|
||||||
#ifndef LFSR_NO_REBALANCE
|
#ifndef LFSR_NO_REBALANCE
|
||||||
// must fetch before mutating!
|
// must fetch before mutating!
|
||||||
LFS_ASSERT(lfsr_rbyd_isfetched(rbyd));
|
LFS_ASSERT(lfsr_rbyd_isfetched(rbyd));
|
||||||
@@ -3031,17 +3031,20 @@ static int lfsr_rbyd_compact(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
|
|
||||||
// first copy over raw tags, note this doesn't create a tree
|
// first copy over raw tags, note this doesn't create a tree
|
||||||
lfs_off_t layer_off = rbyd->eoff;
|
lfs_off_t layer_off = rbyd->eoff;
|
||||||
|
lfs_ssize_t bid = 0;
|
||||||
|
for (lfs_size_t i = 0; i < rbyd_count; i++) {
|
||||||
lfs_ssize_t rid = start_rid;
|
lfs_ssize_t rid = start_rid;
|
||||||
lfsr_tag_t tag = 0;
|
lfsr_tag_t tag = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
lfs_size_t weight;
|
lfs_size_t weight;
|
||||||
lfsr_data_t data;
|
lfsr_data_t data;
|
||||||
int err = lfsr_rbyd_lookupnext(lfs, source, rid, lfsr_tag_next(tag),
|
int err = lfsr_rbyd_lookupnext(lfs, rbyds[i],
|
||||||
|
rid, lfsr_tag_next(tag),
|
||||||
&rid, &tag, &weight, &data);
|
&rid, &tag, &weight, &data);
|
||||||
if (err && err != LFS_ERR_NOENT) {
|
if (err && err != LFS_ERR_NOENT) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (err == LFS_ERR_NOENT || (end_rid >= 0 && rid >= end_rid)) {
|
if (err == LFS_ERR_NOENT || (end_rid >= 0 && bid+rid >= end_rid)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3075,6 +3078,9 @@ static int lfsr_rbyd_compact(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
|||||||
layer_weight += weight;
|
layer_weight += weight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bid += rbyds[i]->weight;
|
||||||
|
}
|
||||||
|
|
||||||
// connect every other trunk together, building layers of a perfectly
|
// connect every other trunk together, building layers of a perfectly
|
||||||
// balanced binary tree upwards until we have a single trunk
|
// balanced binary tree upwards until we have a single trunk
|
||||||
while (layer_trunks > 1) {
|
while (layer_trunks > 1) {
|
||||||
@@ -3201,6 +3207,20 @@ failed:;
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int lfsr_rbyd_compact(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
|
||||||
|
lfs_ssize_t start_rid, lfs_ssize_t end_rid,
|
||||||
|
const lfsr_rbyd_t *rbyd) {
|
||||||
|
return lfsr_rbyd_compact_(lfs, rbyd_, start_rid, end_rid,
|
||||||
|
(const lfsr_rbyd_t *const[1]){rbyd}, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int lfsr_rbyd_merge(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
|
||||||
|
lfs_ssize_t start_rid, lfs_ssize_t end_rid,
|
||||||
|
const lfsr_rbyd_t *rbyd, const lfsr_rbyd_t *sibling) {
|
||||||
|
return lfsr_rbyd_compact_(lfs, rbyd_, start_rid, end_rid,
|
||||||
|
(const lfsr_rbyd_t *const[2]){rbyd, sibling}, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// the following are mostly btree helpers, but since they operate on rbyds,
|
// the following are mostly btree helpers, but since they operate on rbyds,
|
||||||
// exist in the rbyd namespace
|
// exist in the rbyd namespace
|
||||||
@@ -3965,10 +3985,7 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
goto commit;
|
goto commit;
|
||||||
|
|
||||||
compact:;
|
compact:;
|
||||||
// can't commit, try to compact
|
// estimate our compacted size
|
||||||
|
|
||||||
// check if we're within our compaction threshold, otherwise we
|
|
||||||
// need to split
|
|
||||||
lfs_size_t split_rid;
|
lfs_size_t split_rid;
|
||||||
lfs_ssize_t estimate = lfsr_rbyd_estimateall(lfs, &rbyd, -1, -1,
|
lfs_ssize_t estimate = lfsr_rbyd_estimateall(lfs, &rbyd, -1, -1,
|
||||||
&split_rid);
|
&split_rid);
|
||||||
@@ -3976,63 +3993,30 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
return estimate;
|
return estimate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// are we too big? need to split?
|
||||||
if ((lfs_size_t)estimate > lfs->cfg->block_size/2) {
|
if ((lfs_size_t)estimate > lfs->cfg->block_size/2) {
|
||||||
// need to split
|
// need to split
|
||||||
goto split;
|
goto split;
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate a new rbyd
|
// before we compact, can we merge with our siblings?
|
||||||
err = lfsr_rbyd_alloc(lfs, &rbyd_);
|
|
||||||
if (err) {
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// try to compact
|
|
||||||
err = lfsr_rbyd_compact(lfs, &rbyd_, -1, -1, &rbyd);
|
|
||||||
if (err) {
|
|
||||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// append any pending attrs, it's up to upper
|
|
||||||
// layers to make sure these always fit
|
|
||||||
err = lfsr_rbyd_appendall(lfs, &rbyd_, bid, -1, -1,
|
|
||||||
attrs, attr_count);
|
|
||||||
if (err) {
|
|
||||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
// is our compacted size too small? can we merge with one of our
|
|
||||||
// siblings?
|
|
||||||
lfsr_rbyd_t sibling;
|
lfsr_rbyd_t sibling;
|
||||||
lfs_ssize_t sibling_rid;
|
|
||||||
lfs_ssize_t sibling_delta;
|
|
||||||
if (rbyd_.eoff <= lfs->cfg->block_size/4
|
|
||||||
// don't merge if our rbyd went to zero, just drop
|
|
||||||
&& rbyd_.weight > 0
|
|
||||||
// no parent? can't merge
|
|
||||||
&& rid != -1) {
|
|
||||||
for (uint8_t i = 0; i < 2; i++) {
|
for (uint8_t i = 0; i < 2; i++) {
|
||||||
|
lfs_ssize_t sibling_rid;
|
||||||
// try the right sibling
|
// try the right sibling
|
||||||
if (i == 0) {
|
if (i == 0) {
|
||||||
// right-most child? can't merge
|
|
||||||
if ((lfs_size_t)rid == parent.weight-1) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
sibling_rid = rid+1;
|
sibling_rid = rid+1;
|
||||||
sibling_delta = rbyd_.weight;
|
|
||||||
|
|
||||||
// try the left sibling
|
// try the left sibling
|
||||||
} else {
|
} else {
|
||||||
// left-most child? can't merge
|
sibling_rid = rid-rbyd.weight;
|
||||||
if ((lfs_size_t)rid-(rbyd.weight-1) == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sibling_rid = rid-rbyd.weight;
|
// no parent? no sibling?
|
||||||
sibling_delta = 0;
|
if (rid == -1
|
||||||
|
|| sibling_rid < 0
|
||||||
|
|| sibling_rid >= (lfs_ssize_t)parent.weight) {
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// try looking up the sibling
|
// try looking up the sibling
|
||||||
@@ -4071,27 +4055,52 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// estimate if our sibling will fit
|
// estimate if our sibling will fit
|
||||||
lfs_ssize_t estimate = lfsr_rbyd_estimateall(lfs,
|
lfs_ssize_t sibling_estimate = lfsr_rbyd_estimateall(lfs,
|
||||||
&sibling, -1, -1,
|
&sibling, -1, -1,
|
||||||
NULL);
|
NULL);
|
||||||
if (estimate < 0) {
|
if (sibling_estimate < 0) {
|
||||||
return estimate;
|
return estimate;
|
||||||
}
|
}
|
||||||
|
|
||||||
// doesn't fit? can't merge
|
// fits? try to merge
|
||||||
//
|
if ((lfs_size_t)(estimate + sibling_estimate)
|
||||||
// note we use our uncompacted estimate here, since we need to
|
< lfs->cfg->block_size/2) {
|
||||||
// make sure our commit that merges the sibling doesn't fail
|
if (i == 1) {
|
||||||
if (estimate * lfs_nlog2((rbyd_.eoff+estimate)/16)
|
// if we're merging our left sibling, swap our rbyds
|
||||||
> lfs->cfg->block_size/4) {
|
// so our sibling is on the right
|
||||||
continue;
|
bid -= sibling.weight;
|
||||||
}
|
rid -= rbyd.weight;
|
||||||
|
|
||||||
// found a sibling that can be merged
|
rbyd_ = sibling;
|
||||||
|
sibling = rbyd;
|
||||||
|
rbyd = rbyd_;
|
||||||
|
}
|
||||||
goto merge;
|
goto merge;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// allocate a new rbyd
|
||||||
|
err = lfsr_rbyd_alloc(lfs, &rbyd_);
|
||||||
|
if (err) {
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// try to compact
|
||||||
|
err = lfsr_rbyd_compact(lfs, &rbyd_, -1, -1, &rbyd);
|
||||||
|
if (err) {
|
||||||
|
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
// append any pending attrs, it's up to upper
|
||||||
|
// layers to make sure these always fit
|
||||||
|
err = lfsr_rbyd_appendall(lfs, &rbyd_, bid, -1, -1,
|
||||||
|
attrs, attr_count);
|
||||||
|
if (err) {
|
||||||
|
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
// finalize commit
|
// finalize commit
|
||||||
err = lfsr_rbyd_appendcksum(lfs, &rbyd_);
|
err = lfsr_rbyd_appendcksum(lfs, &rbyd_);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -4130,11 +4139,13 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
scratch_attrs[0] = LFSR_ATTR(
|
scratch_attrs[0] = LFSR_ATTR(
|
||||||
bid+rid, BRANCH, 0,
|
bid+rid, BRANCH, 0,
|
||||||
BUF(scratch_buf, scratch_dsize));
|
BUF(scratch_buf, scratch_dsize));
|
||||||
scratch_attrs[1] = LFSR_ATTR(
|
scratch_attrs[1] = (rbyd_.weight == 0
|
||||||
bid+rid,
|
? LFSR_ATTR(
|
||||||
TAG(rbyd_.weight > 0 ? LFSR_TAG_GROW(RM) : LFSR_TAG_RM),
|
bid+rid, RM, -rbyd.weight,
|
||||||
+rbyd_.weight-rbyd.weight,
|
NULL)
|
||||||
NULL);
|
: LFSR_ATTR(
|
||||||
|
bid+rid, GROW(RM), +rbyd_.weight-rbyd.weight,
|
||||||
|
NULL));
|
||||||
attrs = scratch_attrs;
|
attrs = scratch_attrs;
|
||||||
attr_count = 2;
|
attr_count = 2;
|
||||||
|
|
||||||
@@ -4229,19 +4240,6 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t *scratch1_buf = scratch_buf;
|
|
||||||
uint8_t *scratch2_buf = scratch_buf + LFSR_BRANCH_DSIZE;
|
|
||||||
lfs_ssize_t scratch1_dsize = lfsr_branch_todisk(lfs, &rbyd_,
|
|
||||||
scratch1_buf);
|
|
||||||
if (scratch1_dsize < 0) {
|
|
||||||
return scratch1_dsize;
|
|
||||||
}
|
|
||||||
lfs_ssize_t scratch2_dsize = lfsr_branch_todisk(lfs, &sibling,
|
|
||||||
scratch2_buf);
|
|
||||||
if (scratch2_dsize < 0) {
|
|
||||||
return scratch2_dsize;
|
|
||||||
}
|
|
||||||
|
|
||||||
// no parent? introduce a new root
|
// no parent? introduce a new root
|
||||||
if (rid == -1) {
|
if (rid == -1) {
|
||||||
LFS_ASSERT(bid == 0);
|
LFS_ASSERT(bid == 0);
|
||||||
@@ -4256,6 +4254,19 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
rbyd.weight = 0;
|
rbyd.weight = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t *scratch1_buf = scratch_buf;
|
||||||
|
uint8_t *scratch2_buf = scratch_buf + LFSR_BRANCH_DSIZE;
|
||||||
|
lfs_ssize_t scratch1_dsize = lfsr_branch_todisk(lfs, &rbyd_,
|
||||||
|
scratch1_buf);
|
||||||
|
if (scratch1_dsize < 0) {
|
||||||
|
return scratch1_dsize;
|
||||||
|
}
|
||||||
|
lfs_ssize_t scratch2_dsize = lfsr_branch_todisk(lfs, &sibling,
|
||||||
|
scratch2_buf);
|
||||||
|
if (scratch2_dsize < 0) {
|
||||||
|
return scratch2_dsize;
|
||||||
|
}
|
||||||
|
|
||||||
// prepare commit to parent, tail recursing upwards
|
// prepare commit to parent, tail recursing upwards
|
||||||
bid -= rid - (rbyd.weight-1);
|
bid -= rid - (rbyd.weight-1);
|
||||||
LFS_ASSERT(rbyd_.weight > 0);
|
LFS_ASSERT(rbyd_.weight > 0);
|
||||||
@@ -4281,35 +4292,22 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
merge:;
|
merge:;
|
||||||
// try to add our sibling's tags to our rbyd
|
// allocate a new rbyd
|
||||||
lfsr_rbyd_t rbyd__ = rbyd_;
|
err = lfsr_rbyd_alloc(lfs, &rbyd_);
|
||||||
lfs_ssize_t rid_ = 0;
|
if (err) {
|
||||||
lfsr_tag_t tag_ = 0;
|
|
||||||
while (true) {
|
|
||||||
lfs_size_t weight_;
|
|
||||||
lfsr_data_t data_;
|
|
||||||
err = lfsr_rbyd_lookupnext(lfs, &sibling, rid_, lfsr_tag_next(tag_),
|
|
||||||
&rid_, &tag_, &weight_, &data_);
|
|
||||||
if (err && err != LFS_ERR_NOENT) {
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
if (err == LFS_ERR_NOENT) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// append the attr
|
// merge the siblings together
|
||||||
err = lfsr_rbyd_append(lfs, &rbyd__,
|
err = lfsr_rbyd_merge(lfs, &rbyd_, -1, -1, &rbyd, &sibling);
|
||||||
sibling_delta+rid_-lfs_smax32(weight_-1, 0), tag_, +weight_,
|
|
||||||
data_);
|
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// bring in name that previously split the siblings
|
// bring in name that previously split the siblings
|
||||||
err = lfsr_rbyd_lookupnext(lfs, &parent,
|
err = lfsr_rbyd_lookupnext(lfs, &parent,
|
||||||
(sibling_delta == 0 ? rid : sibling_rid), LFSR_TAG_NAME,
|
rid+1, LFSR_TAG_NAME,
|
||||||
NULL, &split_tag, NULL, &split_data);
|
NULL, &split_tag, NULL, &split_data);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
@@ -4318,16 +4316,15 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
if (lfsr_tag_suptype(split_tag) == LFSR_TAG_NAME) {
|
if (lfsr_tag_suptype(split_tag) == LFSR_TAG_NAME) {
|
||||||
// lookup the rid (weight really) of the previously-split entry
|
// lookup the rid (weight really) of the previously-split entry
|
||||||
lfs_ssize_t split_rid;
|
lfs_ssize_t split_rid;
|
||||||
err = lfsr_rbyd_lookupnext(lfs, &rbyd__,
|
err = lfsr_rbyd_lookupnext(lfs, &rbyd_,
|
||||||
(sibling_delta == 0 ? sibling.weight : rbyd_.weight),
|
rbyd.weight, LFSR_TAG_NAME,
|
||||||
LFSR_TAG_NAME,
|
|
||||||
&split_rid, NULL, NULL, NULL);
|
&split_rid, NULL, NULL, NULL);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = lfsr_rbyd_append(lfs, &rbyd__,
|
err = lfsr_rbyd_append(lfs, &rbyd_,
|
||||||
split_rid, LFSR_TAG_BNAME, 0, split_data);
|
split_rid, LFSR_TAG_BNAME, 0, split_data);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||||
@@ -4335,8 +4332,17 @@ 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_appendall(lfs, &rbyd_, bid, -1, -1,
|
||||||
|
attrs, attr_count);
|
||||||
|
if (err) {
|
||||||
|
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
// finalize the commit
|
// finalize the commit
|
||||||
err = lfsr_rbyd_appendcksum(lfs, &rbyd__);
|
err = lfsr_rbyd_appendcksum(lfs, &rbyd_);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||||
return err;
|
return err;
|
||||||
@@ -4347,33 +4353,26 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
|||||||
LFS_ASSERT(rid != -1);
|
LFS_ASSERT(rid != -1);
|
||||||
if (rbyd.weight+sibling.weight == lfsr_btree_weight(btree)) {
|
if (rbyd.weight+sibling.weight == lfsr_btree_weight(btree)) {
|
||||||
// collapse the root, decreasing the height of the tree
|
// collapse the root, decreasing the height of the tree
|
||||||
btree->u.r.rbyd = rbyd__;
|
btree->u.r.rbyd = rbyd_;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// prepare commit to parent, tail recursing upwards
|
scratch_dsize = lfsr_branch_todisk(lfs, &rbyd_,
|
||||||
bid -= rid - (rbyd.weight-1);
|
|
||||||
|
|
||||||
// make rid the lower child so the following math is easier
|
|
||||||
if (rid > sibling_rid) {
|
|
||||||
lfs_sswap32(&rid, &sibling_rid);
|
|
||||||
lfs_swap32(&rbyd.weight, &sibling.weight);
|
|
||||||
}
|
|
||||||
|
|
||||||
scratch_dsize = lfsr_branch_todisk(lfs, &rbyd__,
|
|
||||||
scratch_buf);
|
scratch_buf);
|
||||||
if (scratch_dsize < 0) {
|
if (scratch_dsize < 0) {
|
||||||
return scratch_dsize;
|
return scratch_dsize;
|
||||||
}
|
}
|
||||||
|
|
||||||
LFS_ASSERT(rbyd__.weight > 0);
|
// prepare commit to parent, tail recursing upwards
|
||||||
|
bid -= rid - (rbyd.weight-1);
|
||||||
|
LFS_ASSERT(rbyd_.weight > 0);
|
||||||
scratch_attrs[0] = LFSR_ATTR(
|
scratch_attrs[0] = LFSR_ATTR(
|
||||||
bid+sibling_rid, RM, -sibling.weight, NULL);
|
bid+rid+sibling.weight, RM, -sibling.weight, NULL);
|
||||||
scratch_attrs[1] = LFSR_ATTR(
|
scratch_attrs[1] = LFSR_ATTR(
|
||||||
bid+rid, BRANCH, 0,
|
bid+rid, BRANCH, 0,
|
||||||
BUF(scratch_buf, scratch_dsize));
|
BUF(scratch_buf, scratch_dsize));
|
||||||
scratch_attrs[2] = LFSR_ATTR(
|
scratch_attrs[2] = LFSR_ATTR(
|
||||||
bid+rid, GROW(RM), +rbyd__.weight-rbyd.weight, NULL);
|
bid+rid, GROW(RM), +rbyd_.weight-rbyd.weight, NULL);
|
||||||
attrs = scratch_attrs;
|
attrs = scratch_attrs;
|
||||||
attr_count = 3;
|
attr_count = 3;
|
||||||
|
|
||||||
@@ -5005,7 +5004,8 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_,
|
|||||||
|
|
||||||
// copy over attrs
|
// copy over attrs
|
||||||
err = lfsr_rbyd_compact(lfs, &mdir_->u.r.rbyd,
|
err = lfsr_rbyd_compact(lfs, &mdir_->u.r.rbyd,
|
||||||
start_rid, end_rid, &mdir->u.r.rbyd);
|
start_rid, end_rid,
|
||||||
|
&mdir->u.r.rbyd);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||||
return err;
|
return err;
|
||||||
|
|||||||
Reference in New Issue
Block a user