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:
@@ -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)),
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user