From bea13dcf8eaad3c158da24271f3709ac5a25f67e Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sun, 21 Jan 2024 00:06:36 -0600 Subject: [PATCH] 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%) --- lfs.c | 215 ++++++++++++++++++++++++-------------------- lfs.h | 7 +- scripts/dbgbmap.py | 1 + scripts/dbgbtree.py | 1 + scripts/dbglfs.py | 1 + scripts/dbgmtree.py | 1 + 6 files changed, 125 insertions(+), 101 deletions(-) diff --git a/lfs.c b/lfs.c index a5899926..ef20bb76 100644 --- a/lfs.c +++ b/lfs.c @@ -722,14 +722,6 @@ static inline lfsr_tag_t lfsr_tag_subkey(lfsr_tag_t tag) { 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) { return tag & LFSR_TAG_ALT; } @@ -1993,9 +1985,23 @@ static void lfs_alloc_ckpoint(lfs_t *lfs); /// Red-black-yellow Dhara tree operations /// +#define LFSR_RBYD_SHRUB 0x80000000 + // 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) { - return !(rbyd->eoff == 0 && rbyd->trunk > 0); + return !(lfsr_rbyd_hastrunk(rbyd) && rbyd->eoff == 0); } 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, - 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 uint32_t cksum = 0; 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->eoff = 0; - rbyd->trunk = 0; + rbyd->trunk = (trunk & LFSR_RBYD_SHRUB) | 0; + trunk &= ~LFSR_RBYD_SHRUB; // temporary state until we validate a cksum 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}; // 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_rid_t weight__; 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 rbyd->eoff = off_ + size; rbyd->cksum = cksum; - rbyd->trunk = trunk_; + rbyd->trunk = (LFSR_RBYD_SHRUB & rbyd->trunk) | trunk_; rbyd->weight = weight; } // 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? if (!wastrunk) { wastrunk = true; @@ -2177,7 +2186,7 @@ static int lfsr_rbyd_fetch(lfs_t *lfs, lfsr_rbyd_t *rbyd, } // no valid commits? - if (!rbyd->trunk) { + if (!lfsr_rbyd_hastrunk(rbyd)) { 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 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) { int err = lfsr_rbyd_fetch(lfs, rbyd, block, trunk); if (err) { @@ -2222,13 +2231,13 @@ static int lfsr_rbyd_fetchvalidate(lfs_t *lfs, lfsr_rbyd_t *rbyd, if (rbyd->cksum != cksum) { LFS_ERROR("Found rbyd cksum mismatch rbyd 0x%"PRIx32".%"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; } // if trunk/weight mismatch _after_ cksums match, that's not a storage // 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); return 0; } @@ -2246,12 +2255,12 @@ static int lfsr_rbyd_lookupnext(lfs_t *lfs, const lfsr_rbyd_t *rbyd, tag = lfs_max16(tag, 0x1); // out of bounds? no trunk yet? - if (rid >= rbyd->weight || !rbyd->trunk) { + if (rid >= rbyd->weight || !lfsr_rbyd_hastrunk(rbyd)) { return LFS_ERR_NOENT; } // 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 upper = rbyd->weight; @@ -2281,7 +2290,6 @@ static int lfsr_rbyd_lookupnext(lfs_t *lfs, const lfsr_rbyd_t *rbyd, // found end of tree? } else { // update the tag rid - LFS_ASSERT(lfsr_tag_shrubmode(alt) == 0x0000); lfsr_srid_t rid__ = upper-1; 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 // track of both the lower and upper bounds of diverging paths // 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 upper_rid = rbyd->weight; 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; // assume we'll update our trunk - rbyd->trunk = rbyd->eoff; + rbyd->trunk = (rbyd->trunk & LFSR_RBYD_SHRUB) | rbyd->eoff; // no trunk yet? if (!branch) { @@ -2826,7 +2834,6 @@ static int lfsr_rbyd_appendattr(lfs_t *lfs, lfsr_rbyd_t *rbyd, // note we: // - clear valid bit, marking the tag as found // - preserve diverged state - LFS_ASSERT(lfsr_tag_shrubmode(alt) == 0x0000); tag_ = lfsr_tag_mode(tag_ & ~LFSR_TAG_RM) | alt; // done? @@ -2958,10 +2965,12 @@ leaf:; // note we always need a non-alt to terminate the trunk, otherwise we // can't find trunks during fetch lfs_ssize_t d = lfsr_bd_progtag(lfs, rbyd->blocks[0], rbyd->eoff, - // rm => null or shrubnull, otherwise strip off control bits - (lfsr_tag_isrm(tag)) - ? lfsr_tag_mode(lfsr_tag_shrubkey(tag)) - : lfsr_tag_shrubkey(tag), + // mark as shrub if we are a shrub + (lfsr_rbyd_isshrub(rbyd) ? LFSR_TAG_SHRUB : 0) + // rm => null, otherwise strip off control bits + | ((lfsr_tag_isrm(tag)) + ? LFSR_TAG_NULL + : lfsr_tag_key(tag)), upper_rid - lower_rid + delta, lfsr_data_size(&data), &rbyd->cksum); @@ -3286,7 +3295,10 @@ static int lfsr_rbyd_appendcompactattr(lfs_t *lfs, lfsr_rbyd_t *rbyd, // write the tag 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); if (d < 0) { return d; @@ -3308,8 +3320,7 @@ static int lfsr_rbyd_appendcompactattr(lfs_t *lfs, lfsr_rbyd_t *rbyd, return 0; } -static int lfsr_rbyd_appendcompactrbyd(lfs_t *lfs, - lfsr_rbyd_t *rbyd_, bool isshrub, +static int lfsr_rbyd_appendcompactrbyd(lfs_t *lfs, lfsr_rbyd_t *rbyd_, lfsr_srid_t start_rid, lfsr_srid_t end_rid, const lfsr_rbyd_t *rbyd) { // copy over tags in the rbyd in order @@ -3335,8 +3346,7 @@ static int lfsr_rbyd_appendcompactrbyd(lfs_t *lfs, } // write the tag - err = lfsr_rbyd_appendcompactattr(lfs, rbyd_, - ((isshrub) ? LFSR_TAG_SHRUB : 0) | tag, weight, data); + err = lfsr_rbyd_appendcompactattr(lfs, rbyd_, tag, weight, data); if (err) { return err; } @@ -3345,8 +3355,7 @@ static int lfsr_rbyd_appendcompactrbyd(lfs_t *lfs, return 0; } -static int lfsr_rbyd_appendcompaction(lfs_t *lfs, - lfsr_rbyd_t *rbyd, bool isshrub, +static int lfsr_rbyd_appendcompaction(lfs_t *lfs, lfsr_rbyd_t *rbyd, lfs_size_t off) { // must fetch before mutating! 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 if (rbyd->eoff == off) { 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); if (d < 0) { return d; } rbyd->eoff += d; - rbyd->trunk = off; + rbyd->trunk = (rbyd->trunk & LFSR_RBYD_SHRUB) | off; rbyd->weight = 0; return 0; } @@ -3409,7 +3421,8 @@ static int lfsr_rbyd_appendcompaction(lfs_t *lfs, // ignore shrub trunks, unless we are actually compacting // a shrub tree - if (!isshrub && lfsr_tag_isshrub(tag__)) { + if (!lfsr_rbyd_isshrub(rbyd) + && lfsr_tag_isshrub(tag__)) { trunk = off; weight = 0; continue; @@ -3452,7 +3465,10 @@ static int lfsr_rbyd_appendcompaction(lfs_t *lfs, // terminate with a null tag 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); if (d < 0) { return d; @@ -3466,7 +3482,7 @@ static int lfsr_rbyd_appendcompaction(lfs_t *lfs, done:; // 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. - rbyd->trunk = layer; + rbyd->trunk = (rbyd->trunk & LFSR_RBYD_SHRUB) | layer; rbyd->weight = weight; 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, const lfsr_rbyd_t *rbyd) { // append rbyd - int err = lfsr_rbyd_appendcompactrbyd(lfs, rbyd_, false, - start_rid, end_rid, rbyd); + int err = lfsr_rbyd_appendcompactrbyd(lfs, rbyd_, start_rid, end_rid, + rbyd); if (err) { return err; } // compact - err = lfsr_rbyd_appendcompaction(lfs, rbyd_, false, 0); + err = lfsr_rbyd_appendcompaction(lfs, rbyd_, 0); if (err) { return err; } @@ -3542,16 +3558,17 @@ static int lfsr_rbyd_appendshrub(lfs_t *lfs, lfsr_rbyd_t *rbyd, const lfsr_shrub_t *shrub) { // keep track of the start of the new tree lfs_size_t off = rbyd->eoff; + // mark as shrub + rbyd->trunk |= LFSR_RBYD_SHRUB; // compact our shrub - int err = lfsr_rbyd_appendcompactrbyd(lfs, rbyd, true, - -1, -1, lfsr_shrub_rbyd(shrub)); + int err = lfsr_rbyd_appendcompactrbyd(lfs, rbyd, -1, -1, + lfsr_shrub_rbyd(shrub)); if (err) { return err; } - err = lfsr_rbyd_appendcompaction(lfs, rbyd, true, - off); + err = lfsr_rbyd_appendcompaction(lfs, rbyd, off); if (err) { return err; } @@ -3697,7 +3714,7 @@ static lfsr_data_t lfsr_data_frombranch(const lfsr_rbyd_t *branch, LFS_ASSERT(d_ >= 0); d += d_; - d_ = lfs_toleb128(branch->trunk, &buffer[d], 5); + d_ = lfs_toleb128(lfsr_rbyd_trunk(branch), &buffer[d], 5); LFS_ASSERT(d_ >= 0); d += d_; @@ -3720,7 +3737,7 @@ static int lfsr_data_readbranch(lfs_t *lfs, lfsr_data_t *data, return err; } - err = lfsr_data_readleb128(lfs, data, (int32_t*)&branch->trunk); + err = lfsr_data_readleb128(lfs, data, &branch->trunk); if (err) { return err; } @@ -3922,8 +3939,7 @@ static int lfsr_btree_parent(lfs_t *lfs, const lfsr_btree_t *btree, } // found our child? - if (branch_.blocks[0] == child->blocks[0] - && branch_.trunk == child->trunk) { + if (lfsr_rbyd_cmp(&branch_, child) == 0) { // TODO how many of these should be conditional? if (rbyd_) { *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: // 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, - lfsr_btree_t *btree, bool shrub, +static int lfsr_btree_commit_(lfs_t *lfs, lfsr_btree_t *btree, const lfsr_attr_t **attrs_, lfs_size_t *attr_count_, lfsr_attr_t attrs__[static 4], 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_srid_t rid = -1; // 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 // higher-level btree/bshrub logic - if (rbyd.trunk == 0 || shrub) { + if (!lfsr_rbyd_hastrunk(&rbyd) + || lfsr_rbyd_isshrub(btree)) { *attrs_ = attrs; *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 @@ -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 if (!lfsr_rbyd_isfetched(&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) { return err; } @@ -4051,7 +4069,7 @@ static int lfsr_btree_commit_(lfs_t *lfs, finalize:; // done? - if (parent.trunk == 0) { + if (!lfsr_rbyd_hastrunk(&parent)) { LFS_ASSERT(bid == 0); *btree = rbyd_; *attr_count_ = 0; @@ -4109,7 +4127,7 @@ static int lfsr_btree_commit_(lfs_t *lfs, lfsr_rbyd_t sibling; if ((lfs_size_t)estimate <= lfs->cfg->block_size/4 // no parent? can't merge - && parent.trunk != 0) { + && !lfsr_rbyd_hastrunk(&parent)) { // try the right sibling if (rid+1 < parent.weight) { // try looking up the sibling @@ -4344,7 +4362,7 @@ static int lfsr_btree_commit_(lfs_t *lfs, attr_count = 0; buf_size = 0; // new root? - if (parent.trunk == 0) { + if (!lfsr_rbyd_hastrunk(&parent)) { attrs__[attr_count++] = LFSR_ATTR(0, BRANCH, +rbyd_.weight, FROMBRANCH(&rbyd_, &buf__[buf_size])); @@ -4393,21 +4411,19 @@ static int lfsr_btree_commit_(lfs_t *lfs, } // merge the siblings together - err = lfsr_rbyd_appendcompactrbyd(lfs, &rbyd_, false, - -1, -1, &rbyd); + err = lfsr_rbyd_appendcompactrbyd(lfs, &rbyd_, -1, -1, &rbyd); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); return err; } - err = lfsr_rbyd_appendcompactrbyd(lfs, &rbyd_, false, - -1, -1, &sibling); + err = lfsr_rbyd_appendcompactrbyd(lfs, &rbyd_, -1, -1, &sibling); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); return err; } - err = lfsr_rbyd_appendcompaction(lfs, &rbyd_, false, 0); + err = lfsr_rbyd_appendcompaction(lfs, &rbyd_, 0); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); 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 // and is the root degenerate? - LFS_ASSERT(parent.trunk != 0); + LFS_ASSERT(lfsr_rbyd_hastrunk(&parent) != 0); if (rbyd.weight+sibling.weight == btree->weight) { // collapse the root, decreasing the height of the tree *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]; // 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__, buffer); if (err && err != LFS_ERR_RANGE) { @@ -4493,7 +4509,7 @@ static int lfsr_btree_commit(lfs_t *lfs, lfsr_btree_t *btree, *btree = rbyd; } - LFS_ASSERT(btree->trunk != 0); + LFS_ASSERT(lfsr_rbyd_hastrunk(btree)); return 0; } @@ -4582,16 +4598,15 @@ typedef struct lfsr_btraversal { .branch.trunk=0, \ .branch.weight=0}) -static int lfsr_btree_traverse_(lfs_t *lfs, - const lfsr_btree_t *btree, bool shrub, +static int lfsr_btree_traverse_(lfs_t *lfs, const lfsr_btree_t *btree, lfsr_btraversal_t *btraversal, lfsr_bid_t *bid_, lfsr_tinfo_t *tinfo_) { // explicitly traverse the root even if weight=0 if (btraversal->branch.trunk == 0 // unless we don't even have a root yet - && btree->trunk != 0 + && lfsr_rbyd_trunk(btree) != 0 // or are a shrub - && !shrub) { + && !lfsr_rbyd_isshrub(btree)) { btraversal->rid = btraversal->bid; 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, lfsr_btraversal_t *btraversal, lfsr_bid_t *bid_, lfsr_tinfo_t *tinfo_) { - return lfsr_btree_traverse_(lfs, btree, false, - btraversal, + return lfsr_btree_traverse_(lfs, btree, btraversal, bid_, tinfo_); } @@ -4784,6 +4798,14 @@ static int lfsr_sprout_compact(lfs_t *lfs, const lfsr_rbyd_t *rbyd_, // 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) { 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, uint8_t buffer[static LFSR_SHRUB_DSIZE]) { // shrub trunks should never be null - LFS_ASSERT(shrub->trunk != 0); + LFS_ASSERT(lfsr_shrub_trunk(shrub) != 0); lfs_ssize_t d = 0; // 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); d += d_; - d_ = lfs_toleb128(shrub->trunk, &buffer[d], 5); + d_ = lfs_toleb128(lfsr_shrub_trunk(shrub), &buffer[d], 5); LFS_ASSERT(d_ >= 0); d += d_; @@ -4833,13 +4855,15 @@ static int lfsr_data_readshrub(lfs_t *lfs, lfsr_data_t *data, return err; } - err = lfsr_data_readleb128(lfs, data, (int32_t*)&shrub->trunk); + err = lfsr_data_readleb128(lfs, data, &shrub->trunk); if (err) { return err; } - // 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; } @@ -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_, lfsr_shrub_t *shrub_, const lfsr_shrub_t *shrub) { // save our current trunk/weight - lfs_size_t trunk = rbyd_->trunk; + lfs_ssize_t trunk = rbyd_->trunk; lfsr_srid_t weight = rbyd_->weight; // compact our bshrub @@ -4919,21 +4943,16 @@ static int lfsr_shrub_commit(lfs_t *lfs, lfsr_rbyd_t *rbyd_, // things up too much // // 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; rbyd_->trunk = shrub->trunk; rbyd_->weight = shrub->weight; // append any bshrub attributes - for (lfs_size_t j = 0; j < attr_count; j++) { - int err = lfsr_rbyd_appendattr(lfs, rbyd_, - attrs[j].rid, - LFSR_TAG_SHRUB | attrs[j].tag, - attrs[j].delta, - attrs[j].data); - if (err) { - return err; - } + int err = lfsr_rbyd_appendattrs(lfs, rbyd_, -1, -1, + attrs, attr_count); + if (err) { + return err; } // 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 if (attrs[i].tag == LFSR_TAG_SHRUBALLOC) { bshrubcommit->shrub->blocks[0] = rbyd_.blocks[0]; - bshrubcommit->shrub->trunk = 0; + bshrubcommit->shrub->trunk = LFSR_RBYD_SHRUB | 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) { LFS_ASSERT(err != LFS_ERR_RANGE); 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) { LFS_ASSERT(err != LFS_ERR_RANGE); return err; @@ -8037,7 +8056,7 @@ int lfsr_mount(lfs_t *lfs, const struct lfs_config *cfg) { lfs->cfg->block_count, lfs->mroot.rbyd.blocks[0], lfs->mroot.rbyd.blocks[1], - lfs->mroot.rbyd.trunk, + lfsr_rbyd_trunk(&lfs->mroot.rbyd), lfsr_mtree_weight(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)) { int err = lfsr_btree_traverse_(lfs, lfsr_shrub_rbyd(&file->bshrub.u.bshrub), - lfsr_bshrub_isbshrub(&file->m.mdir, &file->bshrub), btraversal, bid_, tinfo_); if (err) { @@ -9713,7 +9731,6 @@ static int lfsr_bshrub_commit(lfs_t *lfs, lfsr_file_t *file, // try to commit to the btree int err = lfsr_btree_commit_(lfs, &file->bshrub.u.btree, - lfsr_bshrub_isbshrub(&file->m.mdir, &file->bshrub), &attrs, &attr_count, attrs__, buffer); if (err && err != LFS_ERR_RANGE) { @@ -9803,7 +9820,7 @@ static int lfsr_bshrub_commit(lfs_t *lfs, lfsr_file_t *file, return 0; } - LFS_ASSERT(file->bshrub.u.bshrub.trunk != 0); + LFS_ASSERT(lfsr_shrub_hastrunk(&file->bshrub.u.bshrub)); return 0; 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.trunk = 0; + file->bshrub.u.bshrub.trunk = LFSR_RBYD_SHRUB | 0; file->bshrub.u.bshrub.weight = 0; // force estimate recalculation file->bshrub.u.bshrub.estimate = -1; diff --git a/lfs.h b/lfs.h index 28cfe233..f5216622 100644 --- a/lfs.h +++ b/lfs.h @@ -339,12 +339,15 @@ typedef struct lfs_cache { // TODO do we get ram savings with a lfsr_rorbyd_t substruct? need to measure typedef struct lfsr_rbyd { // note this lines up with weight in lfsr_btree_t + // sign(weight)=0 => rbyd lfsr_srid_t weight; 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 fetched // eoff>=block_size => rbyd not erased/needs compaction - lfs_size_t trunk; + lfs_ssize_t trunk; lfs_size_t eoff; uint32_t cksum; } lfsr_rbyd_t; @@ -493,7 +496,7 @@ typedef struct lfsr_shrub { // this all lines up with lfsr_rbyd_t lfsr_srid_t weight; lfs_block_t blocks[2]; - lfs_size_t trunk; + lfs_ssize_t trunk; lfs_size_t eoff; // an upper-bound estimate on the on-disk shrub size lfs_size_t estimate; diff --git a/scripts/dbgbmap.py b/scripts/dbgbmap.py index 4762235c..a41ade65 100755 --- a/scripts/dbgbmap.py +++ b/scripts/dbgbmap.py @@ -696,6 +696,7 @@ class Rbyd: # keep track of eoff for best matching trunk if trunk and j_ + size > trunk: trunkeoff = j_ + size + eoff = trunkeoff cksum = cksum_ trunk_ = trunk__ weight = weight_ diff --git a/scripts/dbgbtree.py b/scripts/dbgbtree.py index e594d25f..8c3648bd 100755 --- a/scripts/dbgbtree.py +++ b/scripts/dbgbtree.py @@ -363,6 +363,7 @@ class Rbyd: # keep track of eoff for best matching trunk if trunk and j_ + size > trunk: trunkeoff = j_ + size + eoff = trunkeoff cksum = cksum_ trunk_ = trunk__ weight = weight_ diff --git a/scripts/dbglfs.py b/scripts/dbglfs.py index 46bc65ff..dd351f25 100755 --- a/scripts/dbglfs.py +++ b/scripts/dbglfs.py @@ -394,6 +394,7 @@ class Rbyd: # keep track of eoff for best matching trunk if trunk and j_ + size > trunk: trunkeoff = j_ + size + eoff = trunkeoff cksum = cksum_ trunk_ = trunk__ weight = weight_ diff --git a/scripts/dbgmtree.py b/scripts/dbgmtree.py index 5abe2cde..4f7333c0 100755 --- a/scripts/dbgmtree.py +++ b/scripts/dbgmtree.py @@ -378,6 +378,7 @@ class Rbyd: # keep track of eoff for best matching trunk if trunk and j_ + size > trunk: trunkeoff = j_ + size + eoff = trunkeoff cksum = cksum_ trunk_ = trunk__ weight = weight_