Changed bshrub functions to operate on mdir+bshrub directly

This gets a bit messy, since lfsr_bshrub_commit really requires the
bshrub to be enrolled in the opened mdir list to stage correctly.

To make this work, our internal SHRUBCOMMIT and SHRUBTRUNK attrs now
take a pointer to the active shrub, and assume it is followed by a
staging shrub in memory. This is a big hack/assumption that leaks
through lfsr_bshrub_commit, but it at gets the job done in our current
system.

Note some functions were renamed instead, these didn't really make sense
as pure-bshrub functions:

- lfsr_bshrub_readnext -> lfsr_file_readnext
- lfsr_bshrub_read -> lfsr_file_read_

---

The main reason for this is to comply with C99's strict aliasing rules,
which can be a real PIA sometimes.

We need to track a bshrub in lfsr_mtraversal_t, but we really don't want
to pay the RAM cost for an entire lfsr_file_t. The best option I've
found is to pass around multiple pointers to the relevant internal
structs (mdir+bshrub), but this adds a stack+code cost.

So far, strict aliasing is a net downside:

                         code          stack
  before:               34478           2624
  -fno-strict-aliasing: 34502 (+0.1%)   2616 (-0.3%)
  after:                34566 (+0.3%)   2632 (+0.3%)

But it's baked into the standard and we can't always rely on
-fno-strict-aliasing being available.
This commit is contained in:
Christopher Haster
2024-06-23 13:05:06 -05:00
parent d155750f14
commit 55d9f5c76a
2 changed files with 120 additions and 99 deletions
+117 -92
View File
@@ -6199,18 +6199,21 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir,
// in our rbyd
} else if (attrs[i].tag == LFSR_TAG_SHRUBCOMMIT) {
const lfsr_shrubcommit_t *shrubcommit = attrs[i].cat;
// find the staging shrub
lfsr_shrub_t *shrub = shrubcommit->shrub;
lfsr_shrub_t *shrub_ = &((lfsr_bshrub_t*)shrub + 1)->u.bshrub;
// reset shrub if it doesn't live in our block, this happens
// when converting from a btree
if (shrubcommit->shrub->blocks[0] != rbyd_.blocks[0]) {
shrubcommit->shrub->blocks[0] = rbyd_.blocks[0];
shrubcommit->shrub->trunk = LFSR_RBYD_ISSHRUB | 0;
shrubcommit->shrub->weight = 0;
if (shrub_->blocks[0] != rbyd_.blocks[0]) {
shrub_->blocks[0] = rbyd_.blocks[0];
shrub_->trunk = LFSR_RBYD_ISSHRUB | 0;
shrub_->weight = 0;
}
// commit to shrub
int err = lfsr_shrub_commit(lfs, &rbyd_,
shrubcommit->shrub, shrubcommit->rid,
shrub_, shrubcommit->rid,
shrubcommit->attrs, shrubcommit->attr_count);
if (err) {
return err;
@@ -6222,7 +6225,9 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir,
// TODO should we preserve mode for all of these?
// TODO should we do the same for sprouts?
} else if (lfsr_tag_key(attrs[i].tag) == LFSR_TAG_SHRUBTRUNK) {
const lfsr_shrub_t *shrub = attrs[i].cat;
// find the staging shrub
lfsr_shrub_t *shrub = (lfsr_shrub_t*)attrs[i].cat;
lfsr_shrub_t *shrub_ = &((lfsr_bshrub_t*)shrub + 1)->u.bshrub;
uint8_t shrub_buf[LFSR_SHRUB_DSIZE];
int err = lfsr_rbyd_appendattr(lfs, &rbyd_,
@@ -6231,7 +6236,7 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir,
lfsr_tag_mode(attrs[i].tag) | LFSR_TAG_BSHRUB,
attrs[i].weight,
// note we use the staged trunk here
LFSR_DATA_SHRUB_(shrub, shrub_buf)));
LFSR_DATA_SHRUB_(shrub_, shrub_buf)));
if (err) {
return err;
}
@@ -7884,7 +7889,8 @@ typedef lfsr_btinfo_t lfsr_mtinfo_t;
// needed in lfsr_mtree_traverse_
static inline bool lfsr_f_isunsync(uint32_t flags);
static int lfsr_bshrub_traverse(lfs_t *lfs, const lfsr_file_t *file,
static int lfsr_bshrub_traverse(lfs_t *lfs,
const lfsr_mdir_t *mdir, const lfsr_bshrub_t *bshrub,
lfsr_btraversal_t *bt,
lfsr_bid_t *bid_, lfsr_btinfo_t *btinfo);
@@ -8120,7 +8126,8 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
case LFSR_MTRAVERSAL_BTREE:;
case LFSR_MTRAVERSAL_OBTREE:;
// traverse through our file
err = lfsr_bshrub_traverse(lfs, (const lfsr_file_t*)mt, &mt->u.bt,
err = lfsr_bshrub_traverse(lfs, &mt->o.mdir, &mt->bshrub,
&mt->u.bt,
NULL, mtinfo);
if (err) {
if (err == LFS_ERR_NOENT) {
@@ -10432,7 +10439,7 @@ static inline lfs_off_t lfsr_file_size_(const lfsr_file_t *file) {
// file operations
// needed in lfsr_file_opencfg
static lfs_ssize_t lfsr_bshrub_read(lfs_t *lfs, const lfsr_file_t *file,
static lfs_ssize_t lfsr_file_read_(lfs_t *lfs, const lfsr_file_t *file,
lfs_off_t pos, uint8_t *buffer, lfs_size_t size);
int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
@@ -10591,7 +10598,7 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file,
// if our file is small, try to keep the whole thing in our buffer
if (lfsr_bshrub_size(&file->bshrub) <= lfsr_file_inlinesize(lfs, file)) {
lfs_ssize_t d = lfsr_bshrub_read(lfs, file,
lfs_ssize_t d = lfsr_file_read_(lfs, file,
0, file->buffer.buffer, lfsr_bshrub_size(&file->bshrub));
if (d < 0) {
err = d;
@@ -10673,14 +10680,16 @@ int lfsr_file_close(lfs_t *lfs, lfsr_file_t *file) {
// find a tight upper bound on the _full_ bshrub size, this includes
// any on-disk bshrubs, and all pending bshrubs
static lfs_ssize_t lfsr_bshrub_estimate(lfs_t *lfs, const lfsr_file_t *file) {
static lfs_ssize_t lfsr_bshrub_estimate(lfs_t *lfs,
const lfsr_mdir_t *mdir, const lfsr_bshrub_t *bshrub) {
(void)bshrub;
lfs_size_t estimate = 0;
// include all unique sprouts/shrubs related to our file,
// including the on-disk sprout/shrub
lfsr_tag_t tag;
lfsr_data_t data;
int err = lfsr_mdir_lookupnext(lfs, &file->o.mdir, LFSR_TAG_DATA,
int err = lfsr_mdir_lookupnext(lfs, mdir, LFSR_TAG_DATA,
&tag, &data);
if (err < 0 && err != LFS_ERR_NOENT) {
return err;
@@ -10695,7 +10704,7 @@ static lfs_ssize_t lfsr_bshrub_estimate(lfs_t *lfs, const lfsr_file_t *file) {
} else if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BSHRUB) {
lfsr_shrub_t shrub;
err = lfsr_data_readshrub(lfs, &data, &file->o.mdir,
err = lfsr_data_readshrub(lfs, &data, mdir,
&shrub);
if (err < 0) {
return err;
@@ -10712,7 +10721,7 @@ static lfs_ssize_t lfsr_bshrub_estimate(lfs_t *lfs, const lfsr_file_t *file) {
for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) {
lfsr_file_t *file_ = (lfsr_file_t*)o;
if (file_->o.type == LFS_TYPE_REG
&& file_->o.mdir.mid == file->o.mdir.mid) {
&& file_->o.mdir.mid == mdir->mid) {
if (lfsr_bshrub_isbsprout(&file_->o.mdir, &file_->bshrub)) {
lfs_ssize_t dsize = lfsr_sprout_estimate(lfs,
&file_->bshrub.u.bsprout);
@@ -10735,57 +10744,59 @@ static lfs_ssize_t lfsr_bshrub_estimate(lfs_t *lfs, const lfsr_file_t *file) {
return estimate;
}
static int lfsr_bshrub_lookupnext(lfs_t *lfs, const lfsr_file_t *file,
static int lfsr_bshrub_lookupnext(lfs_t *lfs,
const lfsr_mdir_t *mdir, const lfsr_bshrub_t *bshrub,
lfs_off_t pos,
lfsr_bid_t *bid_, lfsr_tag_t *tag_, lfsr_bid_t *weight_,
lfsr_bptr_t *bptr_) {
if (pos >= lfsr_bshrub_size(&file->bshrub)) {
// out of bounds?
if (pos >= lfsr_bshrub_size(bshrub)) {
return LFS_ERR_NOENT;
}
// the above size check should make this impossible
LFS_ASSERT(!lfsr_bshrub_isbnull(&file->bshrub));
LFS_ASSERT(!lfsr_bshrub_isbnull(bshrub));
// inlined sprout?
if (lfsr_bshrub_isbsprout(&file->o.mdir, &file->bshrub)) {
if (lfsr_bshrub_isbsprout(mdir, bshrub)) {
if (bid_) {
*bid_ = lfsr_data_size(file->bshrub.u.bsprout)-1;
*bid_ = lfsr_data_size(bshrub->u.bsprout)-1;
}
if (tag_) {
*tag_ = LFSR_TAG_DATA;
}
if (weight_) {
*weight_ = lfsr_data_size(file->bshrub.u.bsprout);
*weight_ = lfsr_data_size(bshrub->u.bsprout);
}
if (bptr_) {
bptr_->data = file->bshrub.u.bsprout;
bptr_->data = bshrub->u.bsprout;
}
return 0;
// block pointer?
} else if (lfsr_bshrub_isbptr(&file->o.mdir, &file->bshrub)) {
} else if (lfsr_bshrub_isbptr(mdir, bshrub)) {
if (bid_) {
*bid_ = lfsr_data_size(file->bshrub.u.bptr.data)-1;
*bid_ = lfsr_data_size(bshrub->u.bptr.data)-1;
}
if (tag_) {
*tag_ = LFSR_TAG_BLOCK;
}
if (weight_) {
*weight_ = lfsr_data_size(file->bshrub.u.bptr.data);
*weight_ = lfsr_data_size(bshrub->u.bptr.data);
}
if (bptr_) {
*bptr_ = file->bshrub.u.bptr;
*bptr_ = bshrub->u.bptr;
}
return 0;
// bshrub/btree?
} else if (lfsr_bshrub_isbshruborbtree(&file->bshrub)) {
} else if (lfsr_bshrub_isbshruborbtree(bshrub)) {
lfsr_bid_t bid;
lfsr_rbyd_t rbyd;
lfsr_srid_t rid;
lfsr_tag_t tag;
lfsr_bid_t weight;
lfsr_data_t data;
int err = lfsr_btree_lookupnext_(lfs, &file->bshrub.u.btree, pos,
int err = lfsr_btree_lookupnext_(lfs, &bshrub->u.btree, pos,
&bid, &rbyd, &rid, &tag, &weight, &data);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
@@ -10822,31 +10833,32 @@ static int lfsr_bshrub_lookupnext(lfs_t *lfs, const lfsr_file_t *file,
}
}
static int lfsr_bshrub_traverse(lfs_t *lfs, const lfsr_file_t *file,
static int lfsr_bshrub_traverse(lfs_t *lfs,
const lfsr_mdir_t *mdir, const lfsr_bshrub_t *bshrub,
lfsr_btraversal_t *bt,
lfsr_bid_t *bid_, lfsr_btinfo_t *btinfo) {
// bnull/bsprout do nothing
if (lfsr_bshrub_isbnull(&file->bshrub)
|| lfsr_bshrub_isbsprout(&file->o.mdir, &file->bshrub)) {
if (lfsr_bshrub_isbnull(bshrub)
|| lfsr_bshrub_isbsprout(mdir, bshrub)) {
return LFS_ERR_NOENT;
}
// block pointer?
if (lfsr_bshrub_isbptr(&file->o.mdir, &file->bshrub)) {
if (lfsr_bshrub_isbptr(mdir, bshrub)) {
if (bt->bid > 0) {
return LFS_ERR_NOENT;
}
if (bid_) {
*bid_ = lfsr_data_size(file->bshrub.u.bptr.data)-1;
*bid_ = lfsr_data_size(bshrub->u.bptr.data)-1;
}
btinfo->tag = LFSR_TAG_BLOCK;
btinfo->u.bptr = file->bshrub.u.bptr;
btinfo->u.bptr = bshrub->u.bptr;
return 0;
// bshrub/btree?
} else if (lfsr_bshrub_isbshruborbtree(&file->bshrub)) {
int err = lfsr_btree_traverse_(lfs, &file->bshrub.u.btree, bt,
} else if (lfsr_bshrub_isbshruborbtree(bshrub)) {
int err = lfsr_btree_traverse_(lfs, &bshrub->u.btree, bt,
bid_, btinfo);
if (err) {
return err;
@@ -10869,7 +10881,7 @@ static int lfsr_bshrub_traverse(lfs_t *lfs, const lfsr_file_t *file,
}
}
static lfs_ssize_t lfsr_bshrub_readnext(lfs_t *lfs, const lfsr_file_t *file,
static lfs_ssize_t lfsr_file_readnext(lfs_t *lfs, const lfsr_file_t *file,
lfs_off_t pos, uint8_t *buffer, lfs_size_t size) {
lfs_off_t pos_ = pos;
// read one btree entry
@@ -10877,7 +10889,7 @@ static lfs_ssize_t lfsr_bshrub_readnext(lfs_t *lfs, const lfsr_file_t *file,
lfsr_tag_t tag;
lfsr_bid_t weight;
lfsr_bptr_t bptr;
int err = lfsr_bshrub_lookupnext(lfs, file, pos_,
int err = lfsr_bshrub_lookupnext(lfs, &file->o.mdir, &file->bshrub, pos_,
&bid, &tag, &weight, &bptr);
if (err) {
return err;
@@ -10916,11 +10928,11 @@ static lfs_ssize_t lfsr_bshrub_readnext(lfs_t *lfs, const lfsr_file_t *file,
return pos_ - pos;
}
static lfs_ssize_t lfsr_bshrub_read(lfs_t *lfs, const lfsr_file_t *file,
static lfs_ssize_t lfsr_file_read_(lfs_t *lfs, const lfsr_file_t *file,
lfs_off_t pos, uint8_t *buffer, lfs_size_t size) {
lfs_off_t pos_ = pos;
while (size > 0 && pos_ < lfsr_bshrub_size(&file->bshrub)) {
lfs_ssize_t d = lfsr_bshrub_readnext(lfs, file,
lfs_ssize_t d = lfsr_file_readnext(lfs, file,
pos_, buffer, size);
if (d < 0) {
LFS_ASSERT(d != LFS_ERR_NOENT);
@@ -10936,22 +10948,23 @@ static lfs_ssize_t lfsr_bshrub_read(lfs_t *lfs, const lfsr_file_t *file,
}
// this is atomic
static int lfsr_bshrub_commit(lfs_t *lfs, lfsr_file_t *file,
static int lfsr_bshrub_commit(lfs_t *lfs,
lfsr_mdir_t *mdir, lfsr_bshrub_t *bshrub,
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(&file->bshrub));
LFS_ASSERT(lfsr_bshrub_isbshruborbtree(bshrub));
// before we touch anything, we need to mark all other btree references
// as unerased
if (lfsr_bshrub_isbtree(&file->o.mdir, &file->bshrub)) {
if (lfsr_bshrub_isbtree(mdir, bshrub)) {
for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) {
lfsr_file_t *file_ = (lfsr_file_t*)o;
if (file_->o.type == LFS_TYPE_REG
&& file_ != file
&& &file_->bshrub != bshrub
&& lfsr_bshrub_isbshruborbtree(&file_->bshrub)
&& lfsr_btree_cmp(
&file_->bshrub.u.btree,
&file->bshrub.u.btree) == 0) {
&bshrub->u.btree) == 0) {
// mark as unerased
file_->bshrub.u.btree.eoff = -1;
}
@@ -10960,7 +10973,7 @@ static int lfsr_bshrub_commit(lfs_t *lfs, lfsr_file_t *file,
// try to commit to the btree
lfsr_btree_scratch_t scratch;
int err = lfsr_btree_commit_(lfs, &file->bshrub.u.btree, &scratch,
int err = lfsr_btree_commit_(lfs, &bshrub->u.btree, &scratch,
&bid, &attrs, &attr_count);
if (err && err != LFS_ERR_RANGE) {
return err;
@@ -10996,11 +11009,11 @@ static int lfsr_bshrub_commit(lfs_t *lfs, lfsr_file_t *file,
// accurate estimate
lfs_ssize_t estimate = (alloc)
? (lfs_size_t)-1
: file->bshrub.u.bshrub.estimate;
: bshrub->u.bshrub.estimate;
// this double condition avoids overflow issues
if ((lfs_size_t)estimate > lfs->cfg->shrub_size
|| estimate + commit_estimate > lfs->cfg->shrub_size) {
estimate = lfsr_bshrub_estimate(lfs, file);
estimate = lfsr_bshrub_estimate(lfs, mdir, bshrub);
if (estimate < 0) {
return estimate;
}
@@ -11023,32 +11036,30 @@ static int lfsr_bshrub_commit(lfs_t *lfs, lfsr_file_t *file,
estimate += commit_estimate;
// commit to shrub
int err = lfsr_mdir_commit(lfs, &file->o.mdir, LFSR_ATTRS(
int err = lfsr_mdir_commit(lfs, mdir, LFSR_ATTRS(
LFSR_ATTR_SHRUBCOMMIT(
LFSR_TAG_SHRUBCOMMIT, 0,
&file->bshrub_.u.bshrub, bid,
attrs, attr_count)));
&bshrub->u.bshrub, bid, attrs, attr_count)));
if (err) {
return err;
}
LFS_ASSERT(file->bshrub.u.bshrub.blocks[0]
== file->o.mdir.rbyd.blocks[0]);
LFS_ASSERT(bshrub->u.bshrub.blocks[0] == mdir->rbyd.blocks[0]);
// update _all_ shrubs with the new estimate
for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) {
lfsr_file_t *file_ = (lfsr_file_t*)o;
if (file_->o.type == LFS_TYPE_REG
&& file_->o.mdir.mid == file->o.mdir.mid
&& file_->o.mdir.mid == mdir->mid
&& lfsr_bshrub_isbshrub(&file_->o.mdir, &file_->bshrub)) {
file_->bshrub.u.bshrub.estimate = estimate;
}
}
LFS_ASSERT(file->bshrub.u.bshrub.estimate == (lfs_size_t)estimate);
LFS_ASSERT(bshrub->u.bshrub.estimate == (lfs_size_t)estimate);
return 0;
}
LFS_ASSERT(lfsr_shrub_trunk(&file->bshrub.u.bshrub));
LFS_ASSERT(lfsr_shrub_trunk(&bshrub->u.bshrub));
return 0;
relocate:;
@@ -11062,7 +11073,7 @@ relocate:;
// note this may be a new root
if (!alloc) {
err = lfsr_rbyd_compact(lfs, &rbyd,
&file->bshrub.u.btree, -1, -1);
&bshrub->u.btree, -1, -1);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
// bad prog? try another block
@@ -11084,7 +11095,7 @@ relocate:;
return err;
}
file->bshrub.u.btree = rbyd;
bshrub->u.btree = rbyd;
return 0;
}
@@ -11138,7 +11149,9 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
if (attr_count > 0) {
LFS_ASSERT(attr_count <= sizeof(attrs)/sizeof(lfsr_attr_t));
int err = lfsr_bshrub_commit(lfs, file, 0, attrs, attr_count);
int err = lfsr_bshrub_commit(lfs,
&file->o.mdir, &file->bshrub, 0,
attrs, attr_count);
if (err) {
return err;
}
@@ -11171,7 +11184,8 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
lfsr_tag_t tag_;
lfsr_bid_t weight_;
lfsr_bptr_t bptr_;
int err = lfsr_bshrub_lookupnext(lfs, file, pos,
int err = lfsr_bshrub_lookupnext(lfs,
&file->o.mdir, &file->bshrub, pos,
&bid, &tag_, &weight_, &bptr_);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
@@ -11195,15 +11209,17 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
lfs->cfg->fragment_size,
-1);
err = lfsr_bshrub_commit(lfs, file, bid, LFSR_ATTRS(
LFSR_ATTR_CAT(
LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_DATA,
-(weight_ - lfs->cfg->fragment_size),
lfsr_data_truncate(left_slice_,
lfs->cfg->fragment_size)),
LFSR_ATTR(
LFSR_TAG_BLOCK, +(weight_ - lfs->cfg->fragment_size),
LFSR_DATA_BPTR_(&bptr_, left.buf))));
err = lfsr_bshrub_commit(lfs,
&file->o.mdir, &file->bshrub, bid, LFSR_ATTRS(
LFSR_ATTR_CAT(
LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_DATA,
-(weight_ - lfs->cfg->fragment_size),
lfsr_data_truncate(left_slice_,
lfs->cfg->fragment_size)),
LFSR_ATTR(
LFSR_TAG_BLOCK,
+(weight_ - lfs->cfg->fragment_size),
LFSR_DATA_BPTR_(&bptr_, left.buf))));
if (err) {
return err;
}
@@ -11223,16 +11239,17 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
-1,
lfsr_data_size(bptr_.data) - lfs->cfg->fragment_size);
err = lfsr_bshrub_commit(lfs, file, bid, LFSR_ATTRS(
LFSR_ATTR(
LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_BLOCK,
-(weight_ - lfsr_data_size(bptr_.data)),
LFSR_DATA_BPTR_(&bptr_, right.buf)),
LFSR_ATTR_CAT(
LFSR_TAG_DATA,
+(weight_ - lfsr_data_size(bptr_.data)),
lfsr_data_fruncate(right_slice_,
lfs->cfg->fragment_size))));
err = lfsr_bshrub_commit(lfs,
&file->o.mdir, &file->bshrub, bid, LFSR_ATTRS(
LFSR_ATTR(
LFSR_TAG_GROW | LFSR_TAG_SUB | LFSR_TAG_BLOCK,
-(weight_ - lfsr_data_size(bptr_.data)),
LFSR_DATA_BPTR_(&bptr_, right.buf)),
LFSR_ATTR_CAT(
LFSR_TAG_DATA,
+(weight_ - lfsr_data_size(bptr_.data)),
lfsr_data_fruncate(right_slice_,
lfs->cfg->fragment_size))));
if (err) {
return err;
}
@@ -11287,7 +11304,8 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
LFS_ASSERT(lfsr_data_size(right_slice_) == 0);
LFS_ASSERT(attr_count <= sizeof(attrs)/sizeof(lfsr_attr_t));
err = lfsr_bshrub_commit(lfs, file, bid,
err = lfsr_bshrub_commit(lfs,
&file->o.mdir, &file->bshrub, bid,
attrs, attr_count);
if (err) {
return err;
@@ -11369,7 +11387,8 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
if (attr_count > 0) {
LFS_ASSERT(attr_count <= sizeof(attrs)/sizeof(lfsr_attr_t));
int err = lfsr_bshrub_commit(lfs, file, bid,
int err = lfsr_bshrub_commit(lfs,
&file->o.mdir, &file->bshrub, bid,
attrs, attr_count);
if (err) {
return err;
@@ -11410,7 +11429,8 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
lfsr_bid_t bid;
lfsr_tag_t tag;
lfsr_bid_t weight;
int err = lfsr_bshrub_lookupnext(lfs, file,
int err = lfsr_bshrub_lookupnext(lfs,
&file->o.mdir, &file->bshrub,
lfs_smax(pos - (lfs->cfg->crystal_thresh-1), 0),
&bid, &tag, &weight, &bptr);
if (err) {
@@ -11459,7 +11479,8 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
lfsr_bid_t bid;
lfsr_tag_t tag;
lfsr_bid_t weight;
int err = lfsr_bshrub_lookupnext(lfs, file,
int err = lfsr_bshrub_lookupnext(lfs,
&file->o.mdir, &file->bshrub,
lfs_min(
crystal_start + (lfs->cfg->crystal_thresh-1),
lfsr_bshrub_size(&file->bshrub)-1),
@@ -11504,7 +11525,8 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
lfsr_bid_t bid;
lfsr_tag_t tag;
lfsr_bid_t weight;
int err = lfsr_bshrub_lookupnext(lfs, file,
int err = lfsr_bshrub_lookupnext(lfs,
&file->o.mdir, &file->bshrub,
lfs_min(
crystal_start-1,
lfsr_bshrub_size(&file->bshrub)-1),
@@ -11613,7 +11635,8 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
lfsr_tag_t tag_;
lfsr_bid_t weight_;
lfsr_bptr_t bptr_;
int err = lfsr_bshrub_lookupnext(lfs, file, pos_,
int err = lfsr_bshrub_lookupnext(lfs,
&file->o.mdir, &file->bshrub, pos_,
&bid_, &tag_, &weight_, &bptr_);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
@@ -11758,7 +11781,8 @@ fragment:;
lfsr_tag_t tag;
lfsr_bid_t weight;
lfsr_bptr_t bptr;
int err = lfsr_bshrub_lookupnext(lfs, file,
int err = lfsr_bshrub_lookupnext(lfs,
&file->o.mdir, &file->bshrub,
fragment_start-1,
&bid, &tag, &weight, &bptr);
if (err) {
@@ -11795,7 +11819,8 @@ fragment:;
lfsr_tag_t tag;
lfsr_bid_t weight;
lfsr_bptr_t bptr;
int err = lfsr_bshrub_lookupnext(lfs, file,
int err = lfsr_bshrub_lookupnext(lfs,
&file->o.mdir, &file->bshrub,
fragment_end,
&bid, &tag, &weight, &bptr);
if (err) {
@@ -11885,7 +11910,7 @@ lfs_ssize_t lfsr_file_read(lfs_t *lfs, lfsr_file_t *file,
if (pos_ < lfsr_bshrub_size(&file->bshrub)) {
// bypass buffer?
if ((lfs_size_t)d >= lfsr_file_buffersize(lfs, file)) {
lfs_ssize_t d_ = lfsr_bshrub_readnext(lfs, file,
lfs_ssize_t d_ = lfsr_file_readnext(lfs, file,
pos_, buffer_, d);
if (d_ < 0) {
LFS_ASSERT(d_ != LFS_ERR_NOENT);
@@ -11913,7 +11938,7 @@ lfs_ssize_t lfsr_file_read(lfs_t *lfs, lfsr_file_t *file,
}
// try to fill our buffer with some data
lfs_ssize_t d_ = lfsr_bshrub_readnext(lfs, file,
lfs_ssize_t d_ = lfsr_file_readnext(lfs, file,
pos_, file->buffer.buffer, d);
if (d_ < 0) {
LFS_ASSERT(d != LFS_ERR_NOENT);
@@ -12237,7 +12262,7 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
} else if (lfsr_bshrub_isbshrub(&file->o.mdir, &file->bshrub)) {
attrs[attr_count++] = LFSR_ATTR_SHRUBTRUNK(
LFSR_TAG_SUB | LFSR_TAG_SHRUBTRUNK, 0,
&file->bshrub_.u.bshrub);
&file->bshrub.u.bshrub);
// btree?
} else if (lfsr_bshrub_isbtree(&file->o.mdir, &file->bshrub)) {
attrs[attr_count++] = LFSR_ATTR(
@@ -12401,7 +12426,7 @@ int lfsr_file_truncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
file->buffer.pos = 0;
file->buffer.size = 0;
lfs_ssize_t d = lfsr_bshrub_read(lfs, file,
lfs_ssize_t d = lfsr_file_read_(lfs, file,
0, file->buffer.buffer, size_);
if (d < 0) {
err = d;
@@ -12508,7 +12533,7 @@ int lfsr_file_fruncate(lfs_t *lfs, lfsr_file_t *file, lfs_off_t size_) {
file->buffer.pos = 0;
file->buffer.size = 0;
lfs_ssize_t d = lfsr_bshrub_read(lfs, file,
lfs_ssize_t d = lfsr_file_read_(lfs, file,
lfsr_bshrub_size(&file->bshrub) - lfs_min(
size_,
lfsr_bshrub_size(&file->bshrub)),
+3 -7
View File
@@ -605,14 +605,10 @@ typedef struct lfsr_btraversal {
typedef struct lfsr_mtraversal {
// core state machine in o.state
lfsr_omdir_t o;
// we really don't want to pay the RAM cost for a full file,
// so only store the relevant bits, is this a hack? yes
const struct lfs_file_config *cfg;
lfsr_bshrub_t bshrub;
// opened file state, we use an indirect pointer here so we
// always point to data associated with the current mid
// opened file state
lfsr_omdir_t *ot;
// bshrub/btree state
lfsr_bshrub_t bshrub;
union {
// cycle detection state, only valid when traversing the mroot chain
struct {