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:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user