Typedefed lfsr_shrub_t -> lfsr_rbyd_t, replacing lfsr_bshrub_t union

The lfsr_shrub_t/lfsr_btree_t union was _technically_ not undefined
behavior, because the relevant fields were all a part of the "common
initial sequence", but collapsing these to the same type certainly does
simplify things.

The only weirdness is that we now store shrub.estimate in shrub.eoff.

We could add a union here, but the extra noise is just not worth the
slighty better name. The shrub.estimate is a sort of "simulated
shrub.eoff" anyways.

---

This makes it so all of these types alias to the same core lfsr_rbyd_t
type, which I suppose actually reflects the on-disk format quite well:

  lfsr_shrub_t  => lfsr_rbyd_t
  lfsr_bshrub_t
  lfsr_btree_t

Code cost more-or-less unaffected:

           code          stack          ctx
  before: 36432           2608          640
  after:  36436 (+0.0%)   2608 (+0.0%)  640 (+0.0%)
This commit is contained in:
Christopher Haster
2025-02-03 02:17:52 -06:00
parent 192c58318f
commit 7c17be4dbe
3 changed files with 91 additions and 107 deletions
+78 -82
View File
@@ -4627,7 +4627,7 @@ static int lfsr_rbyd_appendshrub(lfs_t *lfs, lfsr_rbyd_t *rbyd,
// compact our shrub
int err = lfsr_rbyd_appendcompactrbyd(lfs, rbyd,
(const lfsr_rbyd_t*)shrub, -1, -1);
shrub, -1, -1);
if (err) {
return err;
}
@@ -5954,24 +5954,22 @@ static void lfsr_shrub_init(lfsr_shrub_t *shrub, lfs_block_t block) {
shrub->blocks[0] = block;
shrub->trunk = LFSR_RBYD_ISSHRUB | 0;
// force estimate recalculation
shrub->estimate = -1;
shrub->eoff = -1;
}
// helper functions
static inline bool lfsr_shrub_isshrub(const lfsr_shrub_t *shrub) {
return lfsr_rbyd_isshrub((const lfsr_rbyd_t*)shrub);
return lfsr_rbyd_isshrub(shrub);
}
static inline lfs_size_t lfsr_shrub_trunk(const lfsr_shrub_t *shrub) {
return lfsr_rbyd_trunk((const lfsr_rbyd_t*)shrub);
return lfsr_rbyd_trunk(shrub);
}
static inline int lfsr_shrub_cmp(
const lfsr_shrub_t *a,
const lfsr_shrub_t *b) {
return lfsr_rbyd_cmp(
(const lfsr_rbyd_t*)a,
(const lfsr_rbyd_t*)b);
return lfsr_rbyd_cmp(a, b);
}
// shrub on-disk encoding
@@ -6021,7 +6019,7 @@ static int lfsr_data_readshrub(lfs_t *lfs, lfsr_data_t *data,
// copy the mdir block
shrub->blocks[0] = mdir->rbyd.blocks[0];
// force estimate recalculation if we write to this shrub
shrub->estimate = -1;
shrub->eoff = -1;
int err = lfsr_data_readleb128(lfs, data, &shrub->weight);
if (err) {
@@ -6051,16 +6049,16 @@ static lfs_ssize_t lfsr_shrub_estimate(lfs_t *lfs,
for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) {
if (lfsr_o_isbshrub(o->flags)
&& lfsr_shrub_cmp(
&((lfsr_obshrub_t*)o)->bshrub.u.bshrub,
&((lfsr_obshrub_t*)o)->bshrub,
shrub) == 0) {
last = &((lfsr_obshrub_t*)o)->bshrub.u.bshrub;
last = &((lfsr_obshrub_t*)o)->bshrub;
}
}
if (last && shrub != last) {
return 0;
}
return lfsr_rbyd_estimate(lfs, (const lfsr_rbyd_t*)shrub, -1, -1,
return lfsr_rbyd_estimate(lfs, shrub, -1, -1,
NULL);
}
@@ -6083,11 +6081,11 @@ static int lfsr_shrub_compact(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) {
if (lfsr_o_isbshrub(o->flags)
&& lfsr_shrub_cmp(
&((lfsr_obshrub_t*)o)->bshrub.u.bshrub,
&((lfsr_obshrub_t*)o)->bshrub,
shrub) == 0) {
((lfsr_obshrub_t*)o)->bshrub_.u.bshrub.blocks[0] = rbyd_->blocks[0];
((lfsr_obshrub_t*)o)->bshrub_.u.bshrub.trunk = rbyd_->trunk;
((lfsr_obshrub_t*)o)->bshrub_.u.bshrub.weight = rbyd_->weight;
((lfsr_obshrub_t*)o)->bshrub_.blocks[0] = rbyd_->blocks[0];
((lfsr_obshrub_t*)o)->bshrub_.trunk = rbyd_->trunk;
((lfsr_obshrub_t*)o)->bshrub_.weight = rbyd_->weight;
}
}
@@ -6141,20 +6139,20 @@ static int lfsr_shrub_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
// create a non-existant bshrub
static void lfsr_bshrub_init(lfsr_bshrub_t *bshrub) {
bshrub->u.bshrub.weight = 0;
bshrub->u.bshrub.trunk = 0;
bshrub->weight = 0;
bshrub->trunk = 0;
}
static inline bool lfsr_bshrub_isbnull(const lfsr_bshrub_t *bshrub) {
return !bshrub->u.bshrub.trunk;
return !bshrub->trunk;
}
static inline bool lfsr_bshrub_isbshrub(const lfsr_bshrub_t *bshrub) {
return lfsr_shrub_isshrub(&bshrub->u.bshrub);
return lfsr_rbyd_isshrub(bshrub);
}
static inline bool lfsr_bshrub_isbtree(const lfsr_bshrub_t *bshrub) {
return !lfsr_shrub_isshrub(&bshrub->u.bshrub);
return !lfsr_rbyd_isshrub(bshrub);
}
// needed in lfsr_bshrub_estimate
@@ -6201,7 +6199,7 @@ static lfs_ssize_t lfsr_bshrub_estimate(lfs_t *lfs,
&& lfsr_bshrub_isbshrub(
&((lfsr_obshrub_t*)o)->bshrub)) {
lfs_ssize_t dsize = lfsr_shrub_estimate(lfs,
&((lfsr_obshrub_t*)o)->bshrub.u.bshrub);
&((lfsr_obshrub_t*)o)->bshrub);
if (dsize < 0) {
return dsize;
}
@@ -6219,7 +6217,7 @@ static int lfsr_bshrub_lookupnext(lfs_t *lfs,
lfsr_bptr_t *bptr_) {
(void)mdir;
// out of bounds?
if (bid >= bshrub->u.weight) {
if (bid >= bshrub->weight) {
return LFS_ERR_NOENT;
}
@@ -6230,7 +6228,7 @@ static int lfsr_bshrub_lookupnext(lfs_t *lfs,
lfsr_tag_t tag;
lfsr_bid_t weight;
lfsr_data_t data;
int err = lfsr_btree_lookupnext_(lfs, &bshrub->u.btree, bid,
int err = lfsr_btree_lookupnext_(lfs, bshrub, bid,
&bid__, &rbyd, &rid, &tag, &weight, &data);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
@@ -6270,7 +6268,7 @@ static int lfsr_bshrub_traverse(lfs_t *lfs,
(void)mdir;
lfsr_tag_t tag;
lfsr_data_t data;
int err = lfsr_btree_traverse(lfs, &bshrub->u.btree, bt,
int err = lfsr_btree_traverse(lfs, bshrub, bt,
bid_, &tag, &data);
if (err) {
return err;
@@ -6310,17 +6308,17 @@ static int lfsr_bshrub_commit_(lfs_t *lfs,
if (lfsr_o_isbshrub(o->flags)
&& &((lfsr_obshrub_t*)o)->bshrub != bshrub
&& lfsr_btree_cmp(
&((lfsr_obshrub_t*)o)->bshrub.u.btree,
&bshrub->u.btree) == 0) {
&((lfsr_obshrub_t*)o)->bshrub,
bshrub) == 0) {
// mark as unerased
((lfsr_obshrub_t*)o)->bshrub.u.btree.eoff = -1;
((lfsr_obshrub_t*)o)->bshrub.eoff = -1;
}
}
}
// try to commit to the btree
lfsr_bscratch_t bscratch;
int err = lfsr_btree_commit__(lfs, &bshrub->u.btree, &bscratch,
int err = lfsr_btree_commit__(lfs, bshrub, &bscratch,
&bid, rbyd, rid, &rats, &rat_count);
if (err && err != LFS_ERR_RANGE) {
return err;
@@ -6354,9 +6352,7 @@ static int lfsr_bshrub_commit_(lfs_t *lfs,
// does our estimate exceed our shrub_size? need to recalculate an
// accurate estimate
lfs_ssize_t estimate = (alloc)
? (lfs_size_t)-1
: bshrub->u.bshrub.estimate;
lfs_ssize_t estimate = (alloc) ? (lfs_size_t)-1 : bshrub->eoff;
// this double condition avoids overflow issues
if ((lfs_size_t)estimate > lfs->cfg->shrub_size
|| estimate + commit_estimate > lfs->cfg->shrub_size) {
@@ -6386,11 +6382,11 @@ static int lfsr_bshrub_commit_(lfs_t *lfs,
int err = lfsr_mdir_commit(lfs, mdir, LFSR_RATS(
LFSR_RAT_SHRUBCOMMIT(
LFSR_TAG_SHRUBCOMMIT, 0,
&bshrub->u.bshrub, bid, rats, rat_count)));
bshrub, bid, rats, rat_count)));
if (err) {
return err;
}
LFS_ASSERT(bshrub->u.bshrub.blocks[0] == mdir->rbyd.blocks[0]);
LFS_ASSERT(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) {
@@ -6398,13 +6394,13 @@ static int lfsr_bshrub_commit_(lfs_t *lfs,
&& o->mdir.mid == mdir->mid
&& lfsr_bshrub_isbshrub(
&((lfsr_obshrub_t*)o)->bshrub)) {
((lfsr_obshrub_t*)o)->bshrub.u.bshrub.estimate = estimate;
((lfsr_obshrub_t*)o)->bshrub.eoff = estimate;
}
}
LFS_ASSERT(bshrub->u.bshrub.estimate == (lfs_size_t)estimate);
LFS_ASSERT(bshrub->eoff == (lfs_size_t)estimate);
}
LFS_ASSERT(lfsr_shrub_trunk(&bshrub->u.bshrub));
LFS_ASSERT(lfsr_shrub_trunk(bshrub));
#ifdef LFS_DEBUGBTREECOMMITS
if (lfsr_bshrub_isbshrub(mdir, bshrub)) {
LFS_DEBUG("Committed bshrub "
@@ -6432,7 +6428,7 @@ relocate:;
// 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, -1, -1);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
// bad prog? try another block
@@ -6453,9 +6449,9 @@ relocate:;
return err;
}
bshrub->u.btree = rbyd_;
*bshrub = rbyd_;
LFS_ASSERT(lfsr_rbyd_trunk(&bshrub->u.btree));
LFS_ASSERT(lfsr_rbyd_trunk(bshrub));
#ifdef LFS_DEBUGBTREECOMMITS
LFS_DEBUG("Committed btree 0x%"PRIx32".%"PRIx32" w%"PRId32", "
"cksum %"PRIx32,
@@ -7434,7 +7430,7 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir,
const lfsr_shrubcommit_t *shrubcommit = rats[i].cat;
// find the staging shrub
lfsr_shrub_t *shrub = shrubcommit->shrub;
lfsr_shrub_t *shrub_ = &((lfsr_bshrub_t*)shrub + 1)->u.bshrub;
lfsr_shrub_t *shrub_ = shrub + 1;
// reset shrub if it doesn't live in our block, this happens
// when converting from a btree
@@ -7459,7 +7455,7 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir,
} else if (lfsr_tag_key(rats[i].tag) == LFSR_TAG_SHRUBTRUNK) {
// find the staging shrub
lfsr_shrub_t *shrub = (lfsr_shrub_t*)rats[i].cat;
lfsr_shrub_t *shrub_ = &((lfsr_bshrub_t*)shrub + 1)->u.bshrub;
lfsr_shrub_t *shrub_ = shrub + 1;
uint8_t shrub_buf[LFSR_SHRUB_DSIZE];
int err = lfsr_rbyd_appendrat(lfs, &mdir->rbyd,
@@ -7544,11 +7540,11 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir,
&((lfsr_obshrub_t*)o)->bshrub)
// only compact once, first compact should
// stage the new block
&& ((lfsr_obshrub_t*)o)->bshrub_.u.bshrub.blocks[0]
&& ((lfsr_obshrub_t*)o)->bshrub_.blocks[0]
!= mdir->rbyd.blocks[0]) {
int err = lfsr_shrub_compact(lfs, &mdir->rbyd,
&((lfsr_obshrub_t*)o)->bshrub_.u.bshrub,
&((lfsr_obshrub_t*)o)->bshrub.u.bshrub);
&((lfsr_obshrub_t*)o)->bshrub_,
&((lfsr_obshrub_t*)o)->bshrub);
if (err) {
return err;
}
@@ -7770,7 +7766,7 @@ static lfs_ssize_t lfsr_mdir_estimate__(lfs_t *lfs, const lfsr_mdir_t *mdir,
&& lfsr_bshrub_isbshrub(
&((lfsr_obshrub_t*)o)->bshrub)) {
lfs_ssize_t dsize__ = lfsr_shrub_estimate(lfs,
&((lfsr_obshrub_t*)o)->bshrub.u.bshrub);
&((lfsr_obshrub_t*)o)->bshrub);
if (dsize__ < 0) {
return dsize__;
}
@@ -7896,11 +7892,11 @@ static int lfsr_mdir_compact__(lfs_t *lfs, lfsr_mdir_t *mdir_,
&((lfsr_obshrub_t*)o)->bshrub)
// only compact once, first compact should
// stage the new block
&& ((lfsr_obshrub_t*)o)->bshrub_.u.bshrub.blocks[0]
&& ((lfsr_obshrub_t*)o)->bshrub_.blocks[0]
!= mdir_->rbyd.blocks[0]) {
int err = lfsr_shrub_compact(lfs, &mdir_->rbyd,
&((lfsr_obshrub_t*)o)->bshrub_.u.bshrub,
&((lfsr_obshrub_t*)o)->bshrub.u.bshrub);
&((lfsr_obshrub_t*)o)->bshrub_,
&((lfsr_obshrub_t*)o)->bshrub);
if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE);
return err;
@@ -8141,7 +8137,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir,
// a bshrub outside of its mdir means something has gone
// horribly wrong
LFS_ASSERT(!lfsr_bshrub_isbshrub(&((lfsr_obshrub_t*)o)->bshrub)
|| ((lfsr_obshrub_t*)o)->bshrub.u.bshrub.blocks[0]
|| ((lfsr_obshrub_t*)o)->bshrub.blocks[0]
== o->mdir.rbyd.blocks[0]);
((lfsr_obshrub_t*)o)->bshrub_ = ((lfsr_obshrub_t*)o)->bshrub;
}
@@ -9127,7 +9123,7 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t,
} else if (tag == LFSR_TAG_MTREE) {
// fetch the root of the mtree
err = lfsr_data_fetchbtree(lfs, &data,
&t->o.bshrub.u.btree);
&t->o.bshrub);
if (err) {
return err;
}
@@ -9193,7 +9189,7 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t,
// found a bshrub (inlined btree)?
if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BSHRUB) {
err = lfsr_data_readshrub(lfs, &data, &t->o.o.mdir,
&t->o.bshrub.u.bshrub);
&t->o.bshrub);
if (err) {
return err;
}
@@ -9201,7 +9197,7 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t,
// found a btree?
} else if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BTREE) {
err = lfsr_data_fetchbtree(lfs, &data,
&t->o.bshrub.u.btree);
&t->o.bshrub);
if (err) {
return err;
}
@@ -10797,7 +10793,7 @@ static inline lfs_size_t lfsr_file_inlinesize(lfs_t *lfs,
static inline lfs_off_t lfsr_file_size_(const lfsr_file_t *file) {
return lfs_max(
file->buffer.pos + file->buffer.size,
file->o.bshrub.u.weight);
file->o.bshrub.weight);
}
// file operations
@@ -10830,7 +10826,7 @@ static int lfsr_file_fetch(lfs_t *lfs, lfsr_file_t *file, bool trunc) {
// may be a bshrub (inlined btree)
if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BSHRUB) {
err = lfsr_data_readshrub(lfs, &data, &file->o.o.mdir,
&file->o.bshrub_.u.bshrub);
&file->o.bshrub_);
if (err) {
return err;
}
@@ -10838,7 +10834,7 @@ static int lfsr_file_fetch(lfs_t *lfs, lfsr_file_t *file, bool trunc) {
// or a btree
} else if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BTREE) {
err = lfsr_data_fetchbtree(lfs, &data,
&file->o.bshrub_.u.btree);
&file->o.bshrub_);
if (err) {
return err;
}
@@ -11240,7 +11236,7 @@ lfs_ssize_t lfsr_file_read(lfs_t *lfs, lfsr_file_t *file,
}
// any data in our btree?
if (pos_ < file->o.bshrub.u.weight) {
if (pos_ < file->o.bshrub.weight) {
// bypass buffer?
if ((lfs_size_t)d >= lfsr_file_buffersize(lfs, file)) {
lfs_ssize_t d_ = lfsr_file_readnext(lfs, file,
@@ -11327,14 +11323,14 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
// carving the entire tree? revert to no bshrub/btree
if (pos == 0
&& weight >= file->o.bshrub.u.weight
&& weight >= file->o.bshrub.weight
&& rat.weight == -(lfs_soff_t)weight) {
lfsr_bshrub_init(&file->o.bshrub);
return 0;
}
// try to merge commits where possible
lfsr_bid_t bid = file->o.bshrub.u.weight;
lfsr_bid_t bid = file->o.bshrub.weight;
lfsr_rat_t rats[5];
lfs_size_t rat_count = 0;
union {
@@ -11347,26 +11343,26 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
} right;
// need a hole?
if (pos > file->o.bshrub.u.weight) {
if (pos > file->o.bshrub.weight) {
// can we coalesce?
if (file->o.bshrub.u.weight > 0) {
bid = lfs_min(bid, file->o.bshrub.u.weight-1);
if (file->o.bshrub.weight > 0) {
bid = lfs_min(bid, file->o.bshrub.weight-1);
rats[rat_count++] = LFSR_RAT(
LFSR_TAG_GROW, +(pos - file->o.bshrub.u.weight),
LFSR_TAG_GROW, +(pos - file->o.bshrub.weight),
LFSR_DATA_NULL());
// new hole
} else {
bid = lfs_min(bid, file->o.bshrub.u.weight);
bid = lfs_min(bid, file->o.bshrub.weight);
rats[rat_count++] = LFSR_RAT(
LFSR_TAG_DATA, +(pos - file->o.bshrub.u.weight),
LFSR_TAG_DATA, +(pos - file->o.bshrub.weight),
LFSR_DATA_NULL());
}
}
// try to carve any existing data
lfsr_rat_t right_rat_ = {.tag=0};
while (pos < file->o.bshrub.u.weight) {
while (pos < file->o.bshrub.weight) {
lfsr_tag_t tag_;
lfsr_bid_t weight_;
lfsr_bptr_t bptr_;
@@ -11556,21 +11552,21 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
if (weight + rat.weight > 0) {
// can we coalesce a hole?
if (lfsr_rat_size(rat) == 0 && pos > 0) {
bid = lfs_min(bid, file->o.bshrub.u.weight-1);
bid = lfs_min(bid, file->o.bshrub.weight-1);
rats[rat_count++] = LFSR_RAT(
LFSR_TAG_GROW, +(weight + rat.weight),
LFSR_DATA_NULL());
// need a new hole?
} else if (lfsr_rat_size(rat) == 0) {
bid = lfs_min(bid, file->o.bshrub.u.weight);
bid = lfs_min(bid, file->o.bshrub.weight);
rats[rat_count++] = LFSR_RAT(
LFSR_TAG_DATA, +(weight + rat.weight),
LFSR_DATA_NULL());
// append new fragment/bptr?
} else {
bid = lfs_min(bid, file->o.bshrub.u.weight);
bid = lfs_min(bid, file->o.bshrub.weight);
rats[rat_count++] = LFSR_RAT_(
rat.tag, +(weight + rat.weight),
rat.cat, rat.count);
@@ -11620,8 +11616,8 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
if (pos > 0
&& lfs->cfg->crystal_thresh > 0
&& (lfs_soff_t)(pos - (lfs->cfg->crystal_thresh-1))
< (lfs_soff_t)file->o.bshrub.u.weight
&& file->o.bshrub.u.weight > 0
< (lfs_soff_t)file->o.bshrub.weight
&& file->o.bshrub.weight > 0
// don't bother to lookup left after the first block
&& !aligned) {
lfsr_bid_t bid;
@@ -11674,14 +11670,14 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
// if we haven't already exceeded our crystallization threshold,
// find right crystal neighbor
if (crystal_end - crystal_start < lfs->cfg->crystal_thresh
&& file->o.bshrub.u.weight > 0) {
&& file->o.bshrub.weight > 0) {
lfsr_bid_t bid;
lfsr_tag_t tag;
lfsr_bid_t weight;
int err = lfsr_file_lookupnext(lfs, file,
lfs_min(
crystal_start + (lfs->cfg->crystal_thresh-1),
file->o.bshrub.u.weight-1),
file->o.bshrub.weight-1),
&bid, &tag, &weight, &bptr);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
@@ -11717,7 +11713,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
// crystal for this
block_start = crystal_start;
if (crystal_start > 0
&& file->o.bshrub.u.weight > 0
&& file->o.bshrub.weight > 0
// don't bother to lookup left after the first block
&& !aligned) {
lfsr_bid_t bid;
@@ -11726,7 +11722,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
int err = lfsr_file_lookupnext(lfs, file,
lfs_min(
crystal_start-1,
file->o.bshrub.u.weight-1),
file->o.bshrub.weight-1),
&bid, &tag, &weight, &bptr);
if (err) {
LFS_ASSERT(err != LFS_ERR_NOENT);
@@ -11793,14 +11789,14 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
+ (lfs->cfg->block_size - bptr.data.u.disk.off),
lfs_max(
pos + size,
file->o.bshrub.u.weight))) {
file->o.bshrub.weight))) {
// keep track of the next highest priority data offset
lfs_ssize_t d = lfs_min(
block_start
+ (lfs->cfg->block_size - bptr.data.u.disk.off),
lfs_max(
pos + size,
file->o.bshrub.u.weight)) - pos_;
file->o.bshrub.weight)) - pos_;
// any data in our buffer?
if (pos_ < pos + size && size > 0) {
@@ -11835,7 +11831,7 @@ static int lfsr_file_flush_(lfs_t *lfs, lfsr_file_t *file,
}
// any data on disk?
if (pos_ < file->o.bshrub.u.weight) {
if (pos_ < file->o.bshrub.weight) {
lfsr_bid_t bid_;
lfsr_tag_t tag_;
lfsr_bid_t weight_;
@@ -12005,7 +12001,7 @@ fragment:;
// do we have a left sibling?
if (fragment_start > 0
&& file->o.bshrub.u.weight >= fragment_start
&& file->o.bshrub.weight >= fragment_start
// don't bother to lookup left after first fragment
&& !aligned) {
lfsr_bid_t bid;
@@ -12053,7 +12049,7 @@ fragment:;
// do we have a right sibling?
//
// note this may the same as our left sibling
if (fragment_end < file->o.bshrub.u.weight
if (fragment_end < file->o.bshrub.weight
// don't bother to lookup right if fragment is already full
&& fragment_end - fragment_start < lfs->cfg->fragment_size) {
lfsr_bid_t bid;
@@ -12360,7 +12356,7 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
}
// zero size files should have no bshrub/btree
LFS_ASSERT(file->o.bshrub.u.weight > 0
LFS_ASSERT(file->o.bshrub.weight > 0
|| lfsr_bshrub_isbnull(&file->o.bshrub));
// no bshrub/btree?
@@ -12372,12 +12368,12 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) {
} else if (lfsr_bshrub_isbshrub(&file->o.bshrub)) {
rats[rat_count++] = LFSR_RAT_SHRUBTRUNK(
LFSR_TAG_SUB | LFSR_TAG_SHRUBTRUNK, 0,
&file->o.bshrub.u.bshrub);
&file->o.bshrub);
// btree?
} else if (lfsr_bshrub_isbtree(&file->o.bshrub)) {
rats[rat_count++] = LFSR_RAT(
LFSR_TAG_SUB | LFSR_TAG_BTREE, 0,
LFSR_DATA_BTREE(&file->o.bshrub.u.btree, buf));
LFSR_DATA_BTREE(&file->o.bshrub, buf));
} else {
LFS_UNREACHABLE();
}
+6 -18
View File
@@ -605,14 +605,7 @@ typedef struct lfsr_rbyd {
typedef lfsr_rbyd_t lfsr_btree_t;
// a shrub is a secondary trunk in an mdir
typedef struct {
// this mostly lines up with lfsr_rbyd_t
lfsr_rid_t weight;
lfs_block_t blocks[2];
lfs_size_t trunk;
// except for shrub estimate, which takes the place of eoff, etc
lfs_size_t estimate;
} lfsr_shrub_t;
typedef lfsr_rbyd_t lfsr_shrub_t;
typedef struct lfsr_mdir {
lfsr_smid_t mid;
@@ -694,16 +687,11 @@ typedef struct lfsr_bptr {
} lfsr_bptr_t;
// the lfsr_bshrub_t struct represents the on-disk component of a file
typedef struct lfsr_bshrub {
// weight=0 => no bshrub/btree
// sign(weight)=1 => bshrub
// sign(weight)=0 => btree
union {
lfs_size_t weight;
lfsr_shrub_t bshrub;
lfsr_btree_t btree;
} u;
} lfsr_bshrub_t;
//
// weight=0 => no bshrub/btree
// sign(weight)=1 => bshrub
// sign(weight)=0 => btree
typedef lfsr_rbyd_t lfsr_bshrub_t;
typedef struct lfsr_obshrub {
// bshrubs need to be tracked for commits to work
+7 -7
View File
@@ -1097,19 +1097,19 @@ code = '''
lfsr_mdir_commit(&lfs, &file.o.o.mdir, LFSR_RATS(
LFSR_RAT_SHRUBCOMMIT(
LFSR_TAG_SHRUBCOMMIT, 0,
&file.o.bshrub.u.bshrub, 0, ((lfsr_rat_t[]){
&file.o.bshrub, 0, ((lfsr_rat_t[]){
LFSR_RAT(LFSR_TAG_DATA, +1, LFSR_DATA_BUF("?", 1))}),
1))) => 0;
lfsr_mdir_commit(&lfs, &file.o.o.mdir, LFSR_RATS(
LFSR_RAT_SHRUBCOMMIT(
LFSR_TAG_SHRUBCOMMIT, 0,
&file.o.bshrub.u.bshrub, 0, ((lfsr_rat_t[]){
&file.o.bshrub, 0, ((lfsr_rat_t[]){
LFSR_RAT(LFSR_TAG_RM, -1, LFSR_DATA_NULL())}),
1))) => 0;
lfsr_mdir_commit(&lfs, &file.o.o.mdir, LFSR_RATS(
LFSR_RAT_SHRUBTRUNK(
LFSR_TAG_SUB | LFSR_TAG_SHRUBTRUNK, 0,
&file.o.bshrub.u.bshrub))) => 0;
&file.o.bshrub))) => 0;
lfsr_file_close(&lfs, &file) => 0;
@@ -1224,16 +1224,16 @@ code = '''
// create an empty btree
lfs_alloc_ckpoint(&lfs);
lfsr_rbyd_alloc(&lfs, &file.o.bshrub.u.btree) => 0;
lfsr_rbyd_commit(&lfs, &file.o.bshrub.u.btree, 0, LFSR_RATS(
lfsr_rbyd_alloc(&lfs, &file.o.bshrub) => 0;
lfsr_rbyd_commit(&lfs, &file.o.bshrub, 0, LFSR_RATS(
LFSR_RAT(LFSR_TAG_DATA, +1, LFSR_DATA_BUF("?", 1)))) => 0;
lfsr_rbyd_commit(&lfs, &file.o.bshrub.u.btree, 0, LFSR_RATS(
lfsr_rbyd_commit(&lfs, &file.o.bshrub, 0, LFSR_RATS(
LFSR_RAT(LFSR_TAG_RM, -1, LFSR_DATA_NULL()))) => 0;
uint8_t buf[LFSR_BTREE_DSIZE];
lfsr_mdir_commit(&lfs, &file.o.o.mdir, LFSR_RATS(
LFSR_RAT(
LFSR_TAG_SUB | LFSR_TAG_BTREE, 0,
LFSR_DATA_BTREE(&file.o.bshrub.u.btree, buf)))) => 0;
LFSR_DATA_BTREE(&file.o.bshrub, buf)))) => 0;
lfsr_file_close(&lfs, &file) => 0;