From a9b81820b022eb3fad094ddc0d34e20c8af75050 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Wed, 30 Aug 2023 14:56:54 -0500 Subject: [PATCH] Adopted rid-bound-dependent compressed mids. This adopts a previously discarded idea for compressed mids with a few tweaks to avoiding decoding the bid/rid portions as much as possible. The idea of compressed mids is to shove both the mid bid and mid rid into a single integer, saving RAM and potentially helping filesystem integration where a unique per-file integer is useful. Unfortunately this has proven tricky. littlefs fundamentally needs two ids, one "bid" to lookup which mdir our entry resides on, and one "rid" to lookup the entry in the mdir. It's tempting to use two half-sized integers (16-bit for example), but this risks surprising limitations around the number of files when blocks are either really large or really small. Optimally, we'd limit the number of bits reserved for the rid to the upper bound of number of rids that can fit in a single mdir. This would allows for more bids when the block size is small, and more rids when the block size is large. This should roughly approximate the limits of a per-file integer. With a bit of math we can estimate the upper bound to be <=block_size/16 with our current compaction strategy. This idea was previously discarded due to the overhead of extracting the bids/rids when we need them, but the RAM savings and file-to-integer mapping is too useful to give up. When it became clear half-width integers wasn't really going to work, compressed mids became the new plan: 0bbbbbbb bbbbbbbb bbbbbbbb rrrrrrrr ^'-----------+-----------' '---+--' '------------|-----------------|---- sign-bit, reserved for driver | '---- nlog2(bs/16) bits for rid | (8-bits for 4KiB blocks) '---------------------- remaining bits for bid (23-bits for 4KiB blocks) To reduce the overhead of encoding/decode bids/rids a few extra features were added to the internal mdir APIs: 1. The mtree has been changed to store mids directly. Giving each mdir the upper bound as a weight. This allows direct lookup of mids without any sort of bid decoding, though does bake the upper bound estimate into the metadata of the filesystem, which isn't the cleanest design, but if it works it works. On the plus side, with this upper bound baked in to the filesystems, GRMs can be encoded in a single leb128, which is nice. This may have other savings if we ever store mids anywhere else in the filesystem. 2. rids are now mid relative in lfsr_mdir_lookup when non-negative. This is implemented with a simple condition that is hopefully optimized out when inlined, though there may be some room for improvement here. 3. rids are now mid relative in lfsr_mdir_commit. This was a bit tricky, but we can leverage the existing mechanisms for bid-relative rids used in the btree implementation. The above changes make it so you can pass the mid around directly for most of the mdir functions, hopefully reducing the mid decoding overhead. This savings should only grow as more high-level filesystem APIs are added. Here is the resulting code/RAM changes for this entire change (from before we adopted the mroot bit): code stack structs before: 20590 1784 908 after: 20890 (+1.4%) 1744 (-2.3%) 864 (-5.1%) --- lfs.c | 400 ++++++++++---------- lfs.h | 14 +- tests/test_alloc.toml | 23 +- tests/test_mtree.toml | 853 +++++++++++++++++++++--------------------- 4 files changed, 640 insertions(+), 650 deletions(-) diff --git a/lfs.c b/lfs.c index e61bcd85..09e4dd45 100644 --- a/lfs.c +++ b/lfs.c @@ -1548,20 +1548,9 @@ static inline lfs_ssize_t lfsr_mbidmask(lfs_t *lfs) { return ~lfsr_mridmask(lfs); } -#define LFSR_MID(_bid, _rid) ((lfsr_mid_t){.bid=_bid, .rid=_rid}) - -static inline int lfsr_mid_cmp(lfsr_mid_t a, lfsr_mid_t b) { - if (a.bid != b.bid) { - return a.bid - b.bid; - } - - return a.rid - b.rid; -} - // we use the root's bookmark at 0.0 to represent root -// TODO does this not catch -0.0? -static inline bool lfsr_mid_isroot(lfsr_mid_t mid) { - return lfsr_mid_cmp(mid, LFSR_MID(0, 0)) == 0; +static inline bool lfsr_mid_isroot(lfs_ssize_t mid) { + return mid == 0; } static inline bool lfsr_mdir_isroot(const lfsr_mdir_t *mdir) { @@ -1621,22 +1610,22 @@ static int lfsr_gdelta_xor(lfs_t *lfs, // GRM (global remove) things static inline bool lfsr_grm_hasrm(const lfsr_grm_t *grm) { - return grm->rms[0].bid != -1; + return grm->rms[0] != -1; } static inline uint8_t lfsr_grm_count(const lfsr_grm_t *grm) { - return (grm->rms[0].bid != -1) + (grm->rms[1].bid != -1); + return (grm->rms[0] != -1) + (grm->rms[1] != -1); } -static inline void lfsr_grm_pushrm(lfsr_grm_t *grm, lfsr_mid_t mid) { - LFS_ASSERT(grm->rms[1].bid == -1); +static inline void lfsr_grm_pushrm(lfsr_grm_t *grm, lfs_ssize_t mid) { + LFS_ASSERT(grm->rms[1] == -1); grm->rms[1] = grm->rms[0]; grm->rms[0] = mid; } static inline void lfsr_grm_poprm(lfsr_grm_t *grm) { grm->rms[0] = grm->rms[1]; - grm->rms[1] = LFSR_MID(-1, -1); + grm->rms[1] = -1; } static int lfsr_grm_todisk(lfs_t *lfs, const lfsr_grm_t *grm, @@ -1654,13 +1643,7 @@ static int lfsr_grm_todisk(lfs_t *lfs, const lfsr_grm_t *grm, d += 1; for (uint8_t i = 0; i < count; i++) { - lfs_ssize_t d_ = lfs_toleb128(grm->rms[i].bid, &buffer[d], 5); - if (d_ < 0) { - return d_; - } - d += d_; - - d_ = lfs_toleb128(grm->rms[i].rid, &buffer[d], 5); + lfs_ssize_t d_ = lfs_toleb128(grm->rms[i], &buffer[d], 5); if (d_ < 0) { return d_; } @@ -1676,6 +1659,10 @@ static inline lfs_size_t lfsr_mtree_weight(lfs_t *lfs); static int lfsr_data_readgrm(lfs_t *lfs, lfsr_data_t *data, lfsr_grm_t *grm) { + // clear first + grm->rms[0] = -1; + grm->rms[1] = -1; + // get the count from the first byte uint8_t count; lfs_ssize_t d = lfsr_data_read(lfs, data, &count, 1); @@ -1683,27 +1670,15 @@ static int lfsr_data_readgrm(lfs_t *lfs, lfsr_data_t *data, return d; } - // clear first - grm->rms[0] = LFSR_MID(-1, -1); - grm->rms[1] = LFSR_MID(-1, -1); - LFS_ASSERT(count <= 2); for (uint8_t i = 0; i < count; i++) { - lfs_ssize_t bid; - int err = lfsr_data_readleb128(lfs, data, &bid); + int err = lfsr_data_readleb128(lfs, data, &grm->rms[i]); if (err) { return err; } - lfs_ssize_t rid; - err = lfsr_data_readleb128(lfs, data, &rid); - if (err) { - return err; - } - - // adjust mid if mtree is inlined - LFS_ASSERT(bid < lfs_smax32(lfsr_mtree_weight(lfs), 1)); - grm->rms[i] = LFSR_MID(bid, rid); + LFS_ASSERT(grm->rms[i] + < lfs_smax32(lfsr_mtree_weight(lfs), lfsr_mbidweight(lfs))); } return 0; @@ -2890,13 +2865,17 @@ static int lfsr_rbyd_appendattrs(lfs_t *lfs, lfsr_rbyd_t *rbyd, continue; } + // calculate adjusted rid + lfs_ssize_t rid = (attrs[i].rid == -1 + ? -1 + : (lfs_ssize_t)(attrs[i].rid - bid)); + // don't write tags outside of the requested range - if (lfs_smax32(attrs[i].rid - bid, -1) >= start_rid + if (rid >= start_rid // note the use of rid+1 and unsigned comparison here to // treat end_rid=-1 as "unbounded" in such a way that rid=-1 // is still included - && (lfs_size_t)lfs_smax32(attrs[i].rid - bid, -1) + 1 - <= (lfs_size_t)end_rid) { + && (lfs_size_t)(rid + 1) <= (lfs_size_t)end_rid) { // this is a bit of a hack, but ignore any gstate tags here, // these need to be handled specially by upper-layers if (lfsr_tag_suptype(attrs[i].tag) == LFSR_TAG_GSTATE) { @@ -2912,23 +2891,22 @@ static int lfsr_rbyd_appendattrs(lfs_t *lfs, lfsr_rbyd_t *rbyd, // skip the name tag, this is always replaced by upper layers lfsr_tag_t tag = LFSR_TAG_NAME + 0xff; while (true) { - lfs_ssize_t rid; + lfs_ssize_t rid_; lfsr_data_t data; - int err = lfsr_rbyd_lookupnext(lfs, - &mdir->u.r.rbyd, mdir->mid.rid, lfsr_tag_next(tag), - &rid, &tag, NULL, &data); + int err = lfsr_rbyd_lookupnext(lfs, &mdir->u.r.rbyd, + mdir->mid & lfsr_mridmask(lfs), lfsr_tag_next(tag), + &rid_, &tag, NULL, &data); if (err && err != LFS_ERR_NOENT) { return err; } - if (err == LFS_ERR_NOENT || rid != mdir->mid.rid) { + if (err == LFS_ERR_NOENT + || rid_ != (mdir->mid & lfsr_mridmask(lfs))) { break; } // append the attr err = lfsr_rbyd_append(lfs, rbyd, - lfs_smax32( - attrs[i].rid - bid - lfs_smax32(start_rid, 0), - -1), + rid - lfs_smax32(start_rid, 0), tag, 0, data); if (err) { return err; @@ -2940,9 +2918,7 @@ static int lfsr_rbyd_appendattrs(lfs_t *lfs, lfsr_rbyd_t *rbyd, LFS_ASSERT(!lfsr_tag_isinternal(attrs[i].tag)); int err = lfsr_rbyd_append(lfs, rbyd, - lfs_smax32( - attrs[i].rid - bid - lfs_smax32(start_rid, 0), - -1), + rid - lfs_smax32(start_rid, 0), attrs[i].tag, attrs[i].delta, attrs[i].data); if (err) { return err; @@ -2952,10 +2928,10 @@ static int lfsr_rbyd_appendattrs(lfs_t *lfs, lfsr_rbyd_t *rbyd, // we need to make sure we keep start_rid/end_rid updated with // weight changes - if (lfs_smax32(attrs[i].rid - bid, -1) < start_rid) { + if (rid < start_rid) { start_rid += attrs[i].delta; } - if (lfs_smax32(attrs[i].rid - bid, -1) < end_rid) { + if (rid < end_rid) { end_rid += attrs[i].delta; } } @@ -4691,7 +4667,7 @@ static bool lfsr_mdir_isopened(lfs_t *lfs, // actual mdir functions static int lfsr_mdir_fetch(lfs_t *lfs, lfsr_mdir_t *mdir, - const lfs_block_t blocks[static 2], lfsr_mid_t mid) { + const lfs_block_t blocks[static 2], lfs_ssize_t mid) { // create a copy of blocks, this is so we can swap the blocks // to keep track of the current revision, this also prevents issues // if blocks points to the blocks in the mdir @@ -4740,7 +4716,13 @@ static int lfsr_mdir_fetch(lfs_t *lfs, lfsr_mdir_t *mdir, static int lfsr_mdir_lookup(lfs_t *lfs, const lfsr_mdir_t *mdir, lfs_ssize_t rid, lfsr_tag_t tag, lfsr_tag_t *tag_, lfsr_data_t *data_) { - return lfsr_rbyd_lookup(lfs, &mdir->u.r.rbyd, rid, tag, tag_, data_); + return lfsr_rbyd_lookup(lfs, &mdir->u.r.rbyd, + // TODO anything better? + (rid == -1 + ? -1 + : rid - (lfs_smax32(mdir->mid, 0) & lfsr_mbidmask(lfs))), + tag, + tag_, data_); } @@ -4783,27 +4765,28 @@ static inline lfs_size_t lfsr_mtree_weight(lfs_t *lfs) { return lfsr_btree_weight(&lfs->mtree); } -static int lfsr_mtree_lookup(lfs_t *lfs, lfsr_mid_t mid, lfsr_mdir_t *mdir_) { +static int lfsr_mtree_lookup(lfs_t *lfs, lfs_ssize_t mid, lfsr_mdir_t *mdir_) { // looking up mroot? if (lfsr_mtree_isinlined(lfs)) { - LFS_ASSERT(mid.bid == 0); + LFS_ASSERT(mid >= 0); + LFS_ASSERT(mid < (lfs_ssize_t)lfsr_mbidweight(lfs)); mdir_->mid = mid; mdir_->u.m = lfs->mroot.u.m; return 0; // look up mdir in actual mtree } else { - LFS_ASSERT(mid.bid >= 0); - LFS_ASSERT(mid.bid < (lfs_ssize_t)lfsr_mtree_weight(lfs)); + LFS_ASSERT(mid >= 0); + LFS_ASSERT(mid < (lfs_ssize_t)lfsr_mtree_weight(lfs)); lfs_size_t bid; lfsr_tag_t tag; lfsr_data_t data; - int err = lfsr_btree_lookupnext(lfs, &lfs->mtree, mid.bid, + int err = lfsr_btree_lookupnext(lfs, &lfs->mtree, mid, &bid, &tag, NULL, &data); if (err) { return err; } - LFS_ASSERT(bid == (mid.bid | lfsr_mridmask(lfs))); + LFS_ASSERT((lfs_ssize_t)bid == (mid | lfsr_mridmask(lfs))); LFS_ASSERT(tag == LFSR_TAG_MDIR); // decode mdir @@ -4831,7 +4814,7 @@ static int lfsr_mtree_parent(lfs_t *lfs, const lfs_block_t blocks[static 2], while (true) { // fetch next possible superblock lfsr_mdir_t mdir; - int err = lfsr_mdir_fetch(lfs, &mdir, blocks_, LFSR_MID(-1, -1)); + int err = lfsr_mdir_fetch(lfs, &mdir, blocks_, -1); if (err) { return err; } @@ -4859,29 +4842,29 @@ static int lfsr_mtree_parent(lfs_t *lfs, const lfs_block_t blocks[static 2], } static int lfsr_mtree_seek(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_off_t off) { - // calculate new rid - lfs_ssize_t rid_ = mdir->mid.rid + off; + // calculate new mid, be careful to avoid rid overflow + lfs_size_t bid = mdir->mid & lfsr_mbidmask(lfs); + lfs_size_t rid = (mdir->mid & lfsr_mridmask(lfs)) + off; // lookup mdirs until we find our rid, we need to do this because // we don't know how many rids are in each mdir until we fetch - while (rid_ >= (lfs_ssize_t)mdir->u.m.weight) { - lfsr_smbid_t bid_ = mdir->mid.bid + lfsr_mbidweight(lfs); + while (rid >= mdir->u.m.weight) { // end of mtree? - if (bid_ >= (lfs_ssize_t)lfsr_mtree_weight(lfs)) { - // TODO is this needed? - // make sure to update rid even if we error so seek will always - // return noent after the first noent - mdir->mid.rid = rid_; + if (bid+lfsr_mbidweight(lfs) >= lfsr_mtree_weight(lfs)) { + // if we hit the end of the mtree, park the mdir so all future + // seeks return noent + mdir->mid = bid + mdir->u.m.weight; return LFS_ERR_NOENT; } - rid_ -= mdir->u.m.weight; - int err = lfsr_mtree_lookup(lfs, LFSR_MID(bid_, rid_), mdir); + bid += lfsr_mbidweight(lfs); + rid -= mdir->u.m.weight; + int err = lfsr_mtree_lookup(lfs, bid, mdir); if (err) { return err; } } - mdir->mid.rid = rid_; + mdir->mid = bid + rid; return 0; } @@ -4890,6 +4873,7 @@ static int lfsr_mtree_seek(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_off_t off) { // - reason = compacting => only alloc if mdir is tired (wear-leveling) // - reason = extending => never alloc (mroot anchor) // - reason >= 0 => always alloc, use this as the new mid (new mdir) +// TODO make this -2/-3 or something enum { LFSR_MDIR_COMPACTING = -3, LFSR_MDIR_EXTENDING = -4, @@ -4918,7 +4902,7 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_, // TODO rev things && (rev + 1) % lfs->cfg->block_cycles == 0))) { // assign the new mid - mdir_->mid = LFSR_MID((reason >= 0 ? reason : mdir->mid.bid), -1); + mdir_->mid = (reason >= 0 ? reason : mdir->mid); // allocate two blocks for (int i = 0; i < 2; i++) { @@ -4992,7 +4976,8 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_, // // upper layers should make sure this can't fail by limiting the // maximum commit size - err = lfsr_rbyd_appendattrs(lfs, &mdir_->u.r.rbyd, 0, start_rid, end_rid, + err = lfsr_rbyd_appendattrs(lfs, &mdir_->u.r.rbyd, + lfs_smax32(mdir_->mid, 0) & lfsr_mbidmask(lfs), start_rid, end_rid, attr1s, attr1_count); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); @@ -5001,7 +4986,8 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_, // note we don't filter attrs from our second pending list, this // is used for some auxiliary attrs in lfsr_mdir_commit - err = lfsr_rbyd_appendattrs(lfs, &mdir_->u.r.rbyd, 0, -1, -1, + err = lfsr_rbyd_appendattrs(lfs, &mdir_->u.r.rbyd, + lfs_smax32(mdir_->mid, 0) & lfsr_mbidmask(lfs), -1, -1, attr2s, attr2_count); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); @@ -5012,7 +4998,7 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_, // drop commit if weight goes to zero if (mdir_->u.m.weight == 0 // unless we are an mroot - && !(mdir_->mid.bid == -1 + && !(mdir_->mid == -1 || (lfsr_mtree_isinlined(lfs) && reason == LFSR_MDIR_COMPACTING))) { // TODO should we just make our pcache not assert? @@ -5027,7 +5013,7 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_, // this pushes gstate up into the mroot when relocating, and // helps avoid corner case issues when splitting/dropping bool flushinggdelta = false; - if (mdir_->mid.bid == -1 + if (mdir_->mid == -1 || (lfsr_mtree_isinlined(lfs) && reason == LFSR_MDIR_COMPACTING) || lfsr_mdir_cmp(mdir_->u.m.blocks, mdir->u.m.blocks) == 0) { @@ -5072,7 +5058,8 @@ static int lfsr_mdir_commit_(lfs_t *lfs, lfsr_mdir_t *mdir, // TODO let the lower rbyd layer handle this somehow? // mark mdir as unerased in case we fail mdir->u.r.rbyd.eoff = lfs->cfg->block_size; - int err = lfsr_rbyd_appendattrs(lfs, &mdir_.u.r.rbyd, 0, start_rid, end_rid, + int err = lfsr_rbyd_appendattrs(lfs, &mdir_.u.r.rbyd, + lfs_smax32(mdir_.mid, 0) & lfsr_mbidmask(lfs), start_rid, end_rid, attrs, attr_count); if (err && err != LFS_ERR_RANGE) { return err; @@ -5084,7 +5071,7 @@ static int lfsr_mdir_commit_(lfs_t *lfs, lfsr_mdir_t *mdir, // drop commit if weight goes to zero if (mdir_.u.m.weight == 0 // unless we are an mroot - && !(mdir_.mid.bid == -1 || lfsr_mtree_isinlined(lfs))) { + && !(mdir_.mid == -1 || lfsr_mtree_isinlined(lfs))) { // TODO move this up into lfsr_mdir_commit? // consume gstate so we don't lose any info int err = lfsr_fs_consumegdelta(lfs, mdir); @@ -5160,9 +5147,12 @@ compact:; static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, const lfsr_attr_t *attrs, lfs_size_t attr_count) { LFS_ASSERT(!lfsr_mdir_isdropped(mdir)); - LFS_ASSERT(mdir->mid.bid == -1 + LFS_ASSERT(mdir->mid == -1 || lfsr_mtree_isinlined(lfs) || mdir->u.m.weight > 0); + LFS_ASSERT(mdir->mid == -1 + || (lfs_size_t)(mdir->mid & lfsr_mridmask(lfs)) + <= mdir->u.m.weight); // parse out any pending gstate, these will get automatically xored // with on-disk gdeltas in lower-level functions @@ -5202,7 +5192,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // // TODO wait, do we need to update lfs->mroot and mdir eagerly // for the same reason? - lfsr_mdir_t mroot_ = (mdir->mid.bid == -1 || lfsr_mtree_isinlined(lfs) + lfsr_mdir_t mroot_ = (mdir->mid == -1 || lfsr_mtree_isinlined(lfs) ? mdir_ : lfs->mroot); lfsr_mdir_t msibling_ = {.u.r.rbyd.trunk=0}; @@ -5213,7 +5203,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // need to split? if (err == LFS_ERR_RANGE) { // this should not happen unless we can't fit our mroot's metadata - LFS_ASSERT(lfsr_mtree_isinlined(lfs) || mdir->mid.bid != -1); + LFS_ASSERT(lfsr_mtree_isinlined(lfs) || mdir->mid != -1); // if we're the mroot, create a new mtree, assume the upper layers // will take care of grafting our mtree into the mroot as needed if (lfsr_mtree_isinlined(lfs)) { @@ -5242,7 +5232,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // compact into new mdir tags < split_rid int err = lfsr_mdir_compact_(lfs, &mdir_, - lfs_smax32(mdir->mid.bid, 0), 0, split_rid, + lfs_smax32(mdir->mid, 0), 0, split_rid, mdir, attrs, attr_count, NULL, 0); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); @@ -5251,17 +5241,17 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // compact into new mdir tags >= split_rid err = lfsr_mdir_compact_(lfs, &msibling_, - lfs_smax32(mdir->mid.bid, 0), split_rid, -1, + lfs_smax32(mdir->mid, 0), split_rid, -1, mdir, attrs, attr_count, NULL, 0); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); return err; } - LFS_DEBUG("Splitting mdir %"PRId16" 0x{%"PRIx32",%"PRIx32"} " + LFS_DEBUG("Splitting mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"} " "-> 0x{%"PRIx32",%"PRIx32"}" ", 0x{%"PRIx32",%"PRIx32"}", - mdir->mid.bid, + mdir->mid, mdir->u.m.blocks[0], mdir->u.m.blocks[1], mdir_.u.m.blocks[0], mdir_.u.m.blocks[1], msibling_.u.m.blocks[0], msibling_.u.m.blocks[1]); @@ -5271,11 +5261,11 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // both siblings reduced to zero if (mdir_.u.m.weight == 0 && msibling_.u.m.weight == 0) { - LFS_DEBUG("Dropping mdir %"PRId16" 0x{%"PRIx32",%"PRIx32"}", - mdir_.mid.bid, + LFS_DEBUG("Dropping mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"}", + mdir_.mid, mdir_.u.m.blocks[0], mdir_.u.m.blocks[1]); - LFS_DEBUG("Dropping mdir %"PRId16" 0x{%"PRIx32",%"PRIx32"}", - msibling_.mid.bid, + LFS_DEBUG("Dropping mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"}", + msibling_.mid, msibling_.u.m.blocks[0], msibling_.u.m.blocks[1]); // mark as dropped mdir_.u.r.rbyd.trunk = 0; @@ -5283,7 +5273,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // update our mtree int err = lfsr_btree_commit(lfs, &mtree_, LFSR_ATTRS( - LFSR_ATTR(mdir_.mid.bid | lfsr_mridmask(lfs), + LFSR_ATTR(mdir_.mid | lfsr_mridmask(lfs), RM, -lfsr_mbidweight(lfs), NULL))); if (err) { return err; @@ -5291,8 +5281,8 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // one sibling reduced to zero } else if (msibling_.u.m.weight == 0) { - LFS_DEBUG("Dropping mdir %"PRId16" 0x{%"PRIx32",%"PRIx32"}", - msibling_.mid.bid, + LFS_DEBUG("Dropping mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"}", + msibling_.mid, msibling_.u.m.blocks[0], msibling_.u.m.blocks[1]); // mark as dropped @@ -5307,7 +5297,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, } int err = lfsr_btree_commit(lfs, &mtree_, LFSR_ATTRS( - LFSR_ATTR(mdir_.mid.bid | lfsr_mridmask(lfs), + LFSR_ATTR(mdir_.mid | lfsr_mridmask(lfs), MDIR, 0, BUF(mdir_buf, mdir_dsize)))); if (err) { return err; @@ -5315,8 +5305,8 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // other sibling reduced to zero } else if (mdir_.u.m.weight == 0) { - LFS_DEBUG("Dropping mdir %"PRId16" 0x{%"PRIx32",%"PRIx32"}", - mdir_.mid.bid, + LFS_DEBUG("Dropping mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"}", + mdir_.mid, mdir_.u.m.blocks[0], mdir_.u.m.blocks[1]); // mark as dropped @@ -5331,7 +5321,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, } int err = lfsr_btree_commit(lfs, &mtree_, LFSR_ATTRS( - LFSR_ATTR(msibling_.mid.bid | lfsr_mridmask(lfs), + LFSR_ATTR(msibling_.mid | lfsr_mridmask(lfs), MDIR, 0, BUF(msibling_buf, msibling_dsize)))); if (err) { return err; @@ -5341,7 +5331,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, } else { // adjust our sibling's mid, do this here in case other sibling // was dropped - msibling_.mid.bid += lfsr_mbidweight(lfs); + msibling_.mid += lfsr_mbidweight(lfs); // update out mtree @@ -5350,7 +5340,8 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // note we need to do this after playing out pending attrs in // case they introduce a new name! lfsr_data_t split_data; - int err = lfsr_mdir_lookup(lfs, &msibling_, 0, LFSR_TAG_WIDE(NAME), + int err = lfsr_mdir_lookup(lfs, &msibling_, + msibling_.mid & lfsr_mbidmask(lfs), LFSR_TAG_WIDE(NAME), NULL, &split_data); if (err) { LFS_ASSERT(err != LFS_ERR_NOENT); @@ -5371,11 +5362,11 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, } err = lfsr_btree_commit(lfs, &mtree_, LFSR_ATTRS( - LFSR_ATTR(mdir_.mid.bid | lfsr_mridmask(lfs), + LFSR_ATTR(mdir_.mid | lfsr_mridmask(lfs), MDIR, 0, BUF(mdir_buf, mdir_dsize)), - LFSR_ATTR((mdir_.mid.bid | lfsr_mridmask(lfs))+1, + LFSR_ATTR((mdir_.mid | lfsr_mridmask(lfs))+1, BRANCH, +lfsr_mbidweight(lfs), DATA(split_data)), - LFSR_ATTR(msibling_.mid.bid | lfsr_mridmask(lfs), + LFSR_ATTR(msibling_.mid | lfsr_mridmask(lfs), MDIR, 0, BUF(msibling_buf, msibling_dsize)))); if (err) { return err; @@ -5387,9 +5378,9 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // mdir reduced to zero? need to drop? } else if (mdir_.u.m.weight == 0 // unless we are an mroot - && !(mdir->mid.bid == -1 || lfsr_mtree_isinlined(lfs))) { - LFS_DEBUG("Dropping mdir %"PRId16" 0x{%"PRIx32",%"PRIx32"}", - mdir->mid.bid, + && !(mdir->mid == -1 || lfsr_mtree_isinlined(lfs))) { + LFS_DEBUG("Dropping mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"}", + mdir->mid, mdir->u.m.blocks[0], mdir->u.m.blocks[1]); // mark as dropped @@ -5397,7 +5388,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // update our mtree int err = lfsr_btree_commit(lfs, &mtree_, LFSR_ATTRS( - LFSR_ATTR(mdir->mid.bid | lfsr_mridmask(lfs), + LFSR_ATTR(mdir->mid | lfsr_mridmask(lfs), RM, -lfsr_mbidweight(lfs), NULL))); if (err) { return err; @@ -5408,16 +5399,16 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // need to relocate? } else if (lfsr_mdir_cmp(mdir->u.m.blocks, mdir_.u.m.blocks) != 0) { // relocate mroot - if (mdir->mid.bid == -1 || lfsr_mtree_isinlined(lfs)) { + if (mdir->mid == -1 || lfsr_mtree_isinlined(lfs)) { // if we're relocating our root, just mark the root as dirty // and let our dirtymroot code handle this dirtymroot = true; // relocate a normal mdir } else { - LFS_DEBUG("Relocating mdir %"PRId16" 0x{%"PRIx32",%"PRIx32"} " + LFS_DEBUG("Relocating mdir %"PRId32" 0x{%"PRIx32",%"PRIx32"} " "-> 0x{%"PRIx32",%"PRIx32"}", - mdir->mid.bid, + mdir->mid, mdir->u.m.blocks[0], mdir->u.m.blocks[1], mdir_.u.m.blocks[0], mdir_.u.m.blocks[1]); @@ -5430,7 +5421,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, } int err = lfsr_btree_commit(lfs, &mtree_, LFSR_ATTRS( - LFSR_ATTR(mdir->mid.bid | lfsr_mridmask(lfs), + LFSR_ATTR(mdir->mid | lfsr_mridmask(lfs), MDIR, 0, BUF(mdir_buf, mdir_dsize)))); if (err) { return err; @@ -5468,18 +5459,20 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // fix our grm for (uint8_t j = 0; j < 2; j++) { - if (grm->rms[j].bid == lfs_smax32(mdir->mid.bid, 0)) { - LFS_ASSERT(grm->rms[j].rid + if ((grm->rms[j] & lfsr_mbidmask(lfs)) + == (lfs_smax32(mdir->mid, 0) & lfsr_mbidmask(lfs))) { + LFS_ASSERT((grm->rms[j] & lfsr_mridmask(lfs)) <= (lfs_ssize_t)mdir->u.m.weight); - if (grm->rms[j].rid >= (lfs_ssize_t)mdir_.u.m.weight) { - grm->rms[j].bid += lfsr_mbidweight(lfs); - grm->rms[j].rid -= mdir_.u.m.weight; + if ((grm->rms[j] & lfsr_mridmask(lfs)) + >= (lfs_ssize_t)mdir_.u.m.weight) { + grm->rms[j] += lfsr_mbidweight(lfs) + - mdir_.u.m.weight; } // update mid if we had a split or drop - } else if (grm->rms[j].bid > mdir->mid.bid + } else if (grm->rms[j] > mdir->mid && lfsr_btree_weight(&mtree_) != lfsr_mtree_weight(lfs)) { - grm->rms[j].bid += lfsr_btree_weight(&mtree_) + grm->rms[j] += lfsr_btree_weight(&mtree_) - lfsr_mtree_weight(lfs); } } @@ -5615,7 +5608,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfsr_mdir_t mparentroot = mchildroot; // make sure all non-inlined mroots have mid=-1 // TODO should we assign the mroot mid in lfsr_mdir_compact_? - mparentroot.mid = LFSR_MID(-1, -1); + mparentroot.mid = -1; err = lfsr_mdir_compact_(lfs, &mparentroot, LFSR_MDIR_EXTENDING, 0, 0, &mchildroot, NULL, 0, LFSR_ATTRS( LFSR_ATTR(-1, SUPERMAGIC, 0, DATA(magic)), @@ -5660,17 +5653,18 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // mdirs and normal dirs which are pairs of mdirs for (uint8_t j = 0; j <= type; j++) { lfsr_mdir_t *opened_mdir = &(&opened->mdir)[j]; - LFS_ASSERT(opened_mdir->mid.bid >= 0); + LFS_ASSERT(opened_mdir->mid >= 0); // first play out any attrs that change our rid for (lfs_size_t i = 0; i < attr_count; i++) { // TODO clean this up a bit? // adjust opened mdirs? - if (opened_mdir->mid.bid == lfs_smax32(mdir->mid.bid, 0) - && opened_mdir->mid.rid >= attrs[i].rid) { + if ((opened_mdir->mid & lfsr_mbidmask(lfs)) + == (lfs_smax32(mdir->mid, 0) + & lfsr_mbidmask(lfs)) + && (opened_mdir->mid >= attrs[i].rid)) { // removed? - if (opened_mdir->mid.rid - < attrs[i].rid - attrs[i].delta) { + if (opened_mdir->mid < attrs[i].rid - attrs[i].delta) { // normal mdirs mark as dropped if (j == 0) { opened_mdir->u.r.rbyd.trunk = 0; @@ -5678,9 +5672,9 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, } // for dir's second mdir (the position mdir), move // on to the next rid - opened_mdir->mid.rid = attrs[i].rid; + opened_mdir->mid = attrs[i].rid; } else { - opened_mdir->mid.rid += attrs[i].delta; + opened_mdir->mid += attrs[i].delta; // adjust dir position? if (type == LFS_TYPE_DIR && j == 0) { ((lfsr_dir_t*)opened)->pos -= attrs[i].delta; @@ -5688,7 +5682,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, ((lfsr_dir_t*)opened)->pos += attrs[i].delta; } } - } else if (opened_mdir->mid.bid > mdir->mid.bid) { + } else if (opened_mdir->mid > mdir->mid) { // adjust dir position? if (type == LFS_TYPE_DIR && j == 0) { ((lfsr_dir_t*)opened)->pos -= attrs[i].delta; @@ -5699,20 +5693,21 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, } // update any opened mdirs if we had a split or drop - if (opened_mdir->mid.bid == lfs_smax32(mdir->mid.bid, 0)) { + if ((opened_mdir->mid & lfsr_mbidmask(lfs)) + == (lfs_smax32(mdir->mid, 0) & lfsr_mbidmask(lfs))) { if (!lfsr_mdir_isdropped(&msibling_) - && opened_mdir->mid.rid + && (opened_mdir->mid & lfsr_mridmask(lfs)) >= (lfs_ssize_t)mdir_.u.m.weight) { LFS_ASSERT(lfsr_btree_weight(&mtree_) != lfsr_mtree_weight(lfs)); - opened_mdir->mid.bid += lfsr_mbidweight(lfs); - opened_mdir->mid.rid -= mdir_.u.m.weight; + opened_mdir->mid += lfsr_mbidweight(lfs) + - mdir_.u.m.weight; opened_mdir->u.m = msibling_.u.m; } else { opened_mdir->u.m = mdir_.u.m; } - } else if (opened_mdir->mid.bid > mdir->mid.bid) { - opened_mdir->mid.bid += lfsr_btree_weight(&mtree_) + } else if (opened_mdir->mid > mdir->mid) { + opened_mdir->mid += lfsr_btree_weight(&mtree_) - lfsr_mtree_weight(lfs); } } @@ -5721,13 +5716,15 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, } // update mdir to follow requested rid - LFS_ASSERT(mdir->mid.rid <= (lfs_ssize_t)mdir->u.m.weight); - if (mdir->mid.bid != -1 + if (mdir->mid != -1 && !lfsr_mdir_isdropped(&msibling_) - && mdir->mid.rid >= (lfs_ssize_t)mdir_.u.m.weight) { - LFS_ASSERT(lfsr_btree_weight(&mtree_) != lfsr_mtree_weight(lfs)); - mdir->mid.bid += lfsr_mbidweight(lfs); - mdir->mid.rid -= mdir_.u.m.weight; + && (mdir->mid & lfsr_mridmask(lfs)) + >= (lfs_ssize_t)mdir_.u.m.weight) { + // TODO this can happen if we split+drop while removing this mid, + // can we still assert for this? + //LFS_ASSERT(lfsr_btree_weight(&mtree_) != lfsr_mtree_weight(lfs)); + mdir->mid += lfsr_mbidweight(lfs) + - mdir_.u.m.weight; mdir->u.m = msibling_.u.m; } else { mdir->u.m = mdir_.u.m; @@ -5769,7 +5766,7 @@ static int lfsr_mtree_namelookup(lfs_t *lfs, if (lfsr_mtree_isinlined(lfs)) { mdir = lfs->mroot; // treat inlined mdir as mid=0 - mdir.mid = LFSR_MID(0, -1); + mdir.mid = 0; // lookup name in actual mtree } else { @@ -5784,6 +5781,7 @@ static int lfsr_mtree_namelookup(lfs_t *lfs, return err; } LFS_ASSERT(tag == LFSR_TAG_MDIR); + LFS_ASSERT(weight == lfsr_mbidweight(lfs)); // decode mdir err = lfsr_data_readmdir(lfs, &data, mdir.u.m.blocks); @@ -5792,8 +5790,7 @@ static int lfsr_mtree_namelookup(lfs_t *lfs, } // fetch mdir - err = lfsr_mdir_fetch(lfs, &mdir, mdir.u.m.blocks, - LFSR_MID(bid-(weight-1), -1)); + err = lfsr_mdir_fetch(lfs, &mdir, mdir.u.m.blocks, bid-(weight-1)); if (err) { return err; } @@ -5806,7 +5803,7 @@ static int lfsr_mtree_namelookup(lfs_t *lfs, &rid, tag_, data_); // update mdir weith best place to insert even if we fail - mdir.mid.rid = rid; + mdir.mid += rid; if (mdir_) { *mdir_ = mdir; } @@ -5831,7 +5828,7 @@ static int lfsr_mtree_pathlookup(lfs_t *lfs, const char *path, lfs_size_t *did_, const char **name_, lfs_size_t *name_size_) { // setup root lfsr_mdir_t mdir; - mdir.mid = LFSR_MID(0, 0); + mdir.mid = 0; lfsr_tag_t tag = LFSR_TAG_DIR; lfs_size_t did = LFSR_DID_ROOT; @@ -5899,7 +5896,7 @@ static int lfsr_mtree_pathlookup(lfs_t *lfs, const char *path, // read the next did from the mdir if this is not the root if (!lfsr_mid_isroot(mdir.mid)) { lfsr_data_t data; - int err = lfsr_mdir_lookup(lfs, &mdir, mdir.mid.rid, LFSR_TAG_DID, + int err = lfsr_mdir_lookup(lfs, &mdir, mdir.mid, LFSR_TAG_DID, NULL, &data); if (err) { return err; @@ -5986,7 +5983,7 @@ enum { static int lfsr_mtree_traversal_next(lfs_t *lfs, lfsr_mtree_traversal_t *traversal, - lfsr_mid_t *mid_, lfsr_tag_t *tag_, lfsr_data_t *data_) { + lfs_ssize_t *mid_, lfsr_tag_t *tag_, lfsr_data_t *data_) { // new traversal? start with 0x{0,1} // // note we make sure to include all mroots in our mroot chain! @@ -5994,13 +5991,13 @@ static int lfsr_mtree_traversal_next(lfs_t *lfs, if (traversal->mdir.u.r.rbyd.trunk == 0) { // fetch the first mroot 0x{0,1} int err = lfsr_mdir_fetch(lfs, &traversal->mdir, - LFSR_MDIR_MROOTANCHOR, LFSR_MID(-1, -1)); + LFSR_MDIR_MROOTANCHOR, -1); if (err) { return err; } if (mid_) { - *mid_ = LFSR_MID(-1, -1); + *mid_ = -1; } if (tag_) { *tag_ = LFSR_TAG_MDIR; @@ -6011,7 +6008,7 @@ static int lfsr_mtree_traversal_next(lfs_t *lfs, return 0; // check for mroot/mtree/mdir - } else if (traversal->mdir.mid.bid == -1) { + } else if (traversal->mdir.mid == -1) { // lookup mroot, if we find one this is a fake mroot lfsr_tag_t tag; lfsr_data_t data; @@ -6057,13 +6054,13 @@ static int lfsr_mtree_traversal_next(lfs_t *lfs, // fetch this mroot err = lfsr_mdir_fetch(lfs, &traversal->mdir, - traversal->mdir.u.m.blocks, LFSR_MID(-1, -1)); + traversal->mdir.u.m.blocks, -1); if (err) { return err; } if (mid_) { - *mid_ = LFSR_MID(-1, -1); + *mid_ = -1; } if (tag_) { *tag_ = LFSR_TAG_MDIR; @@ -6156,10 +6153,10 @@ static int lfsr_mtree_traversal_next(lfs_t *lfs, // still update our mdir mid so we don't get stuck in a loop // traversing mroots - traversal->mdir.mid.bid = bid; + traversal->mdir.mid = bid; if (mid_) { - *mid_ = LFSR_MID(bid, -1); + *mid_ = bid; } if (tag_) { *tag_ = tag; @@ -6177,13 +6174,13 @@ static int lfsr_mtree_traversal_next(lfs_t *lfs, } err = lfsr_mdir_fetch(lfs, &traversal->mdir, - traversal->mdir.u.m.blocks, LFSR_MID(bid, -1)); + traversal->mdir.u.m.blocks, bid); if (err) { return err; } if (mid_) { - *mid_ = LFSR_MID(bid, -1); + *mid_ = bid; } if (tag_) { *tag_ = tag; @@ -6325,7 +6322,7 @@ static int lfsr_mountinited(lfs_t *lfs) { lfsr_mdir_t *mdir = (lfsr_mdir_t*)data.u.b.buffer; // found an mroot? - if (mdir->mid.bid == -1) { + if (mdir->mid == -1) { // has magic string? lfsr_data_t data; err = lfsr_mdir_lookup(lfs, mdir, -1, LFSR_TAG_SUPERMAGIC, @@ -6567,11 +6564,9 @@ static int lfsr_mountinited(lfs_t *lfs) { } if (lfsr_grm_hasrm(&lfs->grm)) { - LFS_DEBUG("Found pending grm %"PRId16".%"PRId16" %"PRId16".%"PRId16, - lfs->grm.rms[0].bid, - lfs->grm.rms[0].rid, - lfs->grm.rms[1].bid, - lfs->grm.rms[1].rid); + LFS_DEBUG("Found pending grm %"PRId32" %"PRId32, + lfs->grm.rms[0], + lfs->grm.rms[1]); } return 0; @@ -6886,12 +6881,12 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) { // commit our new directory into our parent, creating a grm to self-remove // in case of powerloss err = lfsr_mdir_commit(lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(mdir.mid.rid, DIR, +1, + LFSR_ATTR(mdir.mid, DIR, +1, NAME(did, name, name_size)), - LFSR_ATTR(mdir.mid.rid, DID, 0, LEB128(did_)), + LFSR_ATTR(mdir.mid, DID, 0, LEB128(did_)), LFSR_ATTR(-1, GRM, 0, GRM(&((lfsr_grm_t){{ mdir.mid, - LFSR_MID(-1, -1)}}))))); + -1}}))))); if (err) { goto failed_with_bookmark; } @@ -6901,10 +6896,10 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) { // commit our bookmark and zero the grm, the bookmark tag is an empty // entry that marks our did as allocated err = lfsr_mdir_commit(lfs, &bookmark.mdir, LFSR_ATTRS( - LFSR_ATTR(bookmark.mdir.mid.rid, BOOKMARK, +1, NAME(did_, NULL, 0)), + LFSR_ATTR(bookmark.mdir.mid, BOOKMARK, +1, NAME(did_, NULL, 0)), LFSR_ATTR(-1, GRM, 0, GRM(&((lfsr_grm_t){{ - LFSR_MID(-1, -1), - LFSR_MID(-1, -1)}}))))); + -1, + -1}}))))); if (err) { return err; } @@ -6939,7 +6934,7 @@ int lfsr_remove(lfs_t *lfs, const char *path) { if (tag == LFSR_TAG_DIR) { // first lets figure out the did lfsr_data_t data; - int err = lfsr_mdir_lookup(lfs, &mdir, mdir.mid.rid, LFSR_TAG_DID, + int err = lfsr_mdir_lookup(lfs, &mdir, mdir.mid, LFSR_TAG_DID, NULL, &data); if (err) { return err; @@ -6972,7 +6967,7 @@ int lfsr_remove(lfs_t *lfs, const char *path) { if (err != LFS_ERR_NOENT) { lfsr_tag_t bookmark_tag; err = lfsr_mdir_lookup(lfs, &bookmark_mdir, - bookmark_mdir.mid.rid, LFSR_TAG_WIDE(NAME), + bookmark_mdir.mid, LFSR_TAG_WIDE(NAME), &bookmark_tag, NULL); if (err) { return err; @@ -6984,15 +6979,16 @@ int lfsr_remove(lfs_t *lfs, const char *path) { } // adjust rid if grm is on the same mdir as our dir - if (grm.rms[0].bid == mdir.mid.bid - && grm.rms[0].rid > mdir.mid.rid) { - grm.rms[0].rid -= 1; + if ((grm.rms[0] & lfsr_mbidmask(lfs)) + == (mdir.mid & lfsr_mbidmask(lfs)) + && grm.rms[0] > mdir.mid) { + grm.rms[0] -= 1; } } // remove the metadata entry err = lfsr_mdir_commit(lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(mdir.mid.rid, RM, -1, NULL), + LFSR_ATTR(mdir.mid, RM, -1, NULL), LFSR_ATTR(-1, GRM, 0, GRM(&grm)))); if (err) { return err; @@ -7046,9 +7042,10 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) { } // adjust old rid if grm is on the same mdir as new rid - if (grm.rms[0].bid == new_mdir.mid.bid - && grm.rms[0].rid >= new_mdir.mid.rid) { - grm.rms[0].rid += 1; + if ((grm.rms[0] & lfsr_mbidmask(lfs)) + == (new_mdir.mid & lfsr_mbidmask(lfs)) + && grm.rms[0] >= new_mdir.mid) { + grm.rms[0] += 1; } } else { @@ -7059,8 +7056,7 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) { // TODO is it? is this check necessary? // renaming to ourself is a noop - if (old_mdir.mid.bid == new_mdir.mid.bid - && old_mdir.mid.rid == new_mdir.mid.rid) { + if (old_mdir.mid == new_mdir.mid) { return 0; } @@ -7071,7 +7067,7 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) { // first lets figure out the did lfsr_data_t data; int err = lfsr_mdir_lookup(lfs, &new_mdir, - new_mdir.mid.rid, LFSR_TAG_DID, + new_mdir.mid, LFSR_TAG_DID, NULL, &data); if (err) { return err; @@ -7104,7 +7100,7 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) { if (err != LFS_ERR_NOENT) { lfsr_tag_t bookmark_tag; err = lfsr_mdir_lookup(lfs, &bookmark_mdir, - bookmark_mdir.mid.rid, LFSR_TAG_WIDE(NAME), + bookmark_mdir.mid, LFSR_TAG_WIDE(NAME), &bookmark_tag, NULL); if (err) { return err; @@ -7121,11 +7117,11 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) { // new rid, while also marking the old rid for removal err = lfsr_mdir_commit(lfs, &new_mdir, LFSR_ATTRS( (exists - ? LFSR_ATTR(new_mdir.mid.rid, RM, -1, NULL) + ? LFSR_ATTR(new_mdir.mid, RM, -1, NULL) : LFSR_ATTR_NOOP), - LFSR_ATTR(new_mdir.mid.rid, TAG(old_tag), +1, + LFSR_ATTR(new_mdir.mid, TAG(old_tag), +1, NAME(new_did, new_name, new_name_size)), - LFSR_ATTR(new_mdir.mid.rid, MOVE, 0, MOVE(&old_mdir)), + LFSR_ATTR(new_mdir.mid, MOVE, 0, MOVE(&old_mdir)), LFSR_ATTR(-1, GRM, 0, GRM(&grm)))); // we need to clean up any pending grms, fortunately we can leave @@ -7188,7 +7184,7 @@ int lfsr_dir_open(lfs_t *lfs, lfsr_dir_t *dir, const char *path) { dir->did = 0; } else { lfsr_data_t data; - int err = lfsr_mdir_lookup(lfs, &mdir, mdir.mid.rid, LFSR_TAG_DID, + int err = lfsr_mdir_lookup(lfs, &mdir, mdir.mid, LFSR_TAG_DID, NULL, &data); if (err) { return err; @@ -7251,7 +7247,7 @@ int lfsr_dir_read(lfs_t *lfs, lfsr_dir_t *dir, struct lfs_info *info) { lfsr_tag_t tag; lfsr_data_t data; err = lfsr_mdir_lookup(lfs, &dir->pos_mdir, - dir->pos_mdir.mid.rid, LFSR_TAG_WIDE(NAME), + dir->pos_mdir.mid, LFSR_TAG_WIDE(NAME), &tag, &data); if (err) { return err; @@ -7348,8 +7344,8 @@ static int lfsr_fs_fixgrm(lfs_t *lfs) { while (lfsr_grm_hasrm(&lfs->grm)) { // find our mdir lfsr_mdir_t mdir; - LFS_ASSERT(lfs->grm.rms[0].bid - < lfs_smax32(lfsr_mtree_weight(lfs), 1)); + LFS_ASSERT(lfs->grm.rms[0] + < lfs_smax32(lfsr_mtree_weight(lfs), lfsr_mbidweight(lfs))); int err = lfsr_mtree_lookup(lfs, lfs->grm.rms[0], &mdir); if (err) { return err; @@ -7360,16 +7356,18 @@ static int lfsr_fs_fixgrm(lfs_t *lfs) { lfsr_grm_poprm(&grm); // make sure to adjust any remaining grms - if (grm.rms[0].bid == mdir.mid.bid - && grm.rms[0].rid >= mdir.mid.rid) { - LFS_ASSERT(grm.rms[0].rid != mdir.mid.rid); - grm.rms[0].rid -= 1; + if ((grm.rms[0] & lfsr_mbidmask(lfs)) + == (mdir.mid & lfsr_mbidmask(lfs)) + && grm.rms[0] >= mdir.mid) { + LFS_ASSERT(grm.rms[0] != mdir.mid); + grm.rms[0] -= 1; } // remove the rid while also updating our grm - LFS_ASSERT(lfs->grm.rms[0].rid < (lfs_ssize_t)mdir.u.m.weight); + LFS_ASSERT((lfs->grm.rms[0] & lfsr_mridmask(lfs)) + < (lfs_ssize_t)mdir.u.m.weight); err = lfsr_mdir_commit(lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(mdir.mid.rid, RM, -1, NULL), + LFSR_ATTR(mdir.mid, RM, -1, NULL), LFSR_ATTR(-1, GRM, 0, GRM(&grm)))); } @@ -7382,11 +7380,9 @@ static int lfsr_fs_preparemutation(lfs_t *lfs) { // fix pending grms if (lfsr_grm_hasrm(&lfs->grm)) { - LFS_DEBUG("Fixing grm %"PRId16".%"PRId16" %"PRId16".%"PRId16, - lfs->grm.rms[0].bid, - lfs->grm.rms[0].rid, - lfs->grm.rms[1].bid, - lfs->grm.rms[1].rid); + LFS_DEBUG("Fixing grm %"PRId32" %"PRId32, + lfs->grm.rms[0], + lfs->grm.rms[1]); int err = lfsr_fs_fixgrm(lfs); if (err) { diff --git a/lfs.h b/lfs.h index fb7ef59d..de1a5307 100644 --- a/lfs.h +++ b/lfs.h @@ -47,16 +47,6 @@ typedef uint32_t lfs_block_t; typedef uint16_t lfsr_tag_t; typedef int16_t lfsr_stag_t; -typedef uint32_t lfsr_mbid_t; -typedef int32_t lfsr_smbid_t; -typedef uint32_t lfsr_mrid_t; -typedef int32_t lfsr_smrid_t; - -typedef struct lfsr_mid { - lfsr_smbid_t bid; - lfsr_smrid_t rid; -} lfsr_mid_t; - // Maximum name size in bytes, may be redefined to reduce the size of the // info struct. Limited to <= 1022. Stored in superblock and must be // respected by other littlefs drivers. @@ -380,7 +370,7 @@ typedef struct lfsr_btree { } lfsr_btree_t; typedef struct lfsr_mdir { - lfsr_mid_t mid; + lfs_ssize_t mid; union { // here we make sure to line up our block array so it overlaps with // the block stored as the first entry in the rbyd @@ -412,7 +402,7 @@ typedef struct lfsr_openedmdir { #define LFSR_GRM_DSIZE (1+5+5+5+5) typedef struct lfsr_grm { - lfsr_mid_t rms[2]; + lfs_ssize_t rms[2]; } lfsr_grm_t; diff --git a/tests/test_alloc.toml b/tests/test_alloc.toml index a445c7cb..caa059f4 100644 --- a/tests/test_alloc.toml +++ b/tests/test_alloc.toml @@ -109,9 +109,8 @@ code = ''' LFSR_ATTR(0, RM, -1, NULL))) => 0; lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; - mdir.mid.rid = 0; lfs_size_t count = 0; while (true) { @@ -123,7 +122,7 @@ code = ''' // keep creating new metadata entries until we run out of space int err = lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(mdir.mid.rid, REG, +1, + LFSR_ATTR(mdir.mid, REG, +1, BUF(&alphas[count % 26], 1)))); assert(!err || err == LFS_ERR_NOSPC); if (err == LFS_ERR_NOSPC) { @@ -131,12 +130,12 @@ code = ''' } uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; assert(memcmp(buffer, &alphas[count % 26], 1) == 0); + mdir.mid += 1; count += 1; - mdir.mid.rid += 1; } printf("alloced %d metadata entries in %d blocks\n", @@ -145,15 +144,17 @@ code = ''' // test that all of our metadata entries are still there lfs_size_t i = 0; for (lfs_ssize_t mid = 0; - mid < lfs_smax32(lfsr_mtree_weight(&lfs), 1); + mid < lfs_smax32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs)); mid += lfsr_mbidweight(&lfs)) { lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; - for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; - mdir.mid.rid++) { + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + for (; (mdir.mid & lfsr_mridmask(&lfs)) + < (lfs_ssize_t)mdir.u.m.weight; + mdir.mid += 1) { uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; assert(memcmp(buffer, &alphas[i % 26], 1) == 0); i += 1; diff --git a/tests/test_mtree.toml b/tests/test_mtree.toml index 7e36608a..a771f0f2 100644 --- a/tests/test_mtree.toml +++ b/tests/test_mtree.toml @@ -193,10 +193,10 @@ code = ''' // assert that our entry is still in the mtree lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); @@ -217,10 +217,10 @@ code = ''' assert(memcmp(buffer, "a", 1) == 0); // assert that our entry is still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); @@ -261,15 +261,15 @@ code = ''' // assert that our entries are still in the mtree lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "a", 1) == 0); - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); @@ -285,15 +285,15 @@ code = ''' assert(lfs.mroot.u.m.weight == 0); // assert that our entries are still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "a", 1) == 0); - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); @@ -334,12 +334,12 @@ code = ''' // now add another large entry to the mdir, forcing a split lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+1, &mdir) => 0; assert(mdir.u.m.weight == 1); memset(buffer, 'c', SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(1, REG, +1, BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(mdir.mid, REG, +1, BUF(buffer, SIZE)))) => 0; // force mdir to compact mdir.u.r.rbyd.eoff = BLOCK_SIZE; @@ -356,15 +356,15 @@ code = ''' assert(memcmp(buffer, "a", 1) == 0); // assert that our entries are still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "c", 1) == 0); @@ -384,15 +384,15 @@ code = ''' assert(memcmp(buffer, "a", 1) == 0); // assert that our entries are still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "c", 1) == 0); @@ -417,10 +417,9 @@ code = ''' // create entries lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(lfs_smax32(lfsr_mtree_weight(&lfs)-1, 0), -1), + lfsr_mtree_lookup(&lfs, + lfs_smax32(lfsr_mtree_weight(&lfs) - lfsr_mbidweight(&lfs), 0), &mdir) => 0; - - mdir.mid.rid = 0; for (lfs_size_t i = 0; i < N; i++) { // force a compaction? if (FORCE_COMPACTION) { @@ -429,29 +428,31 @@ code = ''' } lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(mdir.mid.rid, REG, +1, + LFSR_ATTR(mdir.mid, REG, +1, BUF(&alphas[i % 26], 1)))) => 0; uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; assert(memcmp(buffer, &alphas[i % 26], 1) == 0); - mdir.mid.rid += 1; + mdir.mid += 1; } // try looking up each entry lfs_size_t i = 0; for (lfs_ssize_t mid = 0; - mid < lfs_smax32(lfsr_mtree_weight(&lfs), 1); + mid < lfs_smax32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs)); mid += lfsr_mbidweight(&lfs)) { lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; - for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; - mdir.mid.rid++) { + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + for (; (mdir.mid & lfsr_mridmask(&lfs)) + < (lfs_ssize_t)mdir.u.m.weight; + mdir.mid += 1) { uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; assert(memcmp(buffer, &alphas[i % 26], 1) == 0); i += 1; @@ -468,15 +469,17 @@ code = ''' // try looking up each entry i = 0; for (lfs_ssize_t mid = 0; - mid < lfs_smax32(lfsr_mtree_weight(&lfs), 1); + mid < lfs_smax32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs)); mid += lfsr_mbidweight(&lfs)) { lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; - for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; - mdir.mid.rid++) { + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + for (; (mdir.mid & lfsr_mridmask(&lfs)) + < (lfs_ssize_t)mdir.u.m.weight; + mdir.mid += 1) { uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; assert(memcmp(buffer, &alphas[i % 26], 1) == 0); i += 1; @@ -511,12 +514,15 @@ code = ''' for (lfs_size_t i = 0; i < N; i++) { // choose a pseudo-random mid lfs_ssize_t mid = (lfs_ssize_t)( - TEST_PRNG(&prng) % lfs_max32(lfsr_mtree_weight(&lfs), 1)); + TEST_PRNG(&prng) % lfs_max32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs))); // fetch mdir lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; - // choose a pseudo-random rid - mdir.mid.rid = TEST_PRNG(&prng) % (mdir.u.m.weight+1); + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + // limit our mid to our mdir's weight + mdir.mid = (mdir.mid & lfsr_mbidmask(&lfs)) + | (mdir.mid % (mdir.u.m.weight+1)); // force a compaction? if (FORCE_COMPACTION) { @@ -526,12 +532,12 @@ code = ''' // add to rbyd, potentially splitting the mdir lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(mdir.mid.rid, REG, +1, + LFSR_ATTR(mdir.mid, REG, +1, BUF(&alphas[i % 26], 1)))) => 0; // make sure we can look up the new entry uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; assert(memcmp(buffer, &alphas[i % 26], 1) == 0); @@ -542,15 +548,17 @@ code = ''' lfs_size_t count_ = 0; for (lfs_ssize_t mid = 0; - mid < lfs_smax32(lfsr_mtree_weight(&lfs), 1); + mid < lfs_smax32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs)); mid += lfsr_mbidweight(&lfs)) { lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; - for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; - mdir.mid.rid++) { + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + for (; (mdir.mid & lfsr_mridmask(&lfs)) + < (lfs_ssize_t)mdir.u.m.weight; + mdir.mid += 1) { uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; count_ += 1; @@ -571,15 +579,17 @@ code = ''' count_ = 0; for (lfs_ssize_t mid = 0; - mid < lfs_smax32(lfsr_mtree_weight(&lfs), 1); + mid < lfs_smax32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs)); mid += lfsr_mbidweight(&lfs)) { lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; - for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; - mdir.mid.rid++) { + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + for (; (mdir.mid & lfsr_mridmask(&lfs)) + < (lfs_ssize_t)mdir.u.m.weight; + mdir.mid += 1) { uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; count_ += 1; @@ -631,7 +641,7 @@ code = ''' // remove the entry, forcing the mdir to be dropped lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( @@ -700,7 +710,7 @@ code = ''' // remove the entry, forcing the mdir to be dropped lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); // force mdir to compact while we're removing @@ -835,10 +845,10 @@ code = ''' // assert that one entry is still in the mtree lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); @@ -854,10 +864,10 @@ code = ''' assert(lfs.mroot.u.m.weight == 0); // assert that one entry is still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); @@ -902,10 +912,10 @@ code = ''' // assert that one entry is still in the mtree lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "a", 1) == 0); @@ -921,10 +931,10 @@ code = ''' assert(lfs.mroot.u.m.weight == 0); // assert that one entry is still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "a", 1) == 0); @@ -1015,20 +1025,21 @@ code = ''' // now add another large entry to the mdir, forcing a split lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+1, &mdir) => 0; assert(mdir.u.m.weight == 1); memset(buffer, 'c', SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(1, REG, +1, BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(mdir.mid, REG, +1, BUF(buffer, SIZE)))) => 0; // force mdir to compact mdir.u.r.rbyd.eoff = BLOCK_SIZE; // remove the left entry as we compact, forcing the left // mdir to be dropped + mdir.mid = 0*lfsr_mbidweight(&lfs)+0; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(0, RM, -1, NULL))) => 0; + LFSR_ATTR(mdir.mid, RM, -1, NULL))) => 0; // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 1*lfsr_mbidweight(&lfs)); @@ -1041,10 +1052,10 @@ code = ''' assert(memcmp(buffer, "a", 1) == 0); // assert that one entry is still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "c", 1) == 0); @@ -1065,10 +1076,10 @@ code = ''' assert(memcmp(buffer, "a", 1) == 0); // assert that one entry is still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "c", 1) == 0); @@ -1109,12 +1120,12 @@ code = ''' // now add another large entry to the mdir, forcing a split lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+1, &mdir) => 0; assert(mdir.u.m.weight == 1); memset(buffer, 'c', SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(1, REG, +1, BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(mdir.mid, REG, +1, BUF(buffer, SIZE)))) => 0; // force mdir to compact mdir.u.r.rbyd.eoff = BLOCK_SIZE; @@ -1135,10 +1146,10 @@ code = ''' assert(memcmp(buffer, "a", 1) == 0); // assert that one entry is still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); @@ -1159,10 +1170,10 @@ code = ''' assert(memcmp(buffer, "a", 1) == 0); // assert that one entry is still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); @@ -1203,12 +1214,12 @@ code = ''' // now add another large entry to the mdir, forcing a split lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+1, &mdir) => 0; assert(mdir.u.m.weight == 1); memset(buffer, 'c', SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(1, REG, +1, BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(mdir.mid, REG, +1, BUF(buffer, SIZE)))) => 0; // force mdir to compact mdir.u.r.rbyd.eoff = BLOCK_SIZE; @@ -1266,27 +1277,26 @@ code = ''' // create entries lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(lfs_smax32(lfsr_mtree_weight(&lfs)-1, 0), -1), + lfsr_mtree_lookup(&lfs, + lfs_smax32(lfsr_mtree_weight(&lfs) - lfsr_mbidweight(&lfs), 0), &mdir) => 0; - - mdir.mid.rid = 0; for (lfs_size_t i = 0; i < N; i++) { lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(mdir.mid.rid, REG, +1, + LFSR_ATTR(mdir.mid, REG, +1, BUF(&alphas[i % 26], 1)))) => 0; uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; assert(memcmp(buffer, &alphas[i % 26], 1) == 0); - mdir.mid.rid += 1; + mdir.mid += 1; } // remove entries for (lfs_size_t i = 0; i < N - REMAINING; i++) { lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; // drop should make sure we never have empty mdirs assert(lfsr_mtree_isinlined(&lfs) || mdir.u.m.weight > 0); @@ -1304,15 +1314,17 @@ code = ''' // try looking up each entry lfs_size_t i = N - REMAINING; for (lfs_ssize_t mid = 0; - mid < lfs_smax32(lfsr_mtree_weight(&lfs), 1); + mid < lfs_smax32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs)); mid += lfsr_mbidweight(&lfs)) { lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; - for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; - mdir.mid.rid++) { + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + for (; (mdir.mid & lfsr_mridmask(&lfs)) + < (lfs_ssize_t)mdir.u.m.weight; + mdir.mid += 1) { uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; assert(memcmp(buffer, &alphas[i % 26], 1) == 0); i += 1; @@ -1329,15 +1341,17 @@ code = ''' // try looking up each entry i = N - REMAINING; for (lfs_ssize_t mid = 0; - mid < lfs_smax32(lfsr_mtree_weight(&lfs), 1); + mid < lfs_smax32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs)); mid += lfsr_mbidweight(&lfs)) { lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; - for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; - mdir.mid.rid++) { + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + for (; (mdir.mid & lfsr_mridmask(&lfs)) + < (lfs_ssize_t)mdir.u.m.weight; + mdir.mid += 1) { uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; assert(memcmp(buffer, &alphas[i % 26], 1) == 0); i += 1; @@ -1367,35 +1381,36 @@ code = ''' for (lfs_size_t cycle = 0; cycle < CYCLES; cycle++) { // create entries lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(lfs_smax32(lfsr_mtree_weight(&lfs)-1, 0), -1), + lfsr_mtree_lookup(&lfs, + lfs_smax32(lfsr_mtree_weight(&lfs) - lfsr_mbidweight(&lfs), 0), &mdir) => 0; - - mdir.mid.rid = 0; for (lfs_size_t i = 0; i < N; i++) { lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(mdir.mid.rid, REG, +1, + LFSR_ATTR(mdir.mid, REG, +1, BUF(&alphas[i % 26], 1)))) => 0; uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; assert(memcmp(buffer, &alphas[i % 26], 1) == 0); - mdir.mid.rid += 1; + mdir.mid += 1; } // try looking up each entry lfs_size_t i = 0; for (lfs_ssize_t mid = 0; - mid < lfs_smax32(lfsr_mtree_weight(&lfs), 1); + mid < lfs_smax32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs)); mid += lfsr_mbidweight(&lfs)) { lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; - for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; - mdir.mid.rid++) { + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + for (; (mdir.mid & lfsr_mridmask(&lfs)) + < (lfs_ssize_t)mdir.u.m.weight; + mdir.mid += 1) { uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; assert(memcmp(buffer, &alphas[i % 26], 1) == 0); i += 1; @@ -1406,7 +1421,7 @@ code = ''' // remove entries for (lfs_size_t i = 0; i < N; i++) { lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; // drop should make sure we never have empty mdirs assert(lfsr_mtree_isinlined(&lfs) || mdir.u.m.weight > 0); @@ -1460,16 +1475,20 @@ code = ''' for (lfs_size_t i = 0; i < N; i++) { // choose a pseudo-random mid lfs_ssize_t mid = (lfs_ssize_t)( - TEST_PRNG(&prng) % lfs_max32(lfsr_mtree_weight(&lfs), 1)); + TEST_PRNG(&prng) % lfs_max32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs))); // fetch mdir lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; - // choose a pseudo-random rid - mdir.mid.rid = TEST_PRNG(&prng) % (mdir.u.m.weight+1); + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + // limit our mid to our mdir's weight + mdir.mid = (mdir.mid & lfsr_mbidmask(&lfs)) + | (mdir.mid % (mdir.u.m.weight+1)); // choose to create or delete - uint8_t op = (lfs_size_t)mdir.mid.rid == mdir.u.m.weight + uint8_t op = ((lfs_size_t)(mdir.mid & lfsr_mridmask(&lfs)) + == mdir.u.m.weight ? 0 - : TEST_PRNG(&prng) % 2; + : TEST_PRNG(&prng) % 2); // force a compaction? if (FORCE_COMPACTION) { @@ -1481,12 +1500,12 @@ code = ''' if (op == 0) { // add to rbyd, potentially splitting the mdir lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(mdir.mid.rid, REG, +1, + LFSR_ATTR(mdir.mid, REG, +1, BUF(&alphas[i % 26], 1)))) => 0; // make sure we can look up the new entry uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; assert(memcmp(buffer, &alphas[i % 26], 1) == 0); @@ -1495,7 +1514,7 @@ code = ''' // delete } else { lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(mdir.mid.rid, RM, -1, NULL))) => 0; + LFSR_ATTR(mdir.mid, RM, -1, NULL))) => 0; count -= 1; } @@ -1505,19 +1524,21 @@ code = ''' lfs_size_t count_ = 0; for (lfs_ssize_t mid = 0; - mid < lfs_smax32(lfsr_mtree_weight(&lfs), 1); + mid < lfs_smax32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs)); mid += lfsr_mbidweight(&lfs)) { lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; // drop should make sure we never have empty mdirs assert(lfsr_mtree_isinlined(&lfs) || mdir.u.m.weight > 0); - for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; - mdir.mid.rid++) { + for (; (mdir.mid & lfsr_mridmask(&lfs)) + < (lfs_ssize_t)mdir.u.m.weight; + mdir.mid += 1) { uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; count_ += 1; @@ -1538,19 +1559,21 @@ code = ''' count_ = 0; for (lfs_ssize_t mid = 0; - mid < lfs_smax32(lfsr_mtree_weight(&lfs), 1); + mid < lfs_smax32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs)); mid += lfsr_mbidweight(&lfs)) { lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; // drop should make sure we never have empty mdirs assert(lfsr_mtree_isinlined(&lfs) || mdir.u.m.weight > 0); - for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; - mdir.mid.rid++) { + for (; (mdir.mid & lfsr_mridmask(&lfs)) + < (lfs_ssize_t)mdir.u.m.weight; + mdir.mid += 1) { uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; count_ += 1; @@ -1605,7 +1628,7 @@ code = ''' // force mdir to compact twice, this should relocate lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); lfsr_mdir_t old_mdir = mdir; @@ -1615,7 +1638,7 @@ code = ''' mdir.u.r.rbyd.eoff = BLOCK_SIZE; memset(buffer, 'c', SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(0, REG, 0, BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(mdir.mid, REG, 0, BUF(buffer, SIZE)))) => 0; // assert we relocated assert(lfsr_mdir_cmp(old_mdir.u.m.blocks, mdir.u.m.blocks) != 0); @@ -1626,10 +1649,10 @@ code = ''' assert(memcmp(buffer, "a", 1) == 0); // assert that our entry is still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "c", 1) == 0); @@ -1653,10 +1676,10 @@ code = ''' assert(memcmp(buffer, "a", 1) == 0); // assert that our entry is still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "c", 1) == 0); @@ -1699,7 +1722,7 @@ code = ''' // force mdir to compact twice, this should relocate lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); lfsr_mdir_t old_mdir = mdir; @@ -1709,21 +1732,21 @@ code = ''' mdir.u.r.rbyd.eoff = BLOCK_SIZE; memset(buffer, 'c', SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(0, REG, 0, BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(mdir.mid, REG, 0, BUF(buffer, SIZE)))) => 0; // assert we relocated assert(lfsr_mdir_cmp(old_mdir.u.m.blocks, mdir.u.m.blocks) != 0); // assert that our entries are still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "c", 1) == 0); - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); @@ -1742,15 +1765,15 @@ code = ''' assert(lfsr_mdir_cmp(old_mdir.u.m.blocks, mdir.u.m.blocks) != 0); // assert that our entries are still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "c", 1) == 0); - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); @@ -1793,7 +1816,7 @@ code = ''' // force mdir to compact twice, this should relocate lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); lfsr_mdir_t old_mdir = mdir; @@ -1803,21 +1826,21 @@ code = ''' mdir.u.r.rbyd.eoff = BLOCK_SIZE; memset(buffer, 'c', SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(0, REG, 0, BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(mdir.mid, REG, 0, BUF(buffer, SIZE)))) => 0; // assert we relocated assert(lfsr_mdir_cmp(old_mdir.u.m.blocks, mdir.u.m.blocks) != 0); // assert that our entries are still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "a", 1) == 0); - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "c", 1) == 0); @@ -1836,15 +1859,15 @@ code = ''' assert(lfsr_mdir_cmp(old_mdir.u.m.blocks, mdir.u.m.blocks) != 0); // assert that our entries are still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "a", 1) == 0); - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "c", 1) == 0); @@ -2077,7 +2100,7 @@ code = ''' // force mdir to compact twice, this should relocate lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); lfsr_mdir_t old_mdir = mdir; @@ -2087,7 +2110,7 @@ code = ''' mdir.u.r.rbyd.eoff = BLOCK_SIZE; memset(buffer, 'c', SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(0, REG, 0, BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(mdir.mid, REG, 0, BUF(buffer, SIZE)))) => 0; // assert we relocated our mdir assert(lfsr_mdir_cmp(old_mdir.u.m.blocks, mdir.u.m.blocks) != 0); @@ -2101,10 +2124,10 @@ code = ''' assert(memcmp(buffer, "a", 1) == 0); // assert that our entry is still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "c", 1) == 0); @@ -2131,10 +2154,10 @@ code = ''' assert(memcmp(buffer, "a", 1) == 0); // assert that our entry is still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "c", 1) == 0); @@ -2182,12 +2205,12 @@ code = ''' // now add another large entry to the mdir, forcing a split lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+1, &mdir) => 0; assert(mdir.u.m.weight == 1); memset(buffer, 'c', SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(1, REG, +1, BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(mdir.mid, REG, +1, BUF(buffer, SIZE)))) => 0; // force mdir to compact mdir.u.r.rbyd.eoff = BLOCK_SIZE; @@ -2207,15 +2230,15 @@ code = ''' assert(memcmp(buffer, "a", 1) == 0); // assert that our entries are still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "c", 1) == 0); @@ -2239,15 +2262,15 @@ code = ''' assert(memcmp(buffer, "a", 1) == 0); // assert that our entries are still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "c", 1) == 0); @@ -2295,11 +2318,11 @@ code = ''' // remove the entry, forcing the mdir to be dropped lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(0, RM, -1, NULL))) => 0; + LFSR_ATTR(mdir.mid, RM, -1, NULL))) => 0; // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 0*lfsr_mbidweight(&lfs)); @@ -2387,10 +2410,10 @@ code = ''' // assert that our entry is still in the mtree lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); @@ -2414,10 +2437,10 @@ code = ''' assert(memcmp(buffer, "a", 1) == 0); // assert that our entry is still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); @@ -2469,15 +2492,15 @@ code = ''' // assert that our entries are still in the mtree lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "a", 1) == 0); - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); @@ -2496,15 +2519,15 @@ code = ''' assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our entries are still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "a", 1) == 0); - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); @@ -2536,16 +2559,20 @@ code = ''' for (lfs_size_t i = 0; i < N; i++) { // choose a pseudo-random mid lfs_ssize_t mid = (lfs_ssize_t)( - TEST_PRNG(&prng) % lfs_max32(lfsr_mtree_weight(&lfs), 1)); + TEST_PRNG(&prng) % lfs_max32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs))); // fetch mdir lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; - // choose a pseudo-random rid - mdir.mid.rid = TEST_PRNG(&prng) % (mdir.u.m.weight+1); + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + // limit our mid to our mdir's weight + mdir.mid = (mdir.mid & lfsr_mbidmask(&lfs)) + | (mdir.mid % (mdir.u.m.weight+1)); // choose to create or delete - uint8_t op = (lfs_size_t)mdir.mid.rid == mdir.u.m.weight + uint8_t op = ((lfs_size_t)(mdir.mid & lfsr_mridmask(&lfs)) + == mdir.u.m.weight ? 0 - : TEST_PRNG(&prng) % 3; + : TEST_PRNG(&prng) % 3); // force a compaction? if (FORCE_COMPACTION) { @@ -2557,12 +2584,12 @@ code = ''' if (op == 0) { // add to rbyd lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(mdir.mid.rid, REG, +1, + LFSR_ATTR(mdir.mid, REG, +1, BUF(&alphas[i % 26], 1)))) => 0; // make sure we can look up the new entry uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; assert(memcmp(buffer, &alphas[i % 26], 1) == 0); @@ -2572,19 +2599,19 @@ code = ''' } else if (op == 1) { // update rbyd lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(mdir.mid.rid, REG, 0, + LFSR_ATTR(mdir.mid, REG, 0, BUF(&alphas[i % 26], 1)))) => 0; // make sure we can look up the new entry uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; assert(memcmp(buffer, &alphas[i % 26], 1) == 0); // delete } else { lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(mdir.mid.rid, RM, -1, NULL))) => 0; + LFSR_ATTR(mdir.mid, RM, -1, NULL))) => 0; count -= 1; } @@ -2594,19 +2621,21 @@ code = ''' lfs_size_t count_ = 0; for (lfs_ssize_t mid = 0; - mid < lfs_smax32(lfsr_mtree_weight(&lfs), 1); + mid < lfs_smax32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs)); mid += lfsr_mbidweight(&lfs)) { lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; // drop should make sure we never have empty mdirs assert(lfsr_mtree_isinlined(&lfs) || mdir.u.m.weight > 0); - for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; - mdir.mid.rid++) { + for (; (mdir.mid & lfsr_mridmask(&lfs)) + < (lfs_ssize_t)mdir.u.m.weight; + mdir.mid += 1) { uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; count_ += 1; @@ -2627,19 +2656,21 @@ code = ''' count_ = 0; for (lfs_ssize_t mid = 0; - mid < lfs_smax32(lfsr_mtree_weight(&lfs), 1); + mid < lfs_smax32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs)); mid += lfsr_mbidweight(&lfs)) { lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; // drop should make sure we never have empty mdirs assert(lfsr_mtree_isinlined(&lfs) || mdir.u.m.weight > 0); - for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; - mdir.mid.rid++) { + for (; (mdir.mid & lfsr_mridmask(&lfs)) + < (lfs_ssize_t)mdir.u.m.weight; + mdir.mid += 1) { uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; count_ += 1; @@ -2675,9 +2706,9 @@ code = ''' assert(lfsr_mtree_isinlined(&lfs)); lfsr_openedmdir_t left_neighbor = { - .mdir={.mid=LFSR_MID(0, 0), .u.m=lfs.mroot.u.m}}; + .mdir={.mid=0, .u.m=lfs.mroot.u.m}}; lfsr_openedmdir_t right_neighbor = { - .mdir={.mid=LFSR_MID(0, 1), .u.m=lfs.mroot.u.m}}; + .mdir={.mid=1, .u.m=lfs.mroot.u.m}}; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -2695,13 +2726,11 @@ code = ''' // assert that our neighbors were updated correctly assert(!lfsr_mdir_isdropped(&left_neighbor.mdir)); - assert(left_neighbor.mdir.mid.bid == 0); - assert(left_neighbor.mdir.mid.rid == 0); + assert(left_neighbor.mdir.mid == 0); assert(memcmp(&left_neighbor.mdir.u.m, &lfs.mroot.u.m, sizeof(lfs.mroot.u.m)) == 0); assert(!lfsr_mdir_isdropped(&right_neighbor.mdir)); - assert(right_neighbor.mdir.mid.bid == 0); - assert(right_neighbor.mdir.mid.rid == 2); + assert(right_neighbor.mdir.mid == 2); assert(memcmp(&right_neighbor.mdir.u.m, &lfs.mroot.u.m, sizeof(lfs.mroot.u.m)) == 0); @@ -2729,9 +2758,9 @@ code = ''' assert(lfsr_mtree_isinlined(&lfs)); lfsr_openedmdir_t left_neighbor = { - .mdir={.mid=LFSR_MID(0, 0), .u.m=lfs.mroot.u.m}}; + .mdir={.mid=0, .u.m=lfs.mroot.u.m}}; lfsr_openedmdir_t right_neighbor = { - .mdir={.mid=LFSR_MID(0, 1), .u.m=lfs.mroot.u.m}}; + .mdir={.mid=1, .u.m=lfs.mroot.u.m}}; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -2745,8 +2774,7 @@ code = ''' // assert that our neighbors were updated correctly assert(lfsr_mdir_isdropped(&left_neighbor.mdir)); assert(!lfsr_mdir_isdropped(&right_neighbor.mdir)); - assert(right_neighbor.mdir.mid.bid == 0); - assert(right_neighbor.mdir.mid.rid == 0); + assert(right_neighbor.mdir.mid == 0); assert(memcmp(&right_neighbor.mdir.u.m, &lfs.mroot.u.m, sizeof(lfs.mroot.u.m)) == 0); @@ -2774,9 +2802,9 @@ code = ''' assert(lfsr_mtree_isinlined(&lfs)); lfsr_openedmdir_t left_neighbor = { - .mdir={.mid=LFSR_MID(0, 0), .u.m=lfs.mroot.u.m}}; + .mdir={.mid=0, .u.m=lfs.mroot.u.m}}; lfsr_openedmdir_t right_neighbor = { - .mdir={.mid=LFSR_MID(0, 1), .u.m=lfs.mroot.u.m}}; + .mdir={.mid=1, .u.m=lfs.mroot.u.m}}; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -2789,8 +2817,7 @@ code = ''' // assert that our neighbors were updated correctly assert(!lfsr_mdir_isdropped(&left_neighbor.mdir)); - assert(left_neighbor.mdir.mid.bid == 0); - assert(left_neighbor.mdir.mid.rid == 0); + assert(left_neighbor.mdir.mid == 0); assert(memcmp(&left_neighbor.mdir.u.m, &lfs.mroot.u.m, sizeof(lfs.mroot.u.m)) == 0); assert(lfsr_mdir_isdropped(&right_neighbor.mdir)); @@ -2821,9 +2848,9 @@ code = ''' assert(lfsr_mtree_isinlined(&lfs)); lfsr_openedmdir_t left_neighbor = { - .mdir={.mid=LFSR_MID(0, 0), .u.m=lfs.mroot.u.m}}; + .mdir={.mid=0, .u.m=lfs.mroot.u.m}}; lfsr_openedmdir_t right_neighbor = { - .mdir={.mid=LFSR_MID(0, 1), .u.m=lfs.mroot.u.m}}; + .mdir={.mid=1, .u.m=lfs.mroot.u.m}}; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -2854,27 +2881,25 @@ code = ''' // assert that our entry is still in the mtree lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+1, &mdir) => 0; assert(mdir.u.m.weight == 2); - lfsr_mdir_get(&lfs, &mdir, 1, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "d", 1) == 0); // note that our current implementation splits here, which is suboptimal // but saves on code size lfsr_mdir_t msibling; - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &msibling) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &msibling) => 0; assert(msibling.u.m.weight == 1); // assert that our neighbors were updated correctly assert(!lfsr_mdir_isdropped(&left_neighbor.mdir)); - assert(left_neighbor.mdir.mid.bid == 0*lfsr_mbidweight(&lfs)); - assert(left_neighbor.mdir.mid.rid == 0); + assert(left_neighbor.mdir.mid == 0*lfsr_mbidweight(&lfs)+0); assert(memcmp(&left_neighbor.mdir.u.m, &mdir.u.m, sizeof(mdir.u.m)) == 0); assert(!lfsr_mdir_isdropped(&right_neighbor.mdir)); - assert(right_neighbor.mdir.mid.bid == 1*lfsr_mbidweight(&lfs)); - assert(right_neighbor.mdir.mid.rid == 0); + assert(right_neighbor.mdir.mid == 1*lfsr_mbidweight(&lfs)+0); assert(memcmp(&right_neighbor.mdir.u.m, &msibling.u.m, sizeof(msibling.u.m)) == 0); @@ -2904,9 +2929,9 @@ code = ''' assert(lfsr_mtree_isinlined(&lfs)); lfsr_openedmdir_t left_neighbor = { - .mdir={.mid=LFSR_MID(0, 0), .u.m=lfs.mroot.u.m}}; + .mdir={.mid=0, .u.m=lfs.mroot.u.m}}; lfsr_openedmdir_t right_neighbor = { - .mdir={.mid=LFSR_MID(0, 1), .u.m=lfs.mroot.u.m}}; + .mdir={.mid=1, .u.m=lfs.mroot.u.m}}; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -2931,28 +2956,26 @@ code = ''' // assert that our entries are still in the mtree lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+1, &mdir) => 0; assert(mdir.u.m.weight == 2); - lfsr_mdir_get(&lfs, &mdir, 1, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "c", 1) == 0); lfsr_mdir_t msibling; - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &msibling) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &msibling) => 0; assert(msibling.u.m.weight == 2); - lfsr_mdir_get(&lfs, &msibling, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &msibling, msibling.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "d", 1) == 0); // assert that our neighbors were updated correctly assert(!lfsr_mdir_isdropped(&left_neighbor.mdir)); - assert(left_neighbor.mdir.mid.bid == 0*lfsr_mbidweight(&lfs)); - assert(left_neighbor.mdir.mid.rid == 0); + assert(left_neighbor.mdir.mid == 0*lfsr_mbidweight(&lfs)+0); assert(memcmp(&left_neighbor.mdir.u.m, &mdir.u.m, sizeof(mdir.u.m)) == 0); assert(!lfsr_mdir_isdropped(&right_neighbor.mdir)); - assert(right_neighbor.mdir.mid.bid == 1*lfsr_mbidweight(&lfs)); - assert(right_neighbor.mdir.mid.rid == 1); + assert(right_neighbor.mdir.mid == 1*lfsr_mbidweight(&lfs)+1); assert(memcmp(&right_neighbor.mdir.u.m, &msibling.u.m, sizeof(msibling.u.m)) == 0); @@ -2998,27 +3021,28 @@ code = ''' // note we do this after uninlining! this is because uninlining may // aggresively split the mtree if there are already neighbors in the mdir lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(0, REG, +1, BUF("a", 1)), - LFSR_ATTR(2, REG, +1, BUF("b", 1)))) => 0; + LFSR_ATTR(mdir.mid+0, REG, +1, BUF("a", 1)), + LFSR_ATTR(mdir.mid+2, REG, +1, BUF("b", 1)))) => 0; // this test only works if these all fit in the mdir assert(lfsr_mtree_weight(&lfs) == 1*lfsr_mbidweight(&lfs)); assert(mdir.u.m.weight == 3); lfsr_openedmdir_t left_neighbor = { - .mdir={.mid=LFSR_MID(0, 0), .u.m=mdir.u.m}}; + .mdir={.mid=mdir.mid+0, .u.m=mdir.u.m}}; lfsr_openedmdir_t right_neighbor = { - .mdir={.mid=LFSR_MID(0, 2), .u.m=mdir.u.m}}; + .mdir={.mid=mdir.mid+2, .u.m=mdir.u.m}}; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); // now add another large entry to the mdir, forcing a split memset(buffer, 'e', SIZE); + mdir.mid = 0*lfsr_mbidweight(&lfs)+2; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(2, REG, +1, BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(mdir.mid, REG, +1, BUF(buffer, SIZE)))) => 0; // force mdir to compact mdir.u.r.rbyd.eoff = BLOCK_SIZE; @@ -3035,28 +3059,26 @@ code = ''' assert(memcmp(buffer, "c", 1) == 0); // assert that our entries are still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+1, &mdir) => 0; assert(mdir.u.m.weight == 2); - lfsr_mdir_get(&lfs, &mdir, 1, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "d", 1) == 0); lfsr_mdir_t msibling; - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &msibling) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &msibling) => 0; assert(msibling.u.m.weight == 2); - lfsr_mdir_get(&lfs, &msibling, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &msibling, msibling.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "e", 1) == 0); // assert that our neighbors were updated correctly assert(!lfsr_mdir_isdropped(&left_neighbor.mdir)); - assert(left_neighbor.mdir.mid.bid == 0*lfsr_mbidweight(&lfs)); - assert(left_neighbor.mdir.mid.rid == 0); + assert(left_neighbor.mdir.mid == 0*lfsr_mbidweight(&lfs)+0); assert(memcmp(&left_neighbor.mdir.u.m, &mdir.u.m, sizeof(mdir.u.m)) == 0); assert(!lfsr_mdir_isdropped(&right_neighbor.mdir)); - assert(right_neighbor.mdir.mid.bid == 1*lfsr_mbidweight(&lfs)); - assert(right_neighbor.mdir.mid.rid == 1); + assert(right_neighbor.mdir.mid == 1*lfsr_mbidweight(&lfs)+1); assert(memcmp(&right_neighbor.mdir.u.m, &msibling.u.m, sizeof(msibling.u.m)) == 0); @@ -3088,9 +3110,9 @@ code = ''' assert(lfsr_mtree_isinlined(&lfs)); lfsr_openedmdir_t left_neighbor = { - .mdir={.mid=LFSR_MID(0, 0), .u.m=lfs.mroot.u.m}}; + .mdir={.mid=0, .u.m=lfs.mroot.u.m}}; lfsr_openedmdir_t right_neighbor = { - .mdir={.mid=LFSR_MID(0, 1), .u.m=lfs.mroot.u.m}}; + .mdir={.mid=1, .u.m=lfs.mroot.u.m}}; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -3120,13 +3142,11 @@ code = ''' // assert that our neighbors were updated correctly assert(!lfsr_mdir_isdropped(&left_neighbor.mdir)); - assert(left_neighbor.mdir.mid.bid == 0); - assert(left_neighbor.mdir.mid.rid == 0); + assert(left_neighbor.mdir.mid == 0); assert(memcmp(&left_neighbor.mdir.u.m, &lfs.mroot.u.m, sizeof(lfs.mroot.u.m)) == 0); assert(!lfsr_mdir_isdropped(&right_neighbor.mdir)); - assert(right_neighbor.mdir.mid.bid == 0); - assert(right_neighbor.mdir.mid.rid == 1); + assert(right_neighbor.mdir.mid == 1); assert(memcmp(&right_neighbor.mdir.u.m, &lfs.mroot.u.m, sizeof(lfs.mroot.u.m)) == 0); @@ -3174,20 +3194,20 @@ code = ''' // note we do this after uninlining! this is because uninlining may // aggresively split the mtree if there are already neighbors in the mdir lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(0, REG, +1, BUF("a", 1)), - LFSR_ATTR(2, REG, +1, BUF("b", 1)))) => 0; + LFSR_ATTR(mdir.mid+0, REG, +1, BUF("a", 1)), + LFSR_ATTR(mdir.mid+2, REG, +1, BUF("b", 1)))) => 0; // this test only works if these all fit in the mdir assert(lfsr_mtree_weight(&lfs) == 1*lfsr_mbidweight(&lfs)); assert(mdir.u.m.weight == 3); lfsr_openedmdir_t left_neighbor = { - .mdir={.mid=LFSR_MID(0, 0), .u.m=mdir.u.m}}; + .mdir={.mid=mdir.mid+0, .u.m=mdir.u.m}}; lfsr_openedmdir_t right_neighbor = { - .mdir={.mid=LFSR_MID(0, 2), .u.m=mdir.u.m}}; + .mdir={.mid=mdir.mid+2, .u.m=mdir.u.m}}; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -3210,21 +3230,19 @@ code = ''' assert(memcmp(buffer, "c", 1) == 0); // assert that our entry is still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+1, &mdir) => 0; assert(mdir.u.m.weight == 3); - lfsr_mdir_get(&lfs, &mdir, 1, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "e", 1) == 0); // assert that our neighbors were updated correctly assert(!lfsr_mdir_isdropped(&left_neighbor.mdir)); - assert(left_neighbor.mdir.mid.bid == 0*lfsr_mbidweight(&lfs)); - assert(left_neighbor.mdir.mid.rid == 0); + assert(left_neighbor.mdir.mid == 0*lfsr_mbidweight(&lfs)+0); assert(memcmp(&left_neighbor.mdir.u.m, &mdir.u.m, sizeof(mdir.u.m)) == 0); assert(!lfsr_mdir_isdropped(&right_neighbor.mdir)); - assert(right_neighbor.mdir.mid.bid == 0*lfsr_mbidweight(&lfs)); - assert(right_neighbor.mdir.mid.rid == 2); + assert(right_neighbor.mdir.mid == 0*lfsr_mbidweight(&lfs)+2); assert(memcmp(&right_neighbor.mdir.u.m, &mdir.u.m, sizeof(mdir.u.m)) == 0); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); @@ -3267,11 +3285,11 @@ code = ''' // now force one of our siblings to split lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+1, &mdir) => 0; assert(mdir.u.m.weight == 1); memset(buffer, 'c', SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(1, REG, +1, BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(mdir.mid, REG, +1, BUF(buffer, SIZE)))) => 0; // force mdir to compact mdir.u.r.rbyd.eoff = BLOCK_SIZE; @@ -3285,24 +3303,24 @@ code = ''' // setup our neighbors lfsr_openedmdir_t left_neighbor; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &left_neighbor.mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, + &left_neighbor.mdir) => 0; assert(left_neighbor.mdir.u.m.weight == 1); - left_neighbor.mdir.mid.rid = 0; lfsr_openedmdir_t right_neighbor; - lfsr_mtree_lookup(&lfs, LFSR_MID(2*lfsr_mbidweight(&lfs), -1), &right_neighbor.mdir) => 0; + lfsr_mtree_lookup(&lfs, 2*lfsr_mbidweight(&lfs)+0, + &right_neighbor.mdir) => 0; assert(right_neighbor.mdir.u.m.weight == 1); - right_neighbor.mdir.mid.rid = 0; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); // cause middle mdir to split - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+1, &mdir) => 0; assert(mdir.u.m.weight == 1); memset(buffer, 'd', SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(1, REG, +1, BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(mdir.mid, REG, +1, BUF(buffer, SIZE)))) => 0; // force mdir to compact mdir.u.r.rbyd.eoff = BLOCK_SIZE; @@ -3313,14 +3331,12 @@ code = ''' // assert that our neighbors were updated correctly assert(!lfsr_mdir_isdropped(&left_neighbor.mdir)); - assert(left_neighbor.mdir.mid.bid == 0*lfsr_mbidweight(&lfs)); - assert(left_neighbor.mdir.mid.rid == 0); - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + assert(left_neighbor.mdir.mid == 0*lfsr_mbidweight(&lfs)+0); + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(memcmp(&left_neighbor.mdir.u.m, &mdir.u.m, sizeof(mdir.u.m)) == 0); - assert(right_neighbor.mdir.mid.bid == 3*lfsr_mbidweight(&lfs)); - assert(right_neighbor.mdir.mid.rid == 0); - lfsr_mtree_lookup(&lfs, LFSR_MID(3*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + assert(right_neighbor.mdir.mid == 3*lfsr_mbidweight(&lfs)+0); + lfsr_mtree_lookup(&lfs, 3*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(memcmp(&right_neighbor.mdir.u.m, &mdir.u.m, sizeof(mdir.u.m)) == 0); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); @@ -3363,11 +3379,11 @@ code = ''' // now force one of our siblings to split lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+1, &mdir) => 0; assert(mdir.u.m.weight == 1); memset(buffer, 'c', SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(1, REG, +1, BUF(buffer, SIZE)))) => 0; + LFSR_ATTR(mdir.mid, REG, +1, BUF(buffer, SIZE)))) => 0; // force mdir to compact mdir.u.r.rbyd.eoff = BLOCK_SIZE; @@ -3381,38 +3397,36 @@ code = ''' // setup our neighbors lfsr_openedmdir_t left_neighbor; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &left_neighbor.mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, + &left_neighbor.mdir) => 0; assert(left_neighbor.mdir.u.m.weight == 1); - left_neighbor.mdir.mid.rid = 0; lfsr_openedmdir_t right_neighbor; - lfsr_mtree_lookup(&lfs, LFSR_MID(2*lfsr_mbidweight(&lfs), -1), &right_neighbor.mdir) => 0; + lfsr_mtree_lookup(&lfs, 2*lfsr_mbidweight(&lfs)+0, + &right_neighbor.mdir) => 0; assert(right_neighbor.mdir.u.m.weight == 1); - right_neighbor.mdir.mid.rid = 0; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); // cause middle mdir to drop - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(0, RM, -1, NULL))) => 0; + LFSR_ATTR(mdir.mid, RM, -1, NULL))) => 0; // we should now have 2 mdirs assert(lfsr_mtree_weight(&lfs) == 2*lfsr_mbidweight(&lfs)); // assert that our neighbors were updated correctly assert(!lfsr_mdir_isdropped(&left_neighbor.mdir)); - assert(left_neighbor.mdir.mid.bid == 0*lfsr_mbidweight(&lfs)); - assert(left_neighbor.mdir.mid.rid == 0); - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + assert(left_neighbor.mdir.mid == 0*lfsr_mbidweight(&lfs)+0); + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(memcmp(&left_neighbor.mdir.u.m, &mdir.u.m, sizeof(mdir.u.m)) == 0); assert(!lfsr_mdir_isdropped(&right_neighbor.mdir)); - assert(right_neighbor.mdir.mid.bid == 1*lfsr_mbidweight(&lfs)); - assert(right_neighbor.mdir.mid.rid == 0); - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + assert(right_neighbor.mdir.mid == 1*lfsr_mbidweight(&lfs)+0); + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(memcmp(&right_neighbor.mdir.u.m, &mdir.u.m, sizeof(mdir.u.m)) == 0); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); @@ -3459,7 +3473,7 @@ code = ''' // a bit hacky, but this catches infinite loops assert(i < 2*1); - lfsr_mid_t mid_; + lfs_ssize_t mid_; lfsr_tag_t tag_; lfsr_data_t data_; int err = lfsr_mtree_traversal_next(&lfs, &traversal, @@ -3471,9 +3485,8 @@ code = ''' if (tag_ == LFSR_TAG_BTREE) { lfsr_rbyd_t *branch = (lfsr_rbyd_t *)data_.u.b.buffer; - printf("traversal: %d.%d 0x%x btree 0x%x.%x\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x btree 0x%x.%x\n", + mid_, tag_, branch->block, branch->trunk); @@ -3481,9 +3494,8 @@ code = ''' seen[branch->block / 8] |= 1 << (branch->block % 8); } else if (tag_ == LFSR_TAG_MDIR) { lfsr_mdir_t *mdir = (lfsr_mdir_t*)data_.u.b.buffer; - printf("traversal: %d.%d 0x%x mdir 0x{%x,%x}\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x mdir 0x{%x,%x}\n", + mid_, tag_, mdir->u.m.blocks[0], mdir->u.m.blocks[1]); @@ -3492,9 +3504,8 @@ code = ''' seen[mdir->u.m.blocks[0] / 8] |= 1 << (mdir->u.m.blocks[0] % 8); } else { // this shouldn't happen - printf("traversal: %d.%d 0x%x %d\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x %d\n", + mid_, tag_, lfsr_data_size(&data_)); assert(false); @@ -3565,10 +3576,10 @@ code = ''' // assert that our entry is still in the mtree lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); @@ -3583,7 +3594,7 @@ code = ''' // a bit hacky, but this catches infinite loops assert(i < 2*2); - lfsr_mid_t mid_; + lfs_ssize_t mid_; lfsr_tag_t tag_; lfsr_data_t data_; int err = lfsr_mtree_traversal_next(&lfs, &traversal, @@ -3595,9 +3606,8 @@ code = ''' if (tag_ == LFSR_TAG_BTREE) { lfsr_rbyd_t *branch = (lfsr_rbyd_t *)data_.u.b.buffer; - printf("traversal: %d.%d 0x%x btree 0x%x.%x\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x btree 0x%x.%x\n", + mid_, tag_, branch->block, branch->trunk); @@ -3605,9 +3615,8 @@ code = ''' seen[branch->block / 8] |= 1 << (branch->block % 8); } else if (tag_ == LFSR_TAG_MDIR) { lfsr_mdir_t *mdir = (lfsr_mdir_t*)data_.u.b.buffer; - printf("traversal: %d.%d 0x%x mdir 0x{%x,%x}\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x mdir 0x{%x,%x}\n", + mid_, tag_, mdir->u.m.blocks[0], mdir->u.m.blocks[1]); @@ -3616,9 +3625,8 @@ code = ''' seen[mdir->u.m.blocks[0] / 8] |= 1 << (mdir->u.m.blocks[0] % 8); } else { // this shouldn't happen - printf("traversal: %d.%d 0x%x %d\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x %d\n", + mid_, tag_, lfsr_data_size(&data_)); assert(false); @@ -3649,10 +3657,10 @@ code = ''' assert(memcmp(buffer, "a", 1) == 0); // assert that our entry is still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); @@ -3694,16 +3702,16 @@ code = ''' // assert that our entries are still in the mtree lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "a", 1) == 0); lfsr_mdir_t msibling; - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &msibling) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &msibling) => 0; assert(msibling.u.m.weight == 1); - lfsr_mdir_get(&lfs, &msibling, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &msibling, msibling.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); @@ -3718,7 +3726,7 @@ code = ''' // a bit hacky, but this catches infinite loops assert(i < 2*3); - lfsr_mid_t mid_; + lfs_ssize_t mid_; lfsr_tag_t tag_; lfsr_data_t data_; int err = lfsr_mtree_traversal_next(&lfs, &traversal, @@ -3730,9 +3738,8 @@ code = ''' if (tag_ == LFSR_TAG_BTREE) { lfsr_rbyd_t *branch = (lfsr_rbyd_t *)data_.u.b.buffer; - printf("traversal: %d.%d 0x%x btree 0x%x.%x\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x btree 0x%x.%x\n", + mid_, tag_, branch->block, branch->trunk); @@ -3740,9 +3747,8 @@ code = ''' seen[branch->block / 8] |= 1 << (branch->block % 8); } else if (tag_ == LFSR_TAG_MDIR) { lfsr_mdir_t *mdir = (lfsr_mdir_t*)data_.u.b.buffer; - printf("traversal: %d.%d 0x%x mdir 0x{%x,%x}\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x mdir 0x{%x,%x}\n", + mid_, tag_, mdir->u.m.blocks[0], mdir->u.m.blocks[1]); @@ -3751,9 +3757,8 @@ code = ''' seen[mdir->u.m.blocks[0] / 8] |= 1 << (mdir->u.m.blocks[0] % 8); } else { // this shouldn't happen - printf("traversal: %d.%d 0x%x %d\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x %d\n", + mid_, tag_, lfsr_data_size(&data_)); assert(false); @@ -3779,15 +3784,15 @@ code = ''' assert(lfs.mroot.u.m.weight == 0); // assert that our entries are still in the mtree - lfsr_mtree_lookup(&lfs, LFSR_MID(0*lfsr_mbidweight(&lfs), -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, 0*lfsr_mbidweight(&lfs)+0, &mdir) => 0; assert(mdir.u.m.weight == 1); - lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "a", 1) == 0); - lfsr_mtree_lookup(&lfs, LFSR_MID(1*lfsr_mbidweight(&lfs), -1), &msibling) => 0; + lfsr_mtree_lookup(&lfs, 1*lfsr_mbidweight(&lfs)+0, &msibling) => 0; assert(msibling.u.m.weight == 1); - lfsr_mdir_get(&lfs, &msibling, 0, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &msibling, msibling.mid, LFSR_TAG_REG, buffer, SIZE) => SIZE; assert(memcmp(buffer, "b", 1) == 0); @@ -3845,7 +3850,7 @@ code = ''' // a bit hacky, but this catches infinite loops assert(i < 2*3); - lfsr_mid_t mid_; + lfs_ssize_t mid_; lfsr_tag_t tag_; lfsr_data_t data_; int err = lfsr_mtree_traversal_next(&lfs, &traversal, @@ -3857,9 +3862,8 @@ code = ''' if (tag_ == LFSR_TAG_BTREE) { lfsr_rbyd_t *branch = (lfsr_rbyd_t *)data_.u.b.buffer; - printf("traversal: %d.%d 0x%x btree 0x%x.%x\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x btree 0x%x.%x\n", + mid_, tag_, branch->block, branch->trunk); @@ -3867,9 +3871,8 @@ code = ''' seen[branch->block / 8] |= 1 << (branch->block % 8); } else if (tag_ == LFSR_TAG_MDIR) { lfsr_mdir_t *mdir = (lfsr_mdir_t*)data_.u.b.buffer; - printf("traversal: %d.%d 0x%x mdir 0x{%x,%x}\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x mdir 0x{%x,%x}\n", + mid_, tag_, mdir->u.m.blocks[0], mdir->u.m.blocks[1]); @@ -3878,9 +3881,8 @@ code = ''' seen[mdir->u.m.blocks[0] / 8] |= 1 << (mdir->u.m.blocks[0] % 8); } else { // this shouldn't happen - printf("traversal: %d.%d 0x%x %d\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x %d\n", + mid_, tag_, lfsr_data_size(&data_)); assert(false); @@ -3929,10 +3931,9 @@ code = ''' // create entries lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(lfs_smax32(lfsr_mtree_weight(&lfs)-1, 0), -1), + lfsr_mtree_lookup(&lfs, + lfs_smax32(lfsr_mtree_weight(&lfs) - lfsr_mbidweight(&lfs), 0), &mdir) => 0; - - mdir.mid.rid = 0; for (lfs_size_t i = 0; i < N; i++) { // force a compaction? if (FORCE_COMPACTION) { @@ -3941,29 +3942,31 @@ code = ''' } lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(mdir.mid.rid, REG, +1, + LFSR_ATTR(mdir.mid, REG, +1, BUF(&alphas[i % 26], 1)))) => 0; uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; assert(memcmp(buffer, &alphas[i % 26], 1) == 0); - mdir.mid.rid += 1; + mdir.mid += 1; } // try looking up each entry lfs_size_t i = 0; for (lfs_ssize_t mid = 0; - mid < lfs_smax32(lfsr_mtree_weight(&lfs), 1); + mid < lfs_smax32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs)); mid += lfsr_mbidweight(&lfs)) { lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; - for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; - mdir.mid.rid++) { + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + for (; (mdir.mid & lfsr_mridmask(&lfs)) + < (lfs_ssize_t)mdir.u.m.weight; + mdir.mid += 1) { uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; assert(memcmp(buffer, &alphas[i % 26], 1) == 0); i += 1; @@ -3982,7 +3985,7 @@ code = ''' // a bit hacky, but this catches infinite loops assert(i < 2*(1+N)); - lfsr_mid_t mid_; + lfs_ssize_t mid_; lfsr_tag_t tag_; lfsr_data_t data_; int err = lfsr_mtree_traversal_next(&lfs, &traversal, @@ -3994,9 +3997,8 @@ code = ''' if (tag_ == LFSR_TAG_BTREE) { lfsr_rbyd_t *branch = (lfsr_rbyd_t *)data_.u.b.buffer; - printf("traversal: %d.%d 0x%x btree 0x%x.%x\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x btree 0x%x.%x\n", + mid_, tag_, branch->block, branch->trunk); @@ -4004,9 +4006,8 @@ code = ''' seen[branch->block / 8] |= 1 << (branch->block % 8); } else if (tag_ == LFSR_TAG_MDIR) { lfsr_mdir_t *mdir = (lfsr_mdir_t*)data_.u.b.buffer; - printf("traversal: %d.%d 0x%x mdir 0x{%x,%x}\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x mdir 0x{%x,%x}\n", + mid_, tag_, mdir->u.m.blocks[0], mdir->u.m.blocks[1]); @@ -4015,9 +4016,8 @@ code = ''' seen[mdir->u.m.blocks[0] / 8] |= 1 << (mdir->u.m.blocks[0] % 8); } else { // this shouldn't happen - printf("traversal: %d.%d 0x%x %d\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x %d\n", + mid_, tag_, lfsr_data_size(&data_)); assert(false); @@ -4040,15 +4040,17 @@ code = ''' // try looking up each entry i = 0; for (lfs_ssize_t mid = 0; - mid < lfs_smax32(lfsr_mtree_weight(&lfs), 1); + mid < lfs_smax32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs)); mid += lfsr_mbidweight(&lfs)) { lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; - for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; - mdir.mid.rid++) { + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + for (; (mdir.mid & lfsr_mridmask(&lfs)) + < (lfs_ssize_t)mdir.u.m.weight; + mdir.mid += 1) { uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; assert(memcmp(buffer, &alphas[i % 26], 1) == 0); i += 1; @@ -4083,12 +4085,15 @@ code = ''' for (lfs_size_t i = 0; i < N; i++) { // choose a pseudo-random mid lfs_ssize_t mid = (lfs_ssize_t)( - TEST_PRNG(&prng) % lfs_max32(lfsr_mtree_weight(&lfs), 1)); + TEST_PRNG(&prng) % lfs_max32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs))); // fetch mdir lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; - // choose a pseudo-random rid - mdir.mid.rid = TEST_PRNG(&prng) % (mdir.u.m.weight+1); + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + // limit our mid to our mdir's weight + mdir.mid = (mdir.mid & lfsr_mbidmask(&lfs)) + | (mdir.mid % (mdir.u.m.weight+1)); // force a compaction? if (FORCE_COMPACTION) { @@ -4098,12 +4103,12 @@ code = ''' // add to rbyd, potentially splitting the mdir lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( - LFSR_ATTR(mdir.mid.rid, REG, +1, + LFSR_ATTR(mdir.mid, REG, +1, BUF(&alphas[i % 26], 1)))) => 0; // make sure we can look up the new entry uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; assert(memcmp(buffer, &alphas[i % 26], 1) == 0); @@ -4114,15 +4119,17 @@ code = ''' lfs_size_t count_ = 0; for (lfs_ssize_t mid = 0; - mid < lfs_smax32(lfsr_mtree_weight(&lfs), 1); + mid < lfs_smax32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs)); mid += lfsr_mbidweight(&lfs)) { lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; - for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; - mdir.mid.rid++) { + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + for (; (mdir.mid & lfsr_mridmask(&lfs)) + < (lfs_ssize_t)mdir.u.m.weight; + mdir.mid += 1) { uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; count_ += 1; @@ -4145,7 +4152,7 @@ code = ''' // a bit hacky, but this catches infinite loops assert(i < 2*(1+N)); - lfsr_mid_t mid_; + lfs_ssize_t mid_; lfsr_tag_t tag_; lfsr_data_t data_; int err = lfsr_mtree_traversal_next(&lfs, &traversal, @@ -4157,9 +4164,8 @@ code = ''' if (tag_ == LFSR_TAG_BTREE) { lfsr_rbyd_t *branch = (lfsr_rbyd_t *)data_.u.b.buffer; - printf("traversal: %d.%d 0x%x btree 0x%x.%x\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x btree 0x%x.%x\n", + mid_, tag_, branch->block, branch->trunk); @@ -4167,9 +4173,8 @@ code = ''' seen[branch->block / 8] |= 1 << (branch->block % 8); } else if (tag_ == LFSR_TAG_MDIR) { lfsr_mdir_t *mdir = (lfsr_mdir_t*)data_.u.b.buffer; - printf("traversal: %d.%d 0x%x mdir 0x{%x,%x}\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x mdir 0x{%x,%x}\n", + mid_, tag_, mdir->u.m.blocks[0], mdir->u.m.blocks[1]); @@ -4178,9 +4183,8 @@ code = ''' seen[mdir->u.m.blocks[0] / 8] |= 1 << (mdir->u.m.blocks[0] % 8); } else { // this shouldn't happen - printf("traversal: %d.%d 0x%x %d\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x %d\n", + mid_, tag_, lfsr_data_size(&data_)); assert(false); @@ -4204,15 +4208,17 @@ code = ''' count_ = 0; for (lfs_ssize_t mid = 0; - mid < lfs_smax32(lfsr_mtree_weight(&lfs), 1); + mid < lfs_smax32( + lfsr_mtree_weight(&lfs), + lfsr_mbidweight(&lfs)); mid += lfsr_mbidweight(&lfs)) { lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; - for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; - mdir.mid.rid++) { + lfsr_mtree_lookup(&lfs, mid, &mdir) => 0; + for (; (mdir.mid & lfsr_mridmask(&lfs)) + < (lfs_ssize_t)mdir.u.m.weight; + mdir.mid += 1) { uint8_t buffer[4]; - lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_REG, + lfsr_mdir_get(&lfs, &mdir, mdir.mid, LFSR_TAG_REG, buffer, 4) => 1; count_ += 1; @@ -4252,7 +4258,7 @@ code = ''' // assert that we detect the cycle in a reasonable number of iterations assert(i < 1024); - lfsr_mid_t mid_; + lfs_ssize_t mid_; lfsr_tag_t tag_; lfsr_data_t data_; int err = lfsr_mtree_traversal_next(&lfs, &traversal, @@ -4264,23 +4270,20 @@ code = ''' if (tag_ == LFSR_TAG_BTREE) { lfsr_rbyd_t *branch = (lfsr_rbyd_t *)data_.u.b.buffer; - printf("traversal: %d.%d 0x%x btree 0x%x.%x\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x btree 0x%x.%x\n", + mid_, tag_, branch->block, branch->trunk); } else if (tag_ == LFSR_TAG_MDIR) { lfsr_mdir_t *mdir = (lfsr_mdir_t*)data_.u.b.buffer; - printf("traversal: %d.%d 0x%x mdir 0x{%x,%x}\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x mdir 0x{%x,%x}\n", + mid_, tag_, mdir->u.m.blocks[0], mdir->u.m.blocks[1]); } else { // this shouldn't happen - printf("traversal: %d.%d 0x%x %d\n", - mid_.bid, - mid_.rid, + printf("traversal: %d 0x%x %d\n", + mid_, tag_, lfsr_data_size(&data_)); assert(false);