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,
|
||||
const lfsr_rbyd_t *source) {
|
||||
const lfsr_rbyd_t *const *rbyds, lfs_size_t rbyd_count) {
|
||||
#ifndef LFSR_NO_REBALANCE
|
||||
// must fetch before mutating!
|
||||
LFS_ASSERT(lfsr_rbyd_isfetched(rbyd));
|
||||
@@ -3031,48 +3031,54 @@ static int lfsr_rbyd_compact(lfs_t *lfs, lfsr_rbyd_t *rbyd,
|
||||
|
||||
// first copy over raw tags, note this doesn't create a tree
|
||||
lfs_off_t layer_off = rbyd->eoff;
|
||||
lfs_ssize_t rid = start_rid;
|
||||
lfsr_tag_t tag = 0;
|
||||
while (true) {
|
||||
lfs_size_t weight;
|
||||
lfsr_data_t data;
|
||||
int err = lfsr_rbyd_lookupnext(lfs, source, rid, lfsr_tag_next(tag),
|
||||
&rid, &tag, &weight, &data);
|
||||
if (err && err != LFS_ERR_NOENT) {
|
||||
return err;
|
||||
}
|
||||
if (err == LFS_ERR_NOENT || (end_rid >= 0 && rid >= end_rid)) {
|
||||
break;
|
||||
lfs_ssize_t bid = 0;
|
||||
for (lfs_size_t i = 0; i < rbyd_count; i++) {
|
||||
lfs_ssize_t rid = start_rid;
|
||||
lfsr_tag_t tag = 0;
|
||||
while (true) {
|
||||
lfs_size_t weight;
|
||||
lfsr_data_t data;
|
||||
int err = lfsr_rbyd_lookupnext(lfs, rbyds[i],
|
||||
rid, lfsr_tag_next(tag),
|
||||
&rid, &tag, &weight, &data);
|
||||
if (err && err != LFS_ERR_NOENT) {
|
||||
return err;
|
||||
}
|
||||
if (err == LFS_ERR_NOENT || (end_rid >= 0 && bid+rid >= end_rid)) {
|
||||
break;
|
||||
}
|
||||
|
||||
// TODO is this really the best way to do this?
|
||||
// this is a bit of a hack, but ignore any gstate tags here,
|
||||
// these need to be handled specially by upper-layers
|
||||
if (lfsr_tag_suptype(tag) == LFSR_TAG_GSTATE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// write the tag
|
||||
lfs_ssize_t d = lfsr_bd_progtag(lfs, rbyd->block, rbyd->eoff,
|
||||
tag, weight, lfsr_data_size(&data),
|
||||
&rbyd->cksum);
|
||||
if (d < 0) {
|
||||
err = d;
|
||||
goto failed;
|
||||
}
|
||||
rbyd->eoff += d;
|
||||
|
||||
// and the data
|
||||
err = lfsr_bd_progdata(lfs, rbyd->block, rbyd->eoff, data,
|
||||
&rbyd->cksum);
|
||||
if (err) {
|
||||
goto failed;
|
||||
}
|
||||
rbyd->eoff += lfsr_data_size(&data);
|
||||
|
||||
// keep track of the layer weight/trunks
|
||||
layer_trunks += 1;
|
||||
layer_weight += weight;
|
||||
}
|
||||
|
||||
// TODO is this really the best way to do this?
|
||||
// this is a bit of a hack, but ignore any gstate tags here,
|
||||
// these need to be handled specially by upper-layers
|
||||
if (lfsr_tag_suptype(tag) == LFSR_TAG_GSTATE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// write the tag
|
||||
lfs_ssize_t d = lfsr_bd_progtag(lfs, rbyd->block, rbyd->eoff,
|
||||
tag, weight, lfsr_data_size(&data),
|
||||
&rbyd->cksum);
|
||||
if (d < 0) {
|
||||
err = d;
|
||||
goto failed;
|
||||
}
|
||||
rbyd->eoff += d;
|
||||
|
||||
// and the data
|
||||
err = lfsr_bd_progdata(lfs, rbyd->block, rbyd->eoff, data,
|
||||
&rbyd->cksum);
|
||||
if (err) {
|
||||
goto failed;
|
||||
}
|
||||
rbyd->eoff += lfsr_data_size(&data);
|
||||
|
||||
// keep track of the layer weight/trunks
|
||||
layer_trunks += 1;
|
||||
layer_weight += weight;
|
||||
bid += rbyds[i]->weight;
|
||||
}
|
||||
|
||||
// connect every other trunk together, building layers of a perfectly
|
||||
@@ -3201,6 +3207,20 @@ failed:;
|
||||
#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,
|
||||
// exist in the rbyd namespace
|
||||
@@ -3965,10 +3985,7 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
||||
goto commit;
|
||||
|
||||
compact:;
|
||||
// can't commit, try to compact
|
||||
|
||||
// check if we're within our compaction threshold, otherwise we
|
||||
// need to split
|
||||
// estimate our compacted size
|
||||
lfs_size_t split_rid;
|
||||
lfs_ssize_t estimate = lfsr_rbyd_estimateall(lfs, &rbyd, -1, -1,
|
||||
&split_rid);
|
||||
@@ -3976,11 +3993,92 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
||||
return estimate;
|
||||
}
|
||||
|
||||
// are we too big? need to split?
|
||||
if ((lfs_size_t)estimate > lfs->cfg->block_size/2) {
|
||||
// need to split
|
||||
goto split;
|
||||
}
|
||||
|
||||
// before we compact, can we merge with our siblings?
|
||||
lfsr_rbyd_t sibling;
|
||||
for (uint8_t i = 0; i < 2; i++) {
|
||||
lfs_ssize_t sibling_rid;
|
||||
// try the right sibling
|
||||
if (i == 0) {
|
||||
sibling_rid = rid+1;
|
||||
|
||||
// try the left sibling
|
||||
} else {
|
||||
sibling_rid = rid-rbyd.weight;
|
||||
}
|
||||
|
||||
// no parent? no sibling?
|
||||
if (rid == -1
|
||||
|| sibling_rid < 0
|
||||
|| sibling_rid >= (lfs_ssize_t)parent.weight) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// try looking up the sibling
|
||||
// TODO do we really need to fetch sibling_weight if we get
|
||||
// it in our btree struct?
|
||||
lfsr_tag_t sibling_tag;
|
||||
lfs_size_t sibling_weight;
|
||||
lfsr_data_t sibling_data;
|
||||
err = lfsr_rbyd_lookupnext(lfs, &parent,
|
||||
sibling_rid, LFSR_TAG_NAME,
|
||||
&sibling_rid, &sibling_tag, &sibling_weight,
|
||||
&sibling_data);
|
||||
if (err) {
|
||||
// no sibling? can't merge
|
||||
if (err == LFS_ERR_NOENT) {
|
||||
continue;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
if (sibling_tag == LFSR_TAG_NAME) {
|
||||
err = lfsr_rbyd_lookup(lfs, &parent,
|
||||
sibling_rid, LFSR_TAG_WIDE(STRUCT),
|
||||
&sibling_tag, &sibling_data);
|
||||
if (err) {
|
||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
LFS_ASSERT(sibling_tag == LFSR_TAG_BRANCH);
|
||||
err = lfsr_data_readbranch(lfs, &sibling_data, sibling_weight,
|
||||
&sibling);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// estimate if our sibling will fit
|
||||
lfs_ssize_t sibling_estimate = lfsr_rbyd_estimateall(lfs,
|
||||
&sibling, -1, -1,
|
||||
NULL);
|
||||
if (sibling_estimate < 0) {
|
||||
return estimate;
|
||||
}
|
||||
|
||||
// fits? try to merge
|
||||
if ((lfs_size_t)(estimate + sibling_estimate)
|
||||
< lfs->cfg->block_size/2) {
|
||||
if (i == 1) {
|
||||
// if we're merging our left sibling, swap our rbyds
|
||||
// so our sibling is on the right
|
||||
bid -= sibling.weight;
|
||||
rid -= rbyd.weight;
|
||||
|
||||
rbyd_ = sibling;
|
||||
sibling = rbyd;
|
||||
rbyd = rbyd_;
|
||||
}
|
||||
goto merge;
|
||||
}
|
||||
}
|
||||
|
||||
// allocate a new rbyd
|
||||
err = lfsr_rbyd_alloc(lfs, &rbyd_);
|
||||
if (err) {
|
||||
@@ -4003,95 +4101,6 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
||||
return err;
|
||||
}
|
||||
|
||||
// is our compacted size too small? can we merge with one of our
|
||||
// siblings?
|
||||
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++) {
|
||||
// try the right sibling
|
||||
if (i == 0) {
|
||||
// right-most child? can't merge
|
||||
if ((lfs_size_t)rid == parent.weight-1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sibling_rid = rid+1;
|
||||
sibling_delta = rbyd_.weight;
|
||||
|
||||
// try the left sibling
|
||||
} else {
|
||||
// left-most child? can't merge
|
||||
if ((lfs_size_t)rid-(rbyd.weight-1) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
sibling_rid = rid-rbyd.weight;
|
||||
sibling_delta = 0;
|
||||
}
|
||||
|
||||
// try looking up the sibling
|
||||
// TODO do we really need to fetch sibling_weight if we get
|
||||
// it in our btree struct?
|
||||
lfsr_tag_t sibling_tag;
|
||||
lfs_size_t sibling_weight;
|
||||
lfsr_data_t sibling_data;
|
||||
err = lfsr_rbyd_lookupnext(lfs, &parent,
|
||||
sibling_rid, LFSR_TAG_NAME,
|
||||
&sibling_rid, &sibling_tag, &sibling_weight,
|
||||
&sibling_data);
|
||||
if (err) {
|
||||
// no sibling? can't merge
|
||||
if (err == LFS_ERR_NOENT) {
|
||||
continue;
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
if (sibling_tag == LFSR_TAG_NAME) {
|
||||
err = lfsr_rbyd_lookup(lfs, &parent,
|
||||
sibling_rid, LFSR_TAG_WIDE(STRUCT),
|
||||
&sibling_tag, &sibling_data);
|
||||
if (err) {
|
||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
LFS_ASSERT(sibling_tag == LFSR_TAG_BRANCH);
|
||||
err = lfsr_data_readbranch(lfs, &sibling_data, sibling_weight,
|
||||
&sibling);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// estimate if our sibling will fit
|
||||
lfs_ssize_t estimate = lfsr_rbyd_estimateall(lfs,
|
||||
&sibling, -1, -1,
|
||||
NULL);
|
||||
if (estimate < 0) {
|
||||
return estimate;
|
||||
}
|
||||
|
||||
// doesn't fit? can't merge
|
||||
//
|
||||
// note we use our uncompacted estimate here, since we need to
|
||||
// make sure our commit that merges the sibling doesn't fail
|
||||
if (estimate * lfs_nlog2((rbyd_.eoff+estimate)/16)
|
||||
> lfs->cfg->block_size/4) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// found a sibling that can be merged
|
||||
goto merge;
|
||||
}
|
||||
}
|
||||
|
||||
// finalize commit
|
||||
err = lfsr_rbyd_appendcksum(lfs, &rbyd_);
|
||||
if (err) {
|
||||
@@ -4130,11 +4139,13 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
||||
scratch_attrs[0] = LFSR_ATTR(
|
||||
bid+rid, BRANCH, 0,
|
||||
BUF(scratch_buf, scratch_dsize));
|
||||
scratch_attrs[1] = LFSR_ATTR(
|
||||
bid+rid,
|
||||
TAG(rbyd_.weight > 0 ? LFSR_TAG_GROW(RM) : LFSR_TAG_RM),
|
||||
+rbyd_.weight-rbyd.weight,
|
||||
NULL);
|
||||
scratch_attrs[1] = (rbyd_.weight == 0
|
||||
? LFSR_ATTR(
|
||||
bid+rid, RM, -rbyd.weight,
|
||||
NULL)
|
||||
: LFSR_ATTR(
|
||||
bid+rid, GROW(RM), +rbyd_.weight-rbyd.weight,
|
||||
NULL));
|
||||
attrs = scratch_attrs;
|
||||
attr_count = 2;
|
||||
|
||||
@@ -4229,19 +4240,6 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
||||
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
|
||||
if (rid == -1) {
|
||||
LFS_ASSERT(bid == 0);
|
||||
@@ -4256,6 +4254,19 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
||||
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
|
||||
bid -= rid - (rbyd.weight-1);
|
||||
LFS_ASSERT(rbyd_.weight > 0);
|
||||
@@ -4281,35 +4292,22 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
||||
continue;
|
||||
|
||||
merge:;
|
||||
// try to add our sibling's tags to our rbyd
|
||||
lfsr_rbyd_t rbyd__ = rbyd_;
|
||||
lfs_ssize_t rid_ = 0;
|
||||
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;
|
||||
}
|
||||
if (err == LFS_ERR_NOENT) {
|
||||
break;
|
||||
}
|
||||
// allocate a new rbyd
|
||||
err = lfsr_rbyd_alloc(lfs, &rbyd_);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
// append the attr
|
||||
err = lfsr_rbyd_append(lfs, &rbyd__,
|
||||
sibling_delta+rid_-lfs_smax32(weight_-1, 0), tag_, +weight_,
|
||||
data_);
|
||||
if (err) {
|
||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||
return err;
|
||||
}
|
||||
// merge the siblings together
|
||||
err = lfsr_rbyd_merge(lfs, &rbyd_, -1, -1, &rbyd, &sibling);
|
||||
if (err) {
|
||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||
return err;
|
||||
}
|
||||
|
||||
// bring in name that previously split the siblings
|
||||
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);
|
||||
if (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) {
|
||||
// lookup the rid (weight really) of the previously-split entry
|
||||
lfs_ssize_t split_rid;
|
||||
err = lfsr_rbyd_lookupnext(lfs, &rbyd__,
|
||||
(sibling_delta == 0 ? sibling.weight : rbyd_.weight),
|
||||
LFSR_TAG_NAME,
|
||||
err = lfsr_rbyd_lookupnext(lfs, &rbyd_,
|
||||
rbyd.weight, LFSR_TAG_NAME,
|
||||
&split_rid, NULL, NULL, NULL);
|
||||
if (err) {
|
||||
LFS_ASSERT(err != LFS_ERR_NOENT);
|
||||
return err;
|
||||
}
|
||||
|
||||
err = lfsr_rbyd_append(lfs, &rbyd__,
|
||||
err = lfsr_rbyd_append(lfs, &rbyd_,
|
||||
split_rid, LFSR_TAG_BNAME, 0, split_data);
|
||||
if (err) {
|
||||
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
|
||||
err = lfsr_rbyd_appendcksum(lfs, &rbyd__);
|
||||
err = lfsr_rbyd_appendcksum(lfs, &rbyd_);
|
||||
if (err) {
|
||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||
return err;
|
||||
@@ -4347,33 +4353,26 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
|
||||
LFS_ASSERT(rid != -1);
|
||||
if (rbyd.weight+sibling.weight == lfsr_btree_weight(btree)) {
|
||||
// collapse the root, decreasing the height of the tree
|
||||
btree->u.r.rbyd = rbyd__;
|
||||
btree->u.r.rbyd = rbyd_;
|
||||
return 0;
|
||||
}
|
||||
|
||||
// prepare commit to parent, tail recursing upwards
|
||||
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_dsize = lfsr_branch_todisk(lfs, &rbyd_,
|
||||
scratch_buf);
|
||||
if (scratch_dsize < 0) {
|
||||
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(
|
||||
bid+sibling_rid, RM, -sibling.weight, NULL);
|
||||
bid+rid+sibling.weight, RM, -sibling.weight, NULL);
|
||||
scratch_attrs[1] = LFSR_ATTR(
|
||||
bid+rid, BRANCH, 0,
|
||||
BUF(scratch_buf, scratch_dsize));
|
||||
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;
|
||||
attr_count = 3;
|
||||
|
||||
@@ -5005,7 +5004,8 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_,
|
||||
|
||||
// copy over attrs
|
||||
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) {
|
||||
LFS_ASSERT(err != LFS_ERR_RANGE);
|
||||
return err;
|
||||
|
||||
Reference in New Issue
Block a user