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_