Use sign bit of rbyd.trunk to indicate shrubness of rbyds

Shrubness should have always been a property of lfsr_rbyd_t.

You know you've made a good design decision when things just sort of
fall into place and the code somehow becomes cleaner.

The downside of this change is accessing rbyd trunks requires a mask,
which is annoying, but the upside is we don't need to signal shrubness
via extra booleans in internal functions anymore.

The funny thing is, the actual motivation for this change is was just to
free up a bit in our tag encoding. Simplifying some of the internal
functions was just a nice side effect.

            code          stack
  before:  33940           2928
  after:   33928 (-0.0%)   2912 (-0.5%)
This commit is contained in:
Christopher Haster
2024-01-21 00:06:36 -06:00
parent 4ce582bf9b
commit bea13dcf8e
6 changed files with 125 additions and 101 deletions
+116 -99
View File
@@ -722,14 +722,6 @@ static inline lfsr_tag_t lfsr_tag_subkey(lfsr_tag_t tag) {
return tag & 0x00ff; return tag & 0x00ff;
} }
static inline lfsr_tag_t lfsr_tag_shrubmode(lfsr_tag_t tag) {
return tag & 0xe000;
}
static inline lfsr_tag_t lfsr_tag_shrubkey(lfsr_tag_t tag) {
return tag & 0x1fff;
}
static inline bool lfsr_tag_isalt(lfsr_tag_t tag) { static inline bool lfsr_tag_isalt(lfsr_tag_t tag) {
return tag & LFSR_TAG_ALT; return tag & LFSR_TAG_ALT;
} }
@@ -1993,9 +1985,23 @@ static void lfs_alloc_ckpoint(lfs_t *lfs);
/// Red-black-yellow Dhara tree operations /// /// Red-black-yellow Dhara tree operations ///
#define LFSR_RBYD_SHRUB 0x80000000
// helper functions // helper functions
static inline bool lfsr_rbyd_isshrub(const lfsr_rbyd_t *rbyd) {
return rbyd->trunk & LFSR_RBYD_SHRUB;
}
static inline lfs_size_t lfsr_rbyd_trunk(const lfsr_rbyd_t *rbyd) {
return rbyd->trunk & ~LFSR_RBYD_SHRUB;
}
static inline bool lfsr_rbyd_hastrunk(const lfsr_rbyd_t *rbyd) {
return lfsr_rbyd_trunk(rbyd) != 0;
}
static inline bool lfsr_rbyd_isfetched(const lfsr_rbyd_t *rbyd) { static inline bool lfsr_rbyd_isfetched(const lfsr_rbyd_t *rbyd) {
return !(rbyd->eoff == 0 && rbyd->trunk > 0); return !(lfsr_rbyd_hastrunk(rbyd) && rbyd->eoff == 0);
} }
static inline int lfsr_rbyd_cmp( static inline int lfsr_rbyd_cmp(
@@ -2027,7 +2033,7 @@ static int lfsr_rbyd_alloc(lfs_t *lfs, lfsr_rbyd_t *rbyd) {
} }
static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd, static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd,
lfs_block_t block, lfs_size_t trunk) { lfs_block_t block, lfs_ssize_t trunk) {
// checksum the revision count to get the cksum started // checksum the revision count to get the cksum started
uint32_t cksum = 0; uint32_t cksum = 0;
int err = lfsr_bd_cksum(lfs, block, 0, lfs->cfg->block_size, int err = lfsr_bd_cksum(lfs, block, 0, lfs->cfg->block_size,
@@ -2038,7 +2044,8 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd,
rbyd->blocks[0] = block; rbyd->blocks[0] = block;
rbyd->eoff = 0; rbyd->eoff = 0;
rbyd->trunk = 0; rbyd->trunk = (trunk & LFSR_RBYD_SHRUB) | 0;
trunk &= ~LFSR_RBYD_SHRUB;
// temporary state until we validate a cksum // temporary state until we validate a cksum
lfs_size_t off = sizeof(uint32_t); lfs_size_t off = sizeof(uint32_t);
@@ -2052,7 +2059,8 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd,
lfsr_ecksum_t ecksum = {.size=-1}; lfsr_ecksum_t ecksum = {.size=-1};
// scan tags, checking valid bits, cksums, etc // scan tags, checking valid bits, cksums, etc
while (off < lfs->cfg->block_size && (!trunk || rbyd->eoff <= trunk)) { while (off < lfs->cfg->block_size
&& (!trunk || rbyd->eoff <= (lfs_size_t)trunk)) {
lfsr_tag_t tag; lfsr_tag_t tag;
lfsr_rid_t weight__; lfsr_rid_t weight__;
lfs_size_t size; lfs_size_t size;
@@ -2133,12 +2141,13 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd,
// save what we've found so far // save what we've found so far
rbyd->eoff = off_ + size; rbyd->eoff = off_ + size;
rbyd->cksum = cksum; rbyd->cksum = cksum;
rbyd->trunk = trunk_; rbyd->trunk = (LFSR_RBYD_SHRUB & rbyd->trunk) | trunk_;
rbyd->weight = weight; rbyd->weight = weight;
} }
// found a trunk of a tree? // found a trunk of a tree?
if (lfsr_tag_istrunk(tag) && (!trunk || trunk >= off || wastrunk)) { if (lfsr_tag_istrunk(tag)
&& (!trunk || (lfs_size_t)trunk >= off || wastrunk)) {
// start of trunk? // start of trunk?
if (!wastrunk) { if (!wastrunk) {
wastrunk = true; wastrunk = true;
@@ -2177,7 +2186,7 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd,
} }
// no valid commits? // no valid commits?
if (!rbyd->trunk) { if (!lfsr_rbyd_hastrunk(rbyd)) {
return LFS_ERR_CORRUPT; return LFS_ERR_CORRUPT;
} }
@@ -2202,7 +2211,7 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd,
// a more aggressive fetch when checksum is known // a more aggressive fetch when checksum is known
static int lfsr_rbyd_fetchvalidate(lfs_t *lfs, lfsr_rbyd_t *rbyd, static int lfsr_rbyd_fetchvalidate(lfs_t *lfs, lfsr_rbyd_t *rbyd,
lfs_block_t block, lfs_size_t trunk, lfsr_rid_t weight, lfs_block_t block, lfs_ssize_t trunk, lfsr_rid_t weight,
uint32_t cksum) { uint32_t cksum) {
int err = lfsr_rbyd_fetch(lfs, rbyd, block, trunk); int err = lfsr_rbyd_fetch(lfs, rbyd, block, trunk);
if (err) { if (err) {
@@ -2222,13 +2231,13 @@ static int lfsr_rbyd_fetchvalidate(lfs_t *lfs, lfsr_rbyd_t *rbyd,
if (rbyd->cksum != cksum) { if (rbyd->cksum != cksum) {
LFS_ERROR("Found rbyd cksum mismatch rbyd 0x%"PRIx32".%"PRIx32", " LFS_ERROR("Found rbyd cksum mismatch rbyd 0x%"PRIx32".%"PRIx32", "
"cksum 0x%08"PRIx32" (!= 0x%08"PRIx32")", "cksum 0x%08"PRIx32" (!= 0x%08"PRIx32")",
rbyd->blocks[0], rbyd->trunk, rbyd->cksum, cksum); rbyd->blocks[0], lfsr_rbyd_trunk(rbyd), rbyd->cksum, cksum);
return LFS_ERR_CORRUPT; return LFS_ERR_CORRUPT;
} }
// if trunk/weight mismatch _after_ cksums match, that's not a storage // if trunk/weight mismatch _after_ cksums match, that's not a storage
// error, that's a programming error // error, that's a programming error
LFS_ASSERT(rbyd->trunk == trunk); LFS_ASSERT(lfsr_rbyd_trunk(rbyd) == (lfs_size_t)trunk);
LFS_ASSERT((lfsr_rid_t)rbyd->weight == weight); LFS_ASSERT((lfsr_rid_t)rbyd->weight == weight);
return 0; return 0;
} }
@@ -2246,12 +2255,12 @@ static int lfsr_rbyd_lookupnext(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
tag = lfs_max16(tag, 0x1); tag = lfs_max16(tag, 0x1);
// out of bounds? no trunk yet? // out of bounds? no trunk yet?
if (rid >= rbyd->weight || !rbyd->trunk) { if (rid >= rbyd->weight || !lfsr_rbyd_hastrunk(rbyd)) {
return LFS_ERR_NOENT; return LFS_ERR_NOENT;
} }
// keep track of bounds as we descend down the tree // keep track of bounds as we descend down the tree
lfs_size_t branch = rbyd->trunk; lfs_size_t branch = lfsr_rbyd_trunk(rbyd);
lfsr_srid_t lower = 0; lfsr_srid_t lower = 0;
lfsr_srid_t upper = rbyd->weight; lfsr_srid_t upper = rbyd->weight;
@@ -2281,7 +2290,6 @@ static int lfsr_rbyd_lookupnext(lfs_t *lfs, const lfsr_rbyd_t *rbyd,
// found end of tree? // found end of tree?
} else { } else {
// update the tag rid // update the tag rid
LFS_ASSERT(lfsr_tag_shrubmode(alt) == 0x0000);
lfsr_srid_t rid__ = upper-1; lfsr_srid_t rid__ = upper-1;
lfsr_tag_t tag__ = lfsr_tag_key(alt); lfsr_tag_t tag__ = lfsr_tag_key(alt);
@@ -2574,7 +2582,7 @@ static int lfsr_rbyd_appendattr(lfs_t *lfs, lfsr_rbyd_t *rbyd,
// this gets a bit confusing as we also may need to keep // this gets a bit confusing as we also may need to keep
// track of both the lower and upper bounds of diverging paths // track of both the lower and upper bounds of diverging paths
// in the case of range deletions // in the case of range deletions
lfs_size_t branch = rbyd->trunk; lfs_size_t branch = lfsr_rbyd_trunk(rbyd);
lfsr_srid_t lower_rid = 0; lfsr_srid_t lower_rid = 0;
lfsr_srid_t upper_rid = rbyd->weight; lfsr_srid_t upper_rid = rbyd->weight;
lfsr_tag_t lower_tag = 0; lfsr_tag_t lower_tag = 0;
@@ -2599,7 +2607,7 @@ static int lfsr_rbyd_appendattr(lfs_t *lfs, lfsr_rbyd_t *rbyd,
rbyd->weight += delta; rbyd->weight += delta;
// assume we'll update our trunk // assume we'll update our trunk
rbyd->trunk = rbyd->eoff; rbyd->trunk = (rbyd->trunk & LFSR_RBYD_SHRUB) | rbyd->eoff;
// no trunk yet? // no trunk yet?
if (!branch) { if (!branch) {
@@ -2826,7 +2834,6 @@ static int lfsr_rbyd_appendattr(lfs_t *lfs, lfsr_rbyd_t *rbyd,
// note we: // note we:
// - clear valid bit, marking the tag as found // - clear valid bit, marking the tag as found
// - preserve diverged state // - preserve diverged state
LFS_ASSERT(lfsr_tag_shrubmode(alt) == 0x0000);
tag_ = lfsr_tag_mode(tag_ & ~LFSR_TAG_RM) | alt; tag_ = lfsr_tag_mode(tag_ & ~LFSR_TAG_RM) | alt;
// done? // done?
@@ -2958,10 +2965,12 @@ leaf:;
// note we always need a non-alt to terminate the trunk, otherwise we // note we always need a non-alt to terminate the trunk, otherwise we
// can't find trunks during fetch // can't find trunks during fetch
lfs_ssize_t d = lfsr_bd_progtag(lfs, rbyd->blocks[0], rbyd->eoff, lfs_ssize_t d = lfsr_bd_progtag(lfs, rbyd->blocks[0], rbyd->eoff,
// rm => null or shrubnull, otherwise strip off control bits // mark as shrub if we are a shrub
(lfsr_tag_isrm(tag)) (lfsr_rbyd_isshrub(rbyd) ? LFSR_TAG_SHRUB : 0)
? lfsr_tag_mode(lfsr_tag_shrubkey(tag)) // rm => null, otherwise strip off control bits
: lfsr_tag_shrubkey(tag), | ((lfsr_tag_isrm(tag))
? LFSR_TAG_NULL
: lfsr_tag_key(tag)),
upper_rid - lower_rid + delta, upper_rid - lower_rid + delta,
lfsr_data_size(&data), lfsr_data_size(&data),
&rbyd->cksum); &rbyd->cksum);
@@ -3286,7 +3295,10 @@ static int lfsr_rbyd_appendcompactattr(lfs_t *lfs, lfsr_rbyd_t *rbyd,
// write the tag // write the tag
lfs_ssize_t d = lfsr_bd_progtag(lfs, rbyd->blocks[0], rbyd->eoff, lfs_ssize_t d = lfsr_bd_progtag(lfs, rbyd->blocks[0], rbyd->eoff,
tag, weight, lfsr_data_size(&data), // mark as shrub if we are a shrub
(lfsr_rbyd_isshrub(rbyd) ? LFSR_TAG_SHRUB : 0)
| tag,
weight, lfsr_data_size(&data),
&rbyd->cksum); &rbyd->cksum);
if (d < 0) { if (d < 0) {
return d; return d;
@@ -3308,8 +3320,7 @@ static int lfsr_rbyd_appendcompactattr(lfs_t *lfs, lfsr_rbyd_t *rbyd,
return 0; return 0;
} }
static int lfsr_rbyd_appendcompactrbyd(lfs_t *lfs, static int lfsr_rbyd_appendcompactrbyd(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
lfsr_rbyd_t *rbyd_, bool isshrub,
lfsr_srid_t start_rid, lfsr_srid_t end_rid, lfsr_srid_t start_rid, lfsr_srid_t end_rid,
const lfsr_rbyd_t *rbyd) { const lfsr_rbyd_t *rbyd) {
// copy over tags in the rbyd in order // copy over tags in the rbyd in order
@@ -3335,8 +3346,7 @@ static int lfsr_rbyd_appendcompactrbyd(lfs_t *lfs,
} }
// write the tag // write the tag
err = lfsr_rbyd_appendcompactattr(lfs, rbyd_, err = lfsr_rbyd_appendcompactattr(lfs, rbyd_, tag, weight, data);
((isshrub) ? LFSR_TAG_SHRUB : 0) | tag, weight, data);
if (err) { if (err) {
return err; return err;
} }
@@ -3345,8 +3355,7 @@ static int lfsr_rbyd_appendcompactrbyd(lfs_t *lfs,
return 0; return 0;
} }
static int lfsr_rbyd_appendcompaction(lfs_t *lfs, static int lfsr_rbyd_appendcompaction(lfs_t *lfs, lfsr_rbyd_t *rbyd,
lfsr_rbyd_t *rbyd, bool isshrub,
lfs_size_t off) { lfs_size_t off) {
// must fetch before mutating! // must fetch before mutating!
LFS_ASSERT(lfsr_rbyd_isfetched(rbyd)); LFS_ASSERT(lfsr_rbyd_isfetched(rbyd));
@@ -3365,14 +3374,17 @@ static int lfsr_rbyd_appendcompaction(lfs_t *lfs,
// empty rbyd? write a null tag so our trunk can still point to something // empty rbyd? write a null tag so our trunk can still point to something
if (rbyd->eoff == off) { if (rbyd->eoff == off) {
lfs_ssize_t d = lfsr_bd_progtag(lfs, rbyd->blocks[0], rbyd->eoff, lfs_ssize_t d = lfsr_bd_progtag(lfs, rbyd->blocks[0], rbyd->eoff,
(isshrub) ? LFSR_TAG_SHRUB(NULL) : LFSR_TAG_NULL, 0, 0, // mark as shrub if we are a shrub
(lfsr_rbyd_isshrub(rbyd) ? LFSR_TAG_SHRUB : 0)
| LFSR_TAG_NULL,
0, 0,
&rbyd->cksum); &rbyd->cksum);
if (d < 0) { if (d < 0) {
return d; return d;
} }
rbyd->eoff += d; rbyd->eoff += d;
rbyd->trunk = off; rbyd->trunk = (rbyd->trunk & LFSR_RBYD_SHRUB) | off;
rbyd->weight = 0; rbyd->weight = 0;
return 0; return 0;
} }
@@ -3409,7 +3421,8 @@ static int lfsr_rbyd_appendcompaction(lfs_t *lfs,
// ignore shrub trunks, unless we are actually compacting // ignore shrub trunks, unless we are actually compacting
// a shrub tree // a shrub tree
if (!isshrub && lfsr_tag_isshrub(tag__)) { if (!lfsr_rbyd_isshrub(rbyd)
&& lfsr_tag_isshrub(tag__)) {
trunk = off; trunk = off;
weight = 0; weight = 0;
continue; continue;
@@ -3452,7 +3465,10 @@ static int lfsr_rbyd_appendcompaction(lfs_t *lfs,
// terminate with a null tag // terminate with a null tag
lfs_ssize_t d = lfsr_bd_progtag(lfs, rbyd->blocks[0], rbyd->eoff, lfs_ssize_t d = lfsr_bd_progtag(lfs, rbyd->blocks[0], rbyd->eoff,
(isshrub) ? LFSR_TAG_SHRUB(NULL) : LFSR_TAG_NULL, 0, 0, // mark as shrub if we are a shrub
(lfsr_rbyd_isshrub(rbyd) ? LFSR_TAG_SHRUB : 0)
| LFSR_TAG_NULL,
0, 0,
&rbyd->cksum); &rbyd->cksum);
if (d < 0) { if (d < 0) {
return d; return d;
@@ -3466,7 +3482,7 @@ static int lfsr_rbyd_appendcompaction(lfs_t *lfs,
done:; done:;
// done! just need to update our trunk. Note we could have no trunks // done! just need to update our trunk. Note we could have no trunks
// after compaction. Leave this to upper layers to take care of this. // after compaction. Leave this to upper layers to take care of this.
rbyd->trunk = layer; rbyd->trunk = (rbyd->trunk & LFSR_RBYD_SHRUB) | layer;
rbyd->weight = weight; rbyd->weight = weight;
return 0; return 0;
@@ -3476,14 +3492,14 @@ static int lfsr_rbyd_compact(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
lfsr_srid_t start_rid, lfsr_srid_t end_rid, lfsr_srid_t start_rid, lfsr_srid_t end_rid,
const lfsr_rbyd_t *rbyd) { const lfsr_rbyd_t *rbyd) {
// append rbyd // append rbyd
int err = lfsr_rbyd_appendcompactrbyd(lfs, rbyd_, false, int err = lfsr_rbyd_appendcompactrbyd(lfs, rbyd_, start_rid, end_rid,
start_rid, end_rid, rbyd); rbyd);
if (err) { if (err) {
return err; return err;
} }
// compact // compact
err = lfsr_rbyd_appendcompaction(lfs, rbyd_, false, 0); err = lfsr_rbyd_appendcompaction(lfs, rbyd_, 0);
if (err) { if (err) {
return err; return err;
} }
@@ -3542,16 +3558,17 @@ static int lfsr_rbyd_appendshrub(lfs_t *lfs, lfsr_rbyd_t *rbyd,
const lfsr_shrub_t *shrub) { const lfsr_shrub_t *shrub) {
// keep track of the start of the new tree // keep track of the start of the new tree
lfs_size_t off = rbyd->eoff; lfs_size_t off = rbyd->eoff;
// mark as shrub
rbyd->trunk |= LFSR_RBYD_SHRUB;
// compact our shrub // compact our shrub
int err = lfsr_rbyd_appendcompactrbyd(lfs, rbyd, true, int err = lfsr_rbyd_appendcompactrbyd(lfs, rbyd, -1, -1,
-1, -1, lfsr_shrub_rbyd(shrub)); lfsr_shrub_rbyd(shrub));
if (err) { if (err) {
return err; return err;
} }
err = lfsr_rbyd_appendcompaction(lfs, rbyd, true, err = lfsr_rbyd_appendcompaction(lfs, rbyd, off);
off);
if (err) { if (err) {
return err; return err;
} }
@@ -3697,7 +3714,7 @@ static lfsr_data_t lfsr_data_frombranch(const lfsr_rbyd_t *branch,
LFS_ASSERT(d_ >= 0); LFS_ASSERT(d_ >= 0);
d += d_; d += d_;
d_ = lfs_toleb128(branch->trunk, &buffer[d], 5); d_ = lfs_toleb128(lfsr_rbyd_trunk(branch), &buffer[d], 5);
LFS_ASSERT(d_ >= 0); LFS_ASSERT(d_ >= 0);
d += d_; d += d_;
@@ -3720,7 +3737,7 @@ static int lfsr_data_readbranch(lfs_t *lfs, lfsr_data_t *data,
return err; return err;
} }
err = lfsr_data_readleb128(lfs, data, (int32_t*)&branch->trunk); err = lfsr_data_readleb128(lfs, data, &branch->trunk);
if (err) { if (err) {
return err; return err;
} }
@@ -3922,8 +3939,7 @@ static int lfsr_btree_parent(lfs_t *lfs, const lfsr_btree_t *btree,
} }
// found our child? // found our child?
if (branch_.blocks[0] == child->blocks[0] if (lfsr_rbyd_cmp(&branch_, child) == 0) {
&& branch_.trunk == child->trunk) {
// TODO how many of these should be conditional? // TODO how many of these should be conditional?
if (rbyd_) { if (rbyd_) {
*rbyd_ = branch; *rbyd_ = branch;
@@ -3943,10 +3959,9 @@ static int lfsr_btree_parent(lfs_t *lfs, const lfsr_btree_t *btree,
// //
// this commits up to the root, but stops if: // this commits up to the root, but stops if:
// 1. we need a new root // 1. we need a new root
// 2. shrub=true, which means we have a shrub root // 2. we have a shrub root
// //
static int lfsr_btree_commit_(lfs_t *lfs, static int lfsr_btree_commit_(lfs_t *lfs, lfsr_btree_t *btree,
lfsr_btree_t *btree, bool shrub,
const lfsr_attr_t **attrs_, lfs_size_t *attr_count_, const lfsr_attr_t **attrs_, lfs_size_t *attr_count_,
lfsr_attr_t attrs__[static 4], lfsr_attr_t attrs__[static 4],
uint8_t buf__[static 2*LFSR_BRANCH_DSIZE]) { uint8_t buf__[static 2*LFSR_BRANCH_DSIZE]) {
@@ -3988,13 +4003,15 @@ static int lfsr_btree_commit_(lfs_t *lfs,
lfsr_rbyd_t parent = {.trunk=0, .weight=0}; lfsr_rbyd_t parent = {.trunk=0, .weight=0};
lfsr_srid_t rid = -1; lfsr_srid_t rid = -1;
// are we root? // are we root?
if (rbyd.blocks[0] == btree->blocks[0] || rbyd.trunk == 0) { if (rbyd.blocks[0] == btree->blocks[0]
|| !lfsr_rbyd_hastrunk(&rbyd)) {
// new root? shrub root? yield the final root commit to // new root? shrub root? yield the final root commit to
// higher-level btree/bshrub logic // higher-level btree/bshrub logic
if (rbyd.trunk == 0 || shrub) { if (!lfsr_rbyd_hastrunk(&rbyd)
|| lfsr_rbyd_isshrub(btree)) {
*attrs_ = attrs; *attrs_ = attrs;
*attr_count_ = attr_count; *attr_count_ = attr_count;
return (rbyd.trunk == 0) ? LFS_ERR_RANGE : 0; return (!lfsr_rbyd_hastrunk(&rbyd)) ? LFS_ERR_RANGE : 0;
} }
// mark btree as unerased in case of failure, our btree rbyd and // mark btree as unerased in case of failure, our btree rbyd and
@@ -4020,7 +4037,8 @@ static int lfsr_btree_commit_(lfs_t *lfs,
// a funny benefit is we cache the root of our btree this way // a funny benefit is we cache the root of our btree this way
if (!lfsr_rbyd_isfetched(&rbyd)) { if (!lfsr_rbyd_isfetched(&rbyd)) {
int err = lfsr_rbyd_fetchvalidate(lfs, &rbyd, int err = lfsr_rbyd_fetchvalidate(lfs, &rbyd,
rbyd.blocks[0], rbyd.trunk, rbyd.weight, rbyd.cksum); rbyd.blocks[0], lfsr_rbyd_trunk(&rbyd), rbyd.weight,
rbyd.cksum);
if (err) { if (err) {
return err; return err;
} }
@@ -4051,7 +4069,7 @@ static int lfsr_btree_commit_(lfs_t *lfs,
finalize:; finalize:;
// done? // done?
if (parent.trunk == 0) { if (!lfsr_rbyd_hastrunk(&parent)) {
LFS_ASSERT(bid == 0); LFS_ASSERT(bid == 0);
*btree = rbyd_; *btree = rbyd_;
*attr_count_ = 0; *attr_count_ = 0;
@@ -4109,7 +4127,7 @@ static int lfsr_btree_commit_(lfs_t *lfs,
lfsr_rbyd_t sibling; lfsr_rbyd_t sibling;
if ((lfs_size_t)estimate <= lfs->cfg->block_size/4 if ((lfs_size_t)estimate <= lfs->cfg->block_size/4
// no parent? can't merge // no parent? can't merge
&& parent.trunk != 0) { && !lfsr_rbyd_hastrunk(&parent)) {
// try the right sibling // try the right sibling
if (rid+1 < parent.weight) { if (rid+1 < parent.weight) {
// try looking up the sibling // try looking up the sibling
@@ -4344,7 +4362,7 @@ static int lfsr_btree_commit_(lfs_t *lfs,
attr_count = 0; attr_count = 0;
buf_size = 0; buf_size = 0;
// new root? // new root?
if (parent.trunk == 0) { if (!lfsr_rbyd_hastrunk(&parent)) {
attrs__[attr_count++] = LFSR_ATTR(0, attrs__[attr_count++] = LFSR_ATTR(0,
BRANCH, +rbyd_.weight, BRANCH, +rbyd_.weight,
FROMBRANCH(&rbyd_, &buf__[buf_size])); FROMBRANCH(&rbyd_, &buf__[buf_size]));
@@ -4393,21 +4411,19 @@ static int lfsr_btree_commit_(lfs_t *lfs,
} }
// merge the siblings together // merge the siblings together
err = lfsr_rbyd_appendcompactrbyd(lfs, &rbyd_, false, err = lfsr_rbyd_appendcompactrbyd(lfs, &rbyd_, -1, -1, &rbyd);
-1, -1, &rbyd);
if (err) { if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE); LFS_ASSERT(err != LFS_ERR_RANGE);
return err; return err;
} }
err = lfsr_rbyd_appendcompactrbyd(lfs, &rbyd_, false, err = lfsr_rbyd_appendcompactrbyd(lfs, &rbyd_, -1, -1, &sibling);
-1, -1, &sibling);
if (err) { if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE); LFS_ASSERT(err != LFS_ERR_RANGE);
return err; return err;
} }
err = lfsr_rbyd_appendcompaction(lfs, &rbyd_, false, 0); err = lfsr_rbyd_appendcompaction(lfs, &rbyd_, 0);
if (err) { if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE); LFS_ASSERT(err != LFS_ERR_RANGE);
return err; return err;
@@ -4430,7 +4446,7 @@ static int lfsr_btree_commit_(lfs_t *lfs,
// we must have a parent at this point, but is our parent the root // we must have a parent at this point, but is our parent the root
// and is the root degenerate? // and is the root degenerate?
LFS_ASSERT(parent.trunk != 0); LFS_ASSERT(lfsr_rbyd_hastrunk(&parent) != 0);
if (rbyd.weight+sibling.weight == btree->weight) { if (rbyd.weight+sibling.weight == btree->weight) {
// collapse the root, decreasing the height of the tree // collapse the root, decreasing the height of the tree
*btree = rbyd_; *btree = rbyd_;
@@ -4467,7 +4483,7 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
uint8_t buffer[2*LFSR_BRANCH_DSIZE]; uint8_t buffer[2*LFSR_BRANCH_DSIZE];
// try to commit to the btree // try to commit to the btree
int err = lfsr_btree_commit_(lfs, btree, false, int err = lfsr_btree_commit_(lfs, btree,
&attrs, &attr_count, &attrs, &attr_count,
attrs__, buffer); attrs__, buffer);
if (err && err != LFS_ERR_RANGE) { if (err && err != LFS_ERR_RANGE) {
@@ -4493,7 +4509,7 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree,
*btree = rbyd; *btree = rbyd;
} }
LFS_ASSERT(btree->trunk != 0); LFS_ASSERT(lfsr_rbyd_hastrunk(btree));
return 0; return 0;
} }
@@ -4582,16 +4598,15 @@ typedef struct lfsr_btraversal {
.branch.trunk=0, \ .branch.trunk=0, \
.branch.weight=0}) .branch.weight=0})
static int lfsr_btree_traverse_(lfs_t *lfs, static int lfsr_btree_traverse_(lfs_t *lfs, const lfsr_btree_t *btree,
const lfsr_btree_t *btree, bool shrub,
lfsr_btraversal_t *btraversal, lfsr_btraversal_t *btraversal,
lfsr_bid_t *bid_, lfsr_tinfo_t *tinfo_) { lfsr_bid_t *bid_, lfsr_tinfo_t *tinfo_) {
// explicitly traverse the root even if weight=0 // explicitly traverse the root even if weight=0
if (btraversal->branch.trunk == 0 if (btraversal->branch.trunk == 0
// unless we don't even have a root yet // unless we don't even have a root yet
&& btree->trunk != 0 && lfsr_rbyd_trunk(btree) != 0
// or are a shrub // or are a shrub
&& !shrub) { && !lfsr_rbyd_isshrub(btree)) {
btraversal->rid = btraversal->bid; btraversal->rid = btraversal->bid;
btraversal->branch = *btree; btraversal->branch = *btree;
@@ -4688,8 +4703,7 @@ static int lfsr_btree_traverse_(lfs_t *lfs,
static int lfsr_btree_traverse(lfs_t *lfs, const lfsr_btree_t *btree, static int lfsr_btree_traverse(lfs_t *lfs, const lfsr_btree_t *btree,
lfsr_btraversal_t *btraversal, lfsr_btraversal_t *btraversal,
lfsr_bid_t *bid_, lfsr_tinfo_t *tinfo_) { lfsr_bid_t *bid_, lfsr_tinfo_t *tinfo_) {
return lfsr_btree_traverse_(lfs, btree, false, return lfsr_btree_traverse_(lfs, btree, btraversal,
btraversal,
bid_, tinfo_); bid_, tinfo_);
} }
@@ -4784,6 +4798,14 @@ static int lfsr_sprout_compact(lfs_t *lfs, const lfsr_rbyd_t *rbyd_,
// shrub things // shrub things
static inline lfs_size_t lfsr_shrub_trunk(const lfsr_shrub_t *shrub) {
return shrub->trunk & ~LFSR_RBYD_SHRUB;
}
static inline bool lfsr_shrub_hastrunk(const lfsr_shrub_t *shrub) {
return lfsr_shrub_trunk(shrub) != 0;
}
static inline const lfsr_rbyd_t *lfsr_shrub_rbyd(const lfsr_shrub_t *shrub) { static inline const lfsr_rbyd_t *lfsr_shrub_rbyd(const lfsr_shrub_t *shrub) {
return (const lfsr_rbyd_t*)shrub; return (const lfsr_rbyd_t*)shrub;
} }
@@ -4805,7 +4827,7 @@ static inline int lfsr_shrub_cmp(
static lfsr_data_t lfsr_data_fromshrub(const lfsr_shrub_t *shrub, static lfsr_data_t lfsr_data_fromshrub(const lfsr_shrub_t *shrub,
uint8_t buffer[static LFSR_SHRUB_DSIZE]) { uint8_t buffer[static LFSR_SHRUB_DSIZE]) {
// shrub trunks should never be null // shrub trunks should never be null
LFS_ASSERT(shrub->trunk != 0); LFS_ASSERT(lfsr_shrub_trunk(shrub) != 0);
lfs_ssize_t d = 0; lfs_ssize_t d = 0;
// just write the trunk and weight, the rest of the rbyd is contextual // just write the trunk and weight, the rest of the rbyd is contextual
@@ -4813,7 +4835,7 @@ static lfsr_data_t lfsr_data_fromshrub(const lfsr_shrub_t *shrub,
LFS_ASSERT(d_ >= 0); LFS_ASSERT(d_ >= 0);
d += d_; d += d_;
d_ = lfs_toleb128(shrub->trunk, &buffer[d], 5); d_ = lfs_toleb128(lfsr_shrub_trunk(shrub), &buffer[d], 5);
LFS_ASSERT(d_ >= 0); LFS_ASSERT(d_ >= 0);
d += d_; d += d_;
@@ -4833,13 +4855,15 @@ static int lfsr_data_readshrub(lfs_t *lfs, lfsr_data_t *data,
return err; return err;
} }
err = lfsr_data_readleb128(lfs, data, (int32_t*)&shrub->trunk); err = lfsr_data_readleb128(lfs, data, &shrub->trunk);
if (err) { if (err) {
return err; return err;
} }
// shrub trunks should never be null // shrub trunks should never be null
LFS_ASSERT(shrub->trunk != 0); LFS_ASSERT(lfsr_shrub_hastrunk(shrub));
// set the shrub bit in our trunk
shrub->trunk |= LFSR_RBYD_SHRUB;
return 0; return 0;
} }
@@ -4869,7 +4893,7 @@ static lfs_ssize_t lfsr_shrub_estimate(lfs_t *lfs,
static int lfsr_shrub_compact(lfs_t *lfs, lfsr_rbyd_t *rbyd_, static int lfsr_shrub_compact(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
lfsr_shrub_t *shrub_, const lfsr_shrub_t *shrub) { lfsr_shrub_t *shrub_, const lfsr_shrub_t *shrub) {
// save our current trunk/weight // save our current trunk/weight
lfs_size_t trunk = rbyd_->trunk; lfs_ssize_t trunk = rbyd_->trunk;
lfsr_srid_t weight = rbyd_->weight; lfsr_srid_t weight = rbyd_->weight;
// compact our bshrub // compact our bshrub
@@ -4919,21 +4943,16 @@ static int lfsr_shrub_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd_,
// things up too much // things up too much
// //
// it is important that these rbyds share eoff/cksum/etc // it is important that these rbyds share eoff/cksum/etc
lfs_size_t trunk = rbyd_->trunk; lfs_ssize_t trunk = rbyd_->trunk;
lfsr_srid_t weight = rbyd_->weight; lfsr_srid_t weight = rbyd_->weight;
rbyd_->trunk = shrub->trunk; rbyd_->trunk = shrub->trunk;
rbyd_->weight = shrub->weight; rbyd_->weight = shrub->weight;
// append any bshrub attributes // append any bshrub attributes
for (lfs_size_t j = 0; j < attr_count; j++) { int err = lfsr_rbyd_appendattrs(lfs, rbyd_, -1, -1,
int err = lfsr_rbyd_appendattr(lfs, rbyd_, attrs, attr_count);
attrs[j].rid, if (err) {
LFSR_TAG_SHRUB | attrs[j].tag, return err;
attrs[j].delta,
attrs[j].data);
if (err) {
return err;
}
} }
// restore mdir to the main trunk/weight // restore mdir to the main trunk/weight
@@ -5604,7 +5623,7 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir,
// extensions are atomic // extensions are atomic
if (attrs[i].tag == LFSR_TAG_SHRUBALLOC) { if (attrs[i].tag == LFSR_TAG_SHRUBALLOC) {
bshrubcommit->shrub->blocks[0] = rbyd_.blocks[0]; bshrubcommit->shrub->blocks[0] = rbyd_.blocks[0];
bshrubcommit->shrub->trunk = 0; bshrubcommit->shrub->trunk = LFSR_RBYD_SHRUB | 0;
bshrubcommit->shrub->weight = 0; bshrubcommit->shrub->weight = 0;
} }
@@ -5929,7 +5948,7 @@ static int lfsr_mdir_compact__(lfs_t *lfs, lfsr_mdir_t *mdir_,
} }
} }
int err = lfsr_rbyd_appendcompaction(lfs, &mdir_->rbyd, false, 0); int err = lfsr_rbyd_appendcompaction(lfs, &mdir_->rbyd, 0);
if (err) { if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE); LFS_ASSERT(err != LFS_ERR_RANGE);
return err; return err;
@@ -6203,7 +6222,7 @@ static int lfsr_mroot_commit_(lfs_t *lfs,
} }
} }
err = lfsr_rbyd_appendcompaction(lfs, &mrootanchor_.rbyd, false, 0); err = lfsr_rbyd_appendcompaction(lfs, &mrootanchor_.rbyd, 0);
if (err) { if (err) {
LFS_ASSERT(err != LFS_ERR_RANGE); LFS_ASSERT(err != LFS_ERR_RANGE);
return err; return err;
@@ -8037,7 +8056,7 @@ int lfsr_mount(lfs_t *lfs, const struct lfs_config *cfg) {
lfs->cfg->block_count, lfs->cfg->block_count,
lfs->mroot.rbyd.blocks[0], lfs->mroot.rbyd.blocks[0],
lfs->mroot.rbyd.blocks[1], lfs->mroot.rbyd.blocks[1],
lfs->mroot.rbyd.trunk, lfsr_rbyd_trunk(&lfs->mroot.rbyd),
lfsr_mtree_weight(lfs) / lfsr_mweight(lfs), lfsr_mtree_weight(lfs) / lfsr_mweight(lfs),
lfsr_mweight(lfs)); lfsr_mweight(lfs));
@@ -9594,7 +9613,6 @@ static int lfsr_bshrub_traverse(lfs_t *lfs, const lfsr_file_t *file,
} else if (lfsr_bshrub_isbshruborbtree(&file->bshrub)) { } else if (lfsr_bshrub_isbshruborbtree(&file->bshrub)) {
int err = lfsr_btree_traverse_(lfs, int err = lfsr_btree_traverse_(lfs,
lfsr_shrub_rbyd(&file->bshrub.u.bshrub), lfsr_shrub_rbyd(&file->bshrub.u.bshrub),
lfsr_bshrub_isbshrub(&file->m.mdir, &file->bshrub),
btraversal, btraversal,
bid_, tinfo_); bid_, tinfo_);
if (err) { if (err) {
@@ -9713,7 +9731,6 @@ static int lfsr_bshrub_commit(lfs_t *lfs, lfsr_file_t *file,
// try to commit to the btree // try to commit to the btree
int err = lfsr_btree_commit_(lfs, &file->bshrub.u.btree, int err = lfsr_btree_commit_(lfs, &file->bshrub.u.btree,
lfsr_bshrub_isbshrub(&file->m.mdir, &file->bshrub),
&attrs, &attr_count, &attrs, &attr_count,
attrs__, buffer); attrs__, buffer);
if (err && err != LFS_ERR_RANGE) { if (err && err != LFS_ERR_RANGE) {
@@ -9803,7 +9820,7 @@ static int lfsr_bshrub_commit(lfs_t *lfs, lfsr_file_t *file,
return 0; return 0;
} }
LFS_ASSERT(file->bshrub.u.bshrub.trunk != 0); LFS_ASSERT(lfsr_shrub_hastrunk(&file->bshrub.u.bshrub));
return 0; return 0;
evict:; evict:;
@@ -9880,7 +9897,7 @@ static int lfsr_file_carve(lfs_t *lfs, lfsr_file_t *file,
} }
file->bshrub.u.bshrub.blocks[0] = file->m.mdir.rbyd.blocks[0]; file->bshrub.u.bshrub.blocks[0] = file->m.mdir.rbyd.blocks[0];
file->bshrub.u.bshrub.trunk = 0; file->bshrub.u.bshrub.trunk = LFSR_RBYD_SHRUB | 0;
file->bshrub.u.bshrub.weight = 0; file->bshrub.u.bshrub.weight = 0;
// force estimate recalculation // force estimate recalculation
file->bshrub.u.bshrub.estimate = -1; file->bshrub.u.bshrub.estimate = -1;
+5 -2
View File
@@ -339,12 +339,15 @@ typedef struct lfs_cache {
// TODO do we get ram savings with a lfsr_rorbyd_t substruct? need to measure // TODO do we get ram savings with a lfsr_rorbyd_t substruct? need to measure
typedef struct lfsr_rbyd { typedef struct lfsr_rbyd {
// note this lines up with weight in lfsr_btree_t // note this lines up with weight in lfsr_btree_t
// sign(weight)=0 => rbyd
lfsr_srid_t weight; lfsr_srid_t weight;
lfs_block_t blocks[2]; lfs_block_t blocks[2];
// sign(trunk)=0 => normal rbyd
// sign(trunk)=1 => shrub rbyd
// eoff=0, trunk=0 => not yet committed // eoff=0, trunk=0 => not yet committed
// eoff=0, trunk>0 => not yet fetched // eoff=0, trunk>0 => not yet fetched
// eoff>=block_size => rbyd not erased/needs compaction // eoff>=block_size => rbyd not erased/needs compaction
lfs_size_t trunk; lfs_ssize_t trunk;
lfs_size_t eoff; lfs_size_t eoff;
uint32_t cksum; uint32_t cksum;
} lfsr_rbyd_t; } lfsr_rbyd_t;
@@ -493,7 +496,7 @@ typedef struct lfsr_shrub {
// this all lines up with lfsr_rbyd_t // this all lines up with lfsr_rbyd_t
lfsr_srid_t weight; lfsr_srid_t weight;
lfs_block_t blocks[2]; lfs_block_t blocks[2];
lfs_size_t trunk; lfs_ssize_t trunk;
lfs_size_t eoff; lfs_size_t eoff;
// an upper-bound estimate on the on-disk shrub size // an upper-bound estimate on the on-disk shrub size
lfs_size_t estimate; lfs_size_t estimate;
+1
View File
@@ -696,6 +696,7 @@ class Rbyd:
# keep track of eoff for best matching trunk # keep track of eoff for best matching trunk
if trunk and j_ + size > trunk: if trunk and j_ + size > trunk:
trunkeoff = j_ + size trunkeoff = j_ + size
eoff = trunkeoff
cksum = cksum_ cksum = cksum_
trunk_ = trunk__ trunk_ = trunk__
weight = weight_ weight = weight_
+1
View File
@@ -363,6 +363,7 @@ class Rbyd:
# keep track of eoff for best matching trunk # keep track of eoff for best matching trunk
if trunk and j_ + size > trunk: if trunk and j_ + size > trunk:
trunkeoff = j_ + size trunkeoff = j_ + size
eoff = trunkeoff
cksum = cksum_ cksum = cksum_
trunk_ = trunk__ trunk_ = trunk__
weight = weight_ weight = weight_
+1
View File
@@ -394,6 +394,7 @@ class Rbyd:
# keep track of eoff for best matching trunk # keep track of eoff for best matching trunk
if trunk and j_ + size > trunk: if trunk and j_ + size > trunk:
trunkeoff = j_ + size trunkeoff = j_ + size
eoff = trunkeoff
cksum = cksum_ cksum = cksum_
trunk_ = trunk__ trunk_ = trunk__
weight = weight_ weight = weight_
+1
View File
@@ -378,6 +378,7 @@ class Rbyd:
# keep track of eoff for best matching trunk # keep track of eoff for best matching trunk
if trunk and j_ + size > trunk: if trunk and j_ + size > trunk:
trunkeoff = j_ + size trunkeoff = j_ + size
eoff = trunkeoff
cksum = cksum_ cksum = cksum_
trunk_ = trunk__ trunk_ = trunk__
weight = weight_ weight = weight_