From fe941ef44301c1d1030f194ab7f78597f661def1 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sat, 5 Aug 2023 14:05:17 -0500 Subject: [PATCH] Reworked rbyd/btree/mdir structs to allow better access to subcomponents This turned out to be tricky. At littlefs's core, we have the lfsr_rbyd_t struct. It is really important this is as small as possible since littlefs creates many rbyd copies in order to track state of metadata on disk. Wrapping rbyd, we have the lfsr_btree_t struct, which can alternatively contain a single inlined entry, accomplished by overlapping the width field in both cases. And the lfsr_mdir_t struct, which tracks any redundant blocks, and would be nice if the blocks lined up as neighbors so all blocks involved in the mdir could be passed around as an array. Both of these wrappers attempt to overlap fields of the lfsr_rbyd_t struct, which presents a bit of a problem. The solution here is to put the rbyd block field at the beginning of the lfsr_rbyd_t struct, and use exactly 32-bits of padding in lfsr_btree_t to overlap the width field even though it is not at the beginning of the struct. To avoid inflating the lfsr_btree_t size, we sneak the inlined size and tag into the overlapping padding. This will need special handling if the size of these fields change, but saves a decent amount of RAM: lfsr_rbyd_t lfsr_btree_t lfsr_mdir_t 8b 8b 8b 8b .----+----+----+----. | mid.bid | mid.rid | |----+----+----+----| 8b 8b 8b 8b 8b 8b 8b 8b | blocks | .----+----+----+----. .----+----+----+----. | | | block |..| tag |size|padd|.>| | |----+----+----+----| |----+----+----+----| |----+----+----+----| | weight |.>| weight | | weight | |----+----+----+----| |----+----+----+----| |----+----+----+----| | trunk | | inlined data | | trunk | |----+----+----+----| | | | |----+----+----+----| | off | | v | | off | |----+----+----+----| | | |----+----+----+----| | crc | | | | crc | '----+----+----+----' '----+----+----+----' '----+----+----+----' Also tried to reduce the amount of mdir usage in lfsr_mdir_commit by better using only the arrays of relevant mdir blocks, to limited success. --- lfs.c | 596 ++++++++++++++++------------------ lfs.h | 68 ++-- lfs_util.h | 43 ++- tests/test_alloc.toml | 2 +- tests/test_btree.toml | 390 +++++++++++------------ tests/test_mtree.toml | 719 +++++++++++++++++++++--------------------- 6 files changed, 907 insertions(+), 911 deletions(-) diff --git a/lfs.c b/lfs.c index eb53b430..8d607e23 100644 --- a/lfs.c +++ b/lfs.c @@ -1530,7 +1530,7 @@ static lfs_ssize_t lfsr_fcrc_fromdisk(lfs_t *lfs, lfsr_fcrc_t *fcrc, /// Metadata-id things /// -#define LFSR_MID(_bid, _rid) ((lfsr_mid_t){_bid, _rid}) +#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) { union { lfsr_mid_t mid; lfs_ssize_t w; } a_u = {.mid=a}; @@ -1644,7 +1644,7 @@ static int lfsr_grm_todisk(lfs_t *lfs, const lfsr_grm_t *grm, } // needed in lfsr_grm_fromdisk -static inline int lfsr_mtree_isinlined(lfs_t *lfs); +static inline bool lfsr_mtree_isinlined(lfs_t *lfs); static inline lfs_size_t lfsr_mtree_weight(lfs_t *lfs); static int lfsr_grm_fromdisk(lfs_t *lfs, lfsr_grm_t *grm, @@ -2754,7 +2754,7 @@ static int lfsr_rbyd_appendall(lfs_t *lfs, lfsr_rbyd_t *rbyd, lfs_ssize_t rid; lfsr_data_t data; int err = lfsr_rbyd_lookupnext(lfs, - &attrs[i].d.mdir->m.rbyd, + &attrs[i].d.mdir->u.r.rbyd, attrs[i].d.mdir->mid.rid, lfsr_tag_next(tag), &rid, &tag, NULL, &data); if (err && err != LFS_ERR_NOENT) { @@ -3495,51 +3495,47 @@ static int lfsr_rbyd_dnamelookup(lfs_t *lfs, const lfsr_rbyd_t *rbyd, // convenience operations // TODO need null btrees? -#define LFSR_BTREE_NULL ((lfsr_btree_t){.weight=0x80000000}) +#define LFSR_BTREE_NULL ((lfsr_btree_t){.u.b.weight=0x80000000}) static inline bool lfsr_btree_isinlined(const lfsr_btree_t *btree) { - return btree->weight & 0x80000000; -} - -static inline bool lfsr_btree_isnull(const lfsr_btree_t *btree) { - return btree->weight == 0x80000000; + return btree->u.b.weight & 0x80000000; } static inline lfs_size_t lfsr_btree_weight(const lfsr_btree_t *btree) { - return btree->weight & 0x7fffffff; + return btree->u.b.weight & 0x7fffffff; } -static inline lfs_size_t lfsr_btree_setinlined(lfs_size_t weight) { - return weight | 0x80000000; +static inline bool lfsr_btree_isnull(const lfsr_btree_t *btree) { + return btree->u.b.weight == 0x80000000; } -// bptr on-disk encoding +// branch on-disk encoding // 1 crc32c + 3 leb128 => 19 bytes (worst case) -#define LFSR_BPTR_DSIZE (4+5+5+5) +#define LFSR_BRANCH_DSIZE (4+5+5+5) -static lfs_ssize_t lfsr_bptr_todisk(lfs_t *lfs, const lfsr_rbyd_t *bptr, - uint8_t buffer[static LFSR_BPTR_DSIZE]) { +static lfs_ssize_t lfsr_branch_todisk(lfs_t *lfs, const lfsr_rbyd_t *branch, + uint8_t buffer[static LFSR_BRANCH_DSIZE]) { (void)lfs; lfs_ssize_t d = 0; - lfs_tole32_(bptr->crc, &buffer[d]); + lfs_tole32_(branch->crc, &buffer[d]); d += 4; - lfs_ssize_t d_ = lfs_toleb128(bptr->weight, &buffer[d], 5); + lfs_ssize_t d_ = lfs_toleb128(branch->weight, &buffer[d], 5); if (d_ < 0) { return d_; } d += d_; - d_ = lfs_toleb128(bptr->trunk, &buffer[d], 5); + d_ = lfs_toleb128(branch->trunk, &buffer[d], 5); if (d_ < 0) { return d_; } d += d_; - d_ = lfs_toleb128(bptr->block, &buffer[d], 5); + d_ = lfs_toleb128(branch->block, &buffer[d], 5); if (d_ < 0) { return d_; } @@ -3548,32 +3544,32 @@ static lfs_ssize_t lfsr_bptr_todisk(lfs_t *lfs, const lfsr_rbyd_t *bptr, return d; } -static lfs_ssize_t lfsr_bptr_fromdisk(lfs_t *lfs, lfsr_rbyd_t *bptr, +static lfs_ssize_t lfsr_branch_fromdisk(lfs_t *lfs, lfsr_rbyd_t *branch, lfsr_data_t data) { // setting off to 0 here will trigger asserts if we try to append // without fetching first - bptr->off = 0; + branch->off = 0; lfs_ssize_t d = 0; - lfs_ssize_t d_ = lfsr_data_readle32(lfs, data, d, &bptr->crc); + lfs_ssize_t d_ = lfsr_data_readle32(lfs, data, d, &branch->crc); if (d_ < 0) { return d_; } d += d_; - d_ = lfsr_data_readleb128(lfs, data, d, &bptr->weight); + d_ = lfsr_data_readleb128(lfs, data, d, &branch->weight); if (d_ < 0) { return d_; } d += d_; - d_ = lfsr_data_readleb128(lfs, data, d, &bptr->trunk); + d_ = lfsr_data_readleb128(lfs, data, d, &branch->trunk); if (d_ < 0) { return d_; } d += d_; - d_ = lfsr_data_readleb128(lfs, data, d, &bptr->block); + d_ = lfsr_data_readleb128(lfs, data, d, &branch->block); if (d_ < 0) { return d_; } @@ -3586,8 +3582,8 @@ static lfs_ssize_t lfsr_bptr_fromdisk(lfs_t *lfs, lfsr_rbyd_t *bptr, // // note we leave disambiguating inlined/non-inlined btrees up to the caller #define LFSR_BTREE_DSIZE ( \ - LFSR_BPTR_DSIZE > LFSR_BTREE_INLINESIZE \ - ? LFSR_BPTR_DSIZE \ + LFSR_BRANCH_DSIZE > LFSR_BTREE_INLINESIZE \ + ? LFSR_BRANCH_DSIZE \ : LFSR_BTREE_INLINESIZE) static lfs_ssize_t lfsr_btree_todisk(lfs_t *lfs, const lfsr_btree_t *btree, @@ -3599,13 +3595,13 @@ static lfs_ssize_t lfsr_btree_todisk(lfs_t *lfs, const lfsr_btree_t *btree, return 0; // inlined? } else if (lfsr_btree_isinlined(btree)) { - *tag_ = lfsr_tag_setwide(btree->inlined.tag); - memcpy(buffer, btree->inlined.buffer, btree->inlined.size); - return btree->inlined.size; + *tag_ = lfsr_tag_setwide(btree->u.i.tag); + memcpy(buffer, btree->u.i.buffer, btree->u.i.size); + return btree->u.i.size; // not inlined } else { *tag_ = lfsr_tag_setwide(btree_tag); - return lfsr_bptr_todisk(lfs, &btree->root, buffer); + return lfsr_branch_todisk(lfs, &btree->u.r.rbyd, buffer); } } @@ -3615,19 +3611,20 @@ static lfs_ssize_t lfsr_btree_fromdisk(lfs_t *lfs, lfsr_btree_t *btree, lfsr_tag_t tag, lfs_size_t weight, lfsr_data_t data) { // inlined? if (tag != btree_tag) { - btree->weight = lfsr_btree_setinlined(weight); - btree->inlined.tag = tag; + // mark as inlined + btree->u.i.weight = 0x80000000 | weight; + btree->u.i.tag = tag; lfs_ssize_t size = lfsr_data_read(lfs, data, 0, - btree->inlined.buffer, LFSR_BTREE_INLINESIZE); + btree->u.i.buffer, LFSR_BTREE_INLINESIZE); if (size < 0) { return size; } - btree->inlined.size = size; + btree->u.i.size = size; return size; // not inlined } else { - return lfsr_bptr_fromdisk(lfs, &btree->root, data); + return lfsr_branch_fromdisk(lfs, &btree->u.r.rbyd, data); } } @@ -3650,19 +3647,19 @@ static int lfsr_btree_lookupnext_(lfs_t *lfs, *bid_ = lfsr_btree_weight(btree)-1; } if (tag_) { - *tag_ = btree->inlined.tag; + *tag_ = btree->u.i.tag; } if (weight_) { *weight_ = lfsr_btree_weight(btree); } if (data_) { - *data_ = LFSR_DATA_BUF(btree->inlined.buffer, btree->inlined.size); + *data_ = LFSR_DATA_BUF(btree->u.i.buffer, btree->u.i.size); } return 0; } // descend down the btree looking for our bid - lfsr_rbyd_t branch = btree->root; + lfsr_rbyd_t branch = btree->u.r.rbyd; lfs_ssize_t rid = bid; while (true) { // each branch is a pair of optional name + on-disk structure @@ -3695,7 +3692,7 @@ static int lfsr_btree_lookupnext_(lfs_t *lfs, rid -= (rid__ - (weight__-1)); // fetch the next branch - lfs_ssize_t d = lfsr_bptr_fromdisk(lfs, &branch, data__); + lfs_ssize_t d = lfsr_branch_fromdisk(lfs, &branch, data__); if (d < 0) { return d; } @@ -3777,13 +3774,13 @@ static int lfsr_btree_parent(lfs_t *lfs, // inlined? root? if (bid >= lfsr_btree_weight(btree) || lfsr_btree_isinlined(btree) - || (btree->root.block == child->block - && btree->root.trunk == child->trunk)) { + || (btree->u.r.rbyd.block == child->block + && btree->u.r.rbyd.trunk == child->trunk)) { return LFS_ERR_NOENT; } // descend down the btree looking for our id - lfsr_rbyd_t branch = btree->root; + lfsr_rbyd_t branch = btree->u.r.rbyd; lfs_ssize_t rid = bid; while (true) { // each branch is a pair of optional name + on-disk structure @@ -3820,7 +3817,7 @@ static int lfsr_btree_parent(lfs_t *lfs, // fetch the next branch lfsr_rbyd_t branch_; - lfs_ssize_t d = lfsr_bptr_fromdisk(lfs, &branch_, data__); + lfs_ssize_t d = lfsr_branch_fromdisk(lfs, &branch_, data__); if (d < 0) { return d; } @@ -3850,7 +3847,7 @@ static int lfsr_btree_parent(lfs_t *lfs, // array allocations #define LFSR_BTREE_SCRATCHATTRS ( \ 4 \ - + ((2*LFSR_BPTR_DSIZE) + sizeof(lfsr_attr_t)-1) \ + + ((2*LFSR_BRANCH_DSIZE) + sizeof(lfsr_attr_t)-1) \ / sizeof(lfsr_attr_t)) // this macro creates an attr list with enough reserved space for @@ -3922,7 +3919,7 @@ static int lfsr_btree_commit(lfs_t *lfs, // cannibalize some attributes in our attr list to store // our branch uint8_t *scratch_buf = (uint8_t*)&attrs[2]; - lfs_ssize_t d = lfsr_bptr_todisk(lfs, rbyd, scratch_buf); + lfs_ssize_t d = lfsr_branch_todisk(lfs, rbyd, scratch_buf); if (d < 0) { return d; } @@ -4033,7 +4030,7 @@ static int lfsr_btree_commit(lfs_t *lfs, // cannibalize some attributes in our attr list to store // our branch scratch_buf = (uint8_t*)&attrs[2]; - d = lfsr_bptr_todisk(lfs, rbyd, scratch_buf); + d = lfsr_branch_todisk(lfs, rbyd, scratch_buf); if (d < 0) { return d; } @@ -4141,12 +4138,12 @@ static int lfsr_btree_commit(lfs_t *lfs, // cannibalize some attributes in our attr list to store // our branches uint8_t *scratch_buf1 = (uint8_t*)&attrs[4]; - uint8_t *scratch_buf2 = (uint8_t*)&attrs[4] + LFSR_BPTR_DSIZE; - lfs_ssize_t d1 = lfsr_bptr_todisk(lfs, &rbyd_, scratch_buf1); + uint8_t *scratch_buf2 = (uint8_t*)&attrs[4] + LFSR_BRANCH_DSIZE; + lfs_ssize_t d1 = lfsr_branch_todisk(lfs, &rbyd_, scratch_buf1); if (d1 < 0) { return d1; } - lfs_ssize_t d2 = lfsr_bptr_todisk(lfs, &sibling, scratch_buf2); + lfs_ssize_t d2 = lfsr_branch_todisk(lfs, &sibling, scratch_buf2); if (d2 < 0) { return d2; } @@ -4266,7 +4263,7 @@ static int lfsr_btree_commit(lfs_t *lfs, continue; } - d = lfsr_bptr_fromdisk(lfs, &sibling, sdata); + d = lfsr_branch_fromdisk(lfs, &sibling, sdata); if (d < 0) { return d; } @@ -4386,7 +4383,7 @@ static int lfsr_btree_commit(lfs_t *lfs, // cannibalize some attributes in our attr list to store // our branch uint8_t *scratch_buf = (uint8_t*)&attrs[3]; - lfs_ssize_t d = lfsr_bptr_todisk(lfs, &rbyd_, scratch_buf); + lfs_ssize_t d = lfsr_branch_todisk(lfs, &rbyd_, scratch_buf); if (d < 0) { return d; } @@ -4405,7 +4402,7 @@ static int lfsr_btree_commit(lfs_t *lfs, } // at this point rbyd should be the trunk of our tree - btree->root = *rbyd; + btree->u.r.rbyd = *rbyd; return false; } @@ -4417,16 +4414,17 @@ static int lfsr_btree_push(lfs_t *lfs, lfsr_btree_t *btree, if (lfsr_btree_isinlined(btree) && lfsr_btree_weight(btree) == 0) { LFS_ASSERT(bid == 0); - btree->weight = lfsr_btree_setinlined(weight); - btree->inlined.tag = tag; + // mark as inlined + btree->u.i.weight = 0x80000000 | weight; + btree->u.i.tag = tag; lfs_ssize_t d = lfsr_data_read(lfs, data, 0, - btree->inlined.buffer, LFSR_BTREE_INLINESIZE); + btree->u.i.buffer, LFSR_BTREE_INLINESIZE); if (d < 0) { return d; } LFS_ASSERT(d <= LFSR_BTREE_INLINESIZE); - btree->inlined.size = d; + btree->u.i.size = d; return 0; // inlined btree, need to expand into an rbyd @@ -4439,14 +4437,14 @@ static int lfsr_btree_push(lfs_t *lfs, lfsr_btree_t *btree, // commit our entries err = lfsr_rbyd_commit(lfs, &rbyd, LFSR_ATTRS( - LFSR_ATTR_(0, btree->inlined.tag, +lfsr_btree_weight(btree), - btree->inlined.buffer, btree->inlined.size), + LFSR_ATTR_(0, btree->u.i.tag, +lfsr_btree_weight(btree), + btree->u.i.buffer, btree->u.i.size), LFSR_ATTR_DATA_(bid, tag, +weight, data))); if (err) { return err; } - btree->root = rbyd; + btree->u.r.rbyd = rbyd; return 0; // a normal btree @@ -4461,7 +4459,7 @@ static int lfsr_btree_push(lfs_t *lfs, lfsr_btree_t *btree, // since we defer inlining until compaction time lfs_size_t bid_ = lfs_min32(bid, lfs_smax32(lfsr_btree_weight(btree)-1, 0)); - lfsr_rbyd_t rbyd = btree->root; + lfsr_rbyd_t rbyd = btree->u.r.rbyd; lfs_ssize_t rid = -1; lfs_size_t rweight = 0; int err = lfsr_btree_lookupnext_(lfs, btree, bid_, @@ -4488,16 +4486,17 @@ static int lfsr_btree_push(lfs_t *lfs, lfsr_btree_t *btree, // revert to an inlined btree if (degenerate) { - btree->weight = lfsr_btree_setinlined(weight); - btree->inlined.tag = tag; + // mark as inlined + btree->u.i.weight = 0x80000000 | weight; + btree->u.i.tag = tag; lfs_ssize_t d = lfsr_data_read(lfs, data, 0, - btree->inlined.buffer, LFSR_BTREE_INLINESIZE); + btree->u.i.buffer, LFSR_BTREE_INLINESIZE); if (d < 0) { return d; } LFS_ASSERT(d <= LFSR_BTREE_INLINESIZE); - btree->inlined.size = d; + btree->u.i.size = d; } return 0; @@ -4513,16 +4512,17 @@ static int lfsr_btree_set(lfs_t *lfs, lfsr_btree_t *btree, if (lfsr_btree_isinlined(btree)) { LFS_ASSERT(bid == lfsr_btree_weight(btree)-1); - btree->weight = lfsr_btree_setinlined(weight); - btree->inlined.tag = tag; + // mark as inlined + btree->u.i.weight = 0x80000000 | weight; + btree->u.i.tag = tag; lfs_ssize_t d = lfsr_data_read(lfs, data, 0, - btree->inlined.buffer, LFSR_BTREE_INLINESIZE); + btree->u.i.buffer, LFSR_BTREE_INLINESIZE); if (d < 0) { return d; } LFS_ASSERT(d <= LFSR_BTREE_INLINESIZE); - btree->inlined.size = d; + btree->u.i.size = d; return 0; // a normal btree @@ -4553,16 +4553,17 @@ static int lfsr_btree_set(lfs_t *lfs, lfsr_btree_t *btree, // revert to an inlined btree if (degenerate) { - btree->weight = lfsr_btree_setinlined(weight); - btree->inlined.tag = tag; + // mark as inlined + btree->u.i.weight = 0x80000000 | weight; + btree->u.i.tag = tag; lfs_ssize_t d = lfsr_data_read(lfs, data, 0, - btree->inlined.buffer, LFSR_BTREE_INLINESIZE); + btree->u.i.buffer, LFSR_BTREE_INLINESIZE); if (d < 0) { return d; } LFS_ASSERT(d <= LFSR_BTREE_INLINESIZE); - btree->inlined.size = d; + btree->u.i.size = d; } return 0; @@ -4576,7 +4577,7 @@ static int lfsr_btree_pop(lfs_t *lfs, lfsr_btree_t *btree, lfs_size_t bid) { // inlined btree? if (lfsr_btree_isinlined(btree)) { LFS_ASSERT(bid == lfsr_btree_weight(btree)-1); - btree->weight = lfsr_btree_setinlined(0); + *btree = LFSR_BTREE_NULL; return 0; // a normal btree @@ -4607,7 +4608,7 @@ static int lfsr_btree_pop(lfs_t *lfs, lfsr_btree_t *btree, lfs_size_t bid) { // revert to a null btree if (degenerate && rweight >= rbyd.weight) { - btree->weight = lfsr_btree_setinlined(0); + *btree = LFSR_BTREE_NULL; // revert to an inlined btree } else if (degenerate) { @@ -4640,16 +4641,17 @@ static int lfsr_btree_pop(lfs_t *lfs, lfsr_btree_t *btree, lfs_size_t bid) { } LFS_ASSERT(sweight+rweight == rbyd.weight); - btree->weight = lfsr_btree_setinlined(sweight); - btree->inlined.tag = stag; + // mark as inlined + btree->u.i.weight = 0x80000000 | sweight; + btree->u.i.tag = stag; LFS_ASSERT(lfsr_data_size(sdata) <= LFSR_BTREE_INLINESIZE); err = lfsr_bd_read(lfs, sdata.disk.block, sdata.disk.off, 0, - btree->inlined.buffer, lfsr_data_size(sdata)); + btree->u.i.buffer, lfsr_data_size(sdata)); if (err) { return err; } - btree->inlined.size = lfsr_data_size(sdata); + btree->u.i.size = lfsr_data_size(sdata); } return 0; @@ -4690,7 +4692,7 @@ static int lfsr_btree_split(lfs_t *lfs, lfsr_btree_t *btree, return err; } - btree->root = rbyd; + btree->u.r.rbyd = rbyd; return 0; // a normal btree @@ -4748,19 +4750,19 @@ static int lfsr_btree_dnamelookup(lfs_t *lfs, const lfsr_btree_t *btree, *bid_ = lfsr_btree_weight(btree)-1; } if (tag_) { - *tag_ = btree->inlined.tag; + *tag_ = btree->u.i.tag; } if (weight_) { *weight_ = lfsr_btree_weight(btree); } if (data_) { - *data_ = LFSR_DATA_BUF(btree->inlined.buffer, btree->inlined.size); + *data_ = LFSR_DATA_BUF(btree->u.i.buffer, btree->u.i.size); } return 0; } // descend down the btree looking for our name - lfsr_rbyd_t branch = btree->root; + lfsr_rbyd_t branch = btree->u.r.rbyd; lfs_ssize_t bid = 0; while (true) { // lookup our name in the rbyd via binary search @@ -4788,7 +4790,7 @@ static int lfsr_btree_dnamelookup(lfs_t *lfs, const lfsr_btree_t *btree, bid += rid__ - (weight__-1); // fetch the next branch - lfs_ssize_t d = lfsr_bptr_fromdisk(lfs, &branch, data__); + lfs_ssize_t d = lfsr_branch_fromdisk(lfs, &branch, data__); if (d < 0) { return d; } @@ -4852,14 +4854,13 @@ static int lfsr_btree_traversal_next(lfs_t *lfs, *bid_ = lfsr_btree_weight(btree)-1; } if (tag_) { - *tag_ = btree->inlined.tag; + *tag_ = btree->u.i.tag; } if (weight_) { *weight_ = lfsr_btree_weight(btree); } if (data_) { - *data_ = LFSR_DATA_BUF(btree->inlined.buffer, - btree->inlined.size); + *data_ = LFSR_DATA_BUF(btree->u.i.buffer, btree->u.i.size); } return 0; } @@ -4868,7 +4869,7 @@ static int lfsr_btree_traversal_next(lfs_t *lfs, if ((lfs_size_t)traversal->rid >= traversal->branch.weight) { traversal->bid += traversal->branch.weight; traversal->rid = traversal->bid; - traversal->branch = btree->root; + traversal->branch = btree->u.r.rbyd; if (traversal->rid == 0) { // TODO how many of these should be conditional? @@ -4922,7 +4923,7 @@ static int lfsr_btree_traversal_next(lfs_t *lfs, traversal->rid -= (rid__ - (weight__-1)); // fetch the next branch - lfs_ssize_t d = lfsr_bptr_fromdisk(lfs, + lfs_ssize_t d = lfsr_branch_fromdisk(lfs, &traversal->branch, data__); if (d < 0) { return d; @@ -4982,39 +4983,38 @@ static int lfsr_btree_traversal_next(lfs_t *lfs, /// Metadata pair operations /// -// mptr things -typedef struct lfsr_mptr { - lfs_block_t blocks[2]; -} lfsr_mptr_t; - -#define LFSR_MPTR(block0, block1) ((lfsr_mptr_t){.blocks={block0, block1}}) - // the mroot anchor, mdir 0x{0,1} is the entry point into the filesystem -#define LFSR_MPTR_MROOTANCHOR LFSR_MPTR(0, 1) +#define LFSR_MDIR_MROOTANCHOR ((const lfs_block_t[2]){0, 1}) -static inline int lfsr_mptr_cmp(lfsr_mptr_t a, lfsr_mptr_t b) { +static inline int lfsr_mdir_cmp( + const lfs_block_t a[static 2], + const lfs_block_t b[static 2]) { // allow either order - if ((a.blocks[0] == b.blocks[0] && a.blocks[1] == b.blocks[1]) - || (a.blocks[0] == b.blocks[1] && a.blocks[1] == b.blocks[0])) { + if ((a[0] == b[0] && a[1] == b[1]) + || (a[0] == b[1] && a[1] == b[0])) { return 0; } else { return 1; } } -static inline bool lfsr_mptr_ismrootanchor(lfsr_mptr_t a) { - return lfsr_mptr_cmp(a, LFSR_MPTR_MROOTANCHOR) == 0; +static inline bool lfsr_mdir_ismrootanchor( + const lfs_block_t blocks[static 2]) { + // mrootanchor is always at 0x{0,1} + // just check that the first block is in mroot anchor range + return blocks[0] <= 1; } // 2 leb128 => 10 bytes (worst case) -#define LFSR_MPTR_DSIZE (5+5) +#define LFSR_MDIR_DSIZE (5+5) -static lfs_ssize_t lfsr_mptr_todisk(lfs_t *lfs, lfsr_mptr_t mptr, - uint8_t buffer[static LFSR_MPTR_DSIZE]) { +static lfs_ssize_t lfsr_mdir_todisk(lfs_t *lfs, + const lfs_block_t blocks[static 2], + uint8_t buffer[static LFSR_MDIR_DSIZE]) { (void)lfs; lfs_ssize_t d = 0; for (int i = 0; i < 2; i++) { - lfs_ssize_t d_ = lfs_toleb128(mptr.blocks[i], &buffer[d], 5); + lfs_ssize_t d_ = lfs_toleb128(blocks[i], &buffer[d], 5); if (d_ < 0) { return d_; } @@ -5024,11 +5024,11 @@ static lfs_ssize_t lfsr_mptr_todisk(lfs_t *lfs, lfsr_mptr_t mptr, return d; } -static lfs_ssize_t lfsr_mptr_fromdisk(lfs_t *lfs, lfsr_mptr_t *mptr, - lfsr_data_t data) { +static lfs_ssize_t lfsr_mdir_fromdisk(lfs_t *lfs, + lfs_block_t blocks[static 2], lfsr_data_t data) { lfs_ssize_t d = 0; for (int i = 0; i < 2; i++) { - lfs_ssize_t d_ = lfsr_data_readleb128(lfs, data, d, &mptr->blocks[i]); + lfs_ssize_t d_ = lfsr_data_readleb128(lfs, data, d, &blocks[i]); if (d_ < 0) { return d_; } @@ -5038,28 +5038,8 @@ static lfs_ssize_t lfsr_mptr_fromdisk(lfs_t *lfs, lfsr_mptr_t *mptr, return d; } -// mdir things -static inline lfsr_mptr_t lfsr_mdir_mptr(const lfsr_mdir_t *mdir) { - return LFSR_MPTR(mdir->m.rbyd.block, mdir->m.redund_block); -} - -static inline int lfsr_mdir_cmp(const lfsr_mdir_t *a, const lfsr_mdir_t *b) { - return lfsr_mptr_cmp(lfsr_mdir_mptr(a), lfsr_mdir_mptr(b)); -} - -static inline bool lfsr_mdir_ismrootanchor(const lfsr_mdir_t *a) { - // mrootanchor is always at 0x{0,1} - // just check that at least one block is at 0x0 - return a->m.rbyd.block == 0 || a->m.redund_block == 0; -} - -static lfs_ssize_t lfsr_mdir_todisk(lfs_t *lfs, const lfsr_mdir_t *mdir, - uint8_t buffer[static LFSR_MPTR_DSIZE]) { - return lfsr_mptr_todisk(lfs, lfsr_mdir_mptr(mdir), buffer); -} - static inline bool lfsr_mdir_isdropped(const lfsr_mdir_t *mdir) { - return mdir->m.rbyd.trunk == 0; + return mdir->u.r.rbyd.trunk == 0; } // track opened mdirs that may need to by updated @@ -5091,57 +5071,18 @@ static bool lfsr_mdir_isopened(lfs_t *lfs, } - // actual mdir functions -static int lfsr_mdir_alloc(lfs_t *lfs, lfsr_mdir_t *mdir, lfsr_mid_t mid) { - // allocate two blocks - lfs_block_t blocks[2]; - for (int i = 0; i < 2; i++) { - int err = lfs_alloc(lfs, &blocks[i]); - if (err) { - return err; - } - } - - // rather than performing an unecessary erase, treat the current contents - // of the other block as a valid revision count - uint32_t rev; - int err = lfsr_bd_read(lfs, blocks[1], 0, 0, &rev, sizeof(uint32_t)); - if (err && err != LFS_ERR_CORRUPT) { - return err; - } - // note we can allow blocks that report corrupt here, with the assumption - // that all future reads will also return corrupt, this can happen if - // the underlying block device uses ECC that may be invalid when - // uninitialized - if (err == LFS_ERR_CORRUPT) { - rev = 0; - } - - // align revision count in new mdirs to our block_cycles, this makes sure - // we don't immediately try to relocate the mdir - if (lfs->cfg->block_cycles > 0) { - rev = lfs_alignup(rev+1, lfs->cfg->block_cycles)-1; - } - - // setup mdir struct - mdir->mid = mid; - mdir->m.redund_block = blocks[0]; - mdir->m.rbyd.weight = 0; - mdir->m.rbyd.block = blocks[1]; - // mark mdir as needing compaction - mdir->m.rbyd.off = -1; - mdir->m.rbyd.trunk = 0; - return 0; -} - static int lfsr_mdir_fetch(lfs_t *lfs, lfsr_mdir_t *mdir, - lfsr_mptr_t mptr, lfsr_mid_t mid) { + const lfs_block_t blocks[static 2], lfsr_mid_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 + lfs_block_t blocks_[2] = {blocks[0], blocks[1]}; // read both revision counts, try to figure out which block // has the most recent revision uint32_t revs[2] = {0, 0}; for (int i = 0; i < 2; i++) { - int err = lfsr_bd_read(lfs, mptr.blocks[0], 0, 0, + int err = lfsr_bd_read(lfs, blocks_[0], 0, 0, &revs[0], sizeof(uint32_t)); if (err && err != LFS_ERR_CORRUPT) { return err; @@ -5151,14 +5092,14 @@ static int lfsr_mdir_fetch(lfs_t *lfs, lfsr_mdir_t *mdir, if (i == 0 || err == LFS_ERR_CORRUPT || lfs_scmp(revs[1], revs[0]) > 0) { - lfs_swap32(&mptr.blocks[0], &mptr.blocks[1]); + lfs_swap32(&blocks_[0], &blocks_[1]); lfs_swap32(&revs[0], &revs[1]); } } // try to fetch rbyds in the order of most recent to least recent for (int i = 0; i < 2; i++) { - int err = lfsr_rbyd_fetch(lfs, &mdir->m.rbyd, mptr.blocks[0], 0); + int err = lfsr_rbyd_fetch(lfs, &mdir->u.r.rbyd, blocks_[0], 0); if (err && err != LFS_ERR_CORRUPT) { return err; } @@ -5166,11 +5107,11 @@ static int lfsr_mdir_fetch(lfs_t *lfs, lfsr_mdir_t *mdir, if (!err) { mdir->mid = mid; // keep track of other block for compactions - mdir->m.redund_block = mptr.blocks[1]; + mdir->u.r.redund_block = blocks_[1]; return 0; } - lfs_swap32(&mptr.blocks[0], &mptr.blocks[1]); + lfs_swap32(&blocks_[0], &blocks_[1]); lfs_swap32(&revs[0], &revs[1]); } @@ -5181,21 +5122,21 @@ static int lfsr_mdir_fetch(lfs_t *lfs, lfsr_mdir_t *mdir, static int lfsr_mdir_lookupnext(lfs_t *lfs, const lfsr_mdir_t *mdir, lfs_ssize_t id, lfsr_tag_t tag, lfs_ssize_t *id_, lfsr_tag_t *tag_, lfsr_data_t *data_) { - return lfsr_rbyd_lookupnext(lfs, &mdir->m.rbyd, id, tag, + return lfsr_rbyd_lookupnext(lfs, &mdir->u.r.rbyd, id, tag, id_, tag_, NULL, data_); } static int lfsr_mdir_lookup(lfs_t *lfs, const lfsr_mdir_t *mdir, lfs_ssize_t id, lfsr_tag_t tag, lfsr_tag_t *tag_, lfsr_data_t *data_) { - return lfsr_rbyd_lookup(lfs, &mdir->m.rbyd, id, tag, tag_, data_); + return lfsr_rbyd_lookup(lfs, &mdir->u.r.rbyd, id, tag, tag_, data_); } // TODO do we need this? // TODO move this into the tests? static lfs_ssize_t lfsr_mdir_get(lfs_t *lfs, const lfsr_mdir_t *mdir, lfs_ssize_t id, lfsr_tag_t tag, void *buffer, lfs_size_t size) { - return lfsr_rbyd_get(lfs, &mdir->m.rbyd, id, tag, buffer, size); + return lfsr_rbyd_get(lfs, &mdir->u.r.rbyd, id, tag, buffer, size); } @@ -5224,7 +5165,7 @@ static int lfsr_fs_consumegdelta(lfs_t *lfs, const lfsr_mdir_t *mdir) { // mtree is the core tree of mdirs in littlefs -static inline int lfsr_mtree_isinlined(lfs_t *lfs) { +static inline bool lfsr_mtree_isinlined(lfs_t *lfs) { return lfsr_btree_weight(&lfs->mtree) == 0; } @@ -5240,7 +5181,7 @@ static int lfsr_mtree_lookup(lfs_t *lfs, lfsr_mid_t mid, lfsr_mdir_t *mdir_) { // looking up mroot? if (mid.bid < 0) { mdir_->mid = mid; - mdir_->m = lfs->mroot.m; + mdir_->u = lfs->mroot.u; return 0; // look up mdir in actual mtree @@ -5254,31 +5195,32 @@ static int lfsr_mtree_lookup(lfs_t *lfs, lfsr_mid_t mid, lfsr_mdir_t *mdir_) { } LFS_ASSERT(tag == LFSR_TAG_MDIR); - // decode mptr - lfsr_mptr_t mptr; - lfs_ssize_t d = lfsr_mptr_fromdisk(lfs, &mptr, data); + // decode mdir + lfs_ssize_t d = lfsr_mdir_fromdisk(lfs, mdir_->u.m.blocks, data); if (d < 0) { return d; } // fetch mdir - return lfsr_mdir_fetch(lfs, mdir_, mptr, mid); + return lfsr_mdir_fetch(lfs, mdir_, mdir_->u.m.blocks, mid); } } -static int lfsr_mtree_parent(lfs_t *lfs, lfsr_mptr_t mchild, +static int lfsr_mtree_parent(lfs_t *lfs, const lfs_block_t blocks[static 2], lfsr_mdir_t *mparent_) { // if mptr is our initial 0x{0,1} blocks, we have no parent - if (lfsr_mptr_ismrootanchor(mchild)) { + if (lfsr_mdir_ismrootanchor(blocks)) { return LFS_ERR_NOENT; } // scan list of mroots for our requested pair - lfsr_mptr_t mptr = LFSR_MPTR_MROOTANCHOR; - lfsr_mdir_t mdir; + lfs_block_t blocks_[2] = { + LFSR_MDIR_MROOTANCHOR[0], + LFSR_MDIR_MROOTANCHOR[1]}; while (true) { // fetch next possible superblock - int err = lfsr_mdir_fetch(lfs, &mdir, mptr, LFSR_MID(-1, -1)); + lfsr_mdir_t mdir; + int err = lfsr_mdir_fetch(lfs, &mdir, blocks_, LFSR_MID(-1, -1)); if (err) { return err; } @@ -5291,15 +5233,14 @@ static int lfsr_mtree_parent(lfs_t *lfs, lfsr_mptr_t mchild, return err; } - // decode mptr - lfsr_mptr_t mptr; - lfs_ssize_t d = lfsr_mptr_fromdisk(lfs, &mptr, data); + // decode mdir + lfs_ssize_t d = lfsr_mdir_fromdisk(lfs, blocks_, data); if (d < 0) { return d; } // found our child? - if (lfsr_mptr_cmp(mptr, mchild) == 0) { + if (lfsr_mdir_cmp(blocks_, blocks) == 0) { *mparent_ = mdir; return 0; } @@ -5311,7 +5252,7 @@ static int lfsr_mtree_seek(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_off_t off) { lfs_ssize_t rid_ = mdir->mid.rid + 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->m.rbyd.weight) { + while (rid_ >= (lfs_ssize_t)mdir->u.m.weight) { lfsr_smbid_t bid_ = mdir->mid.bid + 1; // end of mtree? if (bid_ >= (lfs_ssize_t)lfsr_mtree_weight(lfs)) { @@ -5321,7 +5262,7 @@ static int lfsr_mtree_seek(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_off_t off) { mdir->mid.rid = rid_; return LFS_ERR_NOENT; } - rid_ -= mdir->m.rbyd.weight; + rid_ -= mdir->u.m.weight; int err = lfsr_mtree_lookup(lfs, LFSR_MID(bid_, rid_), mdir); if (err) { @@ -5352,7 +5293,7 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_, const lfsr_attr_t *attr2s, lfs_size_t attr2_count) { // first thing we need to do is read our current revision count uint32_t rev; - int err = lfsr_bd_read(lfs, mdir->m.rbyd.block, 0, sizeof(uint32_t), + int err = lfsr_bd_read(lfs, mdir->u.r.rbyd.block, 0, sizeof(uint32_t), &rev, sizeof(uint32_t)); if (err && err != LFS_ERR_CORRUPT) { return err; @@ -5365,28 +5306,37 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_, lfs->cfg->block_cycles > 0 // TODO rev things && (rev + 1) % lfs->cfg->block_cycles == 0))) { - // allocate a new mdir for relocation - err = lfsr_mdir_alloc(lfs, mdir_, LFSR_MID( - (reason >= 0 ? reason : mdir->mid.bid), -1)); - if (err) { - return err; + // assign the new mid + mdir_->mid = LFSR_MID((reason >= 0 ? reason : mdir->mid.bid), -1); + + // allocate two blocks + for (int i = 0; i < 2; i++) { + int err = lfs_alloc(lfs, &mdir_->u.m.blocks[i]); + if (err) { + return err; + } } // read the new revision count // // we use whatever is on-disk to avoid needing to rewrite the // redund block - err = lfsr_bd_read(lfs, mdir_->m.rbyd.block, 0, sizeof(uint32_t), + err = lfsr_bd_read(lfs, mdir_->u.r.rbyd.block, 0, sizeof(uint32_t), &rev, sizeof(uint32_t)); if (err && err != LFS_ERR_CORRUPT) { return err; } // note we allow corrupt errors here, as long as they are consistent rev = (err != LFS_ERR_CORRUPT ? lfs_fromle32_(&rev) : 0); + + // align revision count in new mdirs to our block_cycles, this makes + // sure we don't immediately try to relocate the mdir + if (lfs->cfg->block_cycles > 0) { + rev = lfs_alignup(rev+1, lfs->cfg->block_cycles)-1; + } } // only consume gstate here during normal compacts - // TODO avoid duplicate conditions somehow? if (reason == LFSR_MDIR_COMPACTING) { // consume gstate on original rbyd, we need this even if we drop // our mdir to avoid losing info @@ -5399,29 +5349,28 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_, } // swap our rbyds - lfs_swap32(&mdir_->m.rbyd.block, &mdir_->m.redund_block); - // update our revision count - mdir_->m.rbyd.off = 0; - mdir_->m.rbyd.trunk = 0; - mdir_->m.rbyd.weight = 0; - mdir_->m.rbyd.crc = 0; + lfs_swap32(&mdir_->u.r.rbyd.block, &mdir_->u.r.redund_block); + mdir_->u.r.rbyd.weight = 0; + mdir_->u.r.rbyd.trunk = 0; + mdir_->u.r.rbyd.off = 0; + mdir_->u.r.rbyd.crc = 0; // erase, preparing for compact - err = lfsr_bd_erase(lfs, mdir_->m.rbyd.block); + err = lfsr_bd_erase(lfs, mdir_->u.r.rbyd.block); if (err) { return err; } // increment our revision count and write it to our rbyd // TODO rev things - err = lfsr_rbyd_appendrev(lfs, &mdir_->m.rbyd, rev + 1); + err = lfsr_rbyd_appendrev(lfs, &mdir_->u.r.rbyd, rev + 1); if (err) { return err; } // copy over attrs - err = lfsr_rbyd_compact(lfs, &mdir_->m.rbyd, - start_id, end_id, &mdir->m.rbyd); + err = lfsr_rbyd_compact(lfs, &mdir_->u.r.rbyd, + start_id, end_id, &mdir->u.r.rbyd); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); return err; @@ -5431,7 +5380,7 @@ 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_appendall(lfs, &mdir_->m.rbyd, start_id, end_id, + err = lfsr_rbyd_appendall(lfs, &mdir_->u.r.rbyd, start_id, end_id, attr1s, attr1_count); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); @@ -5440,7 +5389,7 @@ 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_appendall(lfs, &mdir_->m.rbyd, -1, -1, + err = lfsr_rbyd_appendall(lfs, &mdir_->u.r.rbyd, -1, -1, attr2s, attr2_count); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); @@ -5449,7 +5398,7 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_, // drop commit if weight goes to zero - if (mdir_->mid.bid >= 0 && mdir_->m.rbyd.weight == 0) { + if (mdir_->mid.bid >= 0 && mdir_->u.m.weight == 0) { // TODO should we just make our pcache not assert? // drop our pcache, we're not going to complete this commit lfs_cache_zero(lfs, &lfs->pcache); @@ -5461,12 +5410,15 @@ 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 - if (mdir_->mid.bid == -1 || lfsr_mdir_cmp(mdir_, mdir) == 0) { - err = lfsr_rbyd_appendgdelta(lfs, &mdir_->m.rbyd); + bool flushinggdelta = false; + if (mdir_->mid.bid == -1 + || lfsr_mdir_cmp(mdir_->u.m.blocks, mdir->u.m.blocks) == 0) { + err = lfsr_rbyd_appendgdelta(lfs, &mdir_->u.r.rbyd); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); return err; } + flushinggdelta = true; } else { // consume gstate so we don't lose any info err = lfsr_fs_consumegdelta(lfs, mdir_); @@ -5475,7 +5427,7 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_, } } - err = lfsr_rbyd_commit(lfs, &mdir_->m.rbyd, NULL, 0); + err = lfsr_rbyd_commit(lfs, &mdir_->u.r.rbyd, NULL, 0); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); return err; @@ -5483,7 +5435,7 @@ static int lfsr_mdir_compact_(lfs_t *lfs, lfsr_mdir_t *mdir_, // TODO avoid duplicate conditions somehow? // success? gstate is committed - if (mdir_->mid.bid == -1 || lfsr_mdir_cmp(mdir_, mdir) == 0) { + if (flushinggdelta) { lfsr_fs_flushgdelta(lfs); } } @@ -5501,8 +5453,8 @@ static int lfsr_mdir_commit_(lfs_t *lfs, lfsr_mdir_t *mdir, // TODO handle this differently? // TODO let the lower rbyd layer handle this somehow? // mark mdir as unerased in case we fail - mdir->m.rbyd.off = lfs->cfg->block_size; - int err = lfsr_rbyd_appendall(lfs, &mdir_.m.rbyd, start_id, end_id, + mdir->u.r.rbyd.off = lfs->cfg->block_size; + int err = lfsr_rbyd_appendall(lfs, &mdir_.u.r.rbyd, start_id, end_id, attrs, attr_count); if (err && err != LFS_ERR_RANGE) { return err; @@ -5512,7 +5464,7 @@ static int lfsr_mdir_commit_(lfs_t *lfs, lfsr_mdir_t *mdir, } // drop commit if weight goes to zero - if (mdir_.mid.bid >= 0 && mdir_.m.rbyd.weight == 0) { + if (mdir_.mid.bid >= 0 && mdir_.u.m.weight == 0) { // TODO move this up into lfsr_mdir_commit? // consume gstate so we don't lose any info int err = lfsr_fs_consumegdelta(lfs, mdir); @@ -5526,7 +5478,7 @@ static int lfsr_mdir_commit_(lfs_t *lfs, lfsr_mdir_t *mdir, } else { // only append gstate if we are not dropping - err = lfsr_rbyd_appendgdelta(lfs, &mdir_.m.rbyd); + err = lfsr_rbyd_appendgdelta(lfs, &mdir_.u.r.rbyd); if (err && err != LFS_ERR_RANGE) { return err; } @@ -5535,7 +5487,7 @@ static int lfsr_mdir_commit_(lfs_t *lfs, lfsr_mdir_t *mdir, } // finalize commit - err = lfsr_rbyd_commit(lfs, &mdir_.m.rbyd, NULL, 0); + err = lfsr_rbyd_commit(lfs, &mdir_.u.r.rbyd, NULL, 0); if (err && err != LFS_ERR_RANGE) { return err; } @@ -5555,7 +5507,7 @@ compact:; // can't commit, try to compact // check if we're within our compaction threshold - lfs_ssize_t estimate = lfsr_rbyd_estimateall(lfs, &mdir->m.rbyd, + lfs_ssize_t estimate = lfsr_rbyd_estimateall(lfs, &mdir->u.r.rbyd, start_id, end_id, split_id_); if (estimate < 0) { @@ -5588,7 +5540,7 @@ 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 || mdir->m.rbyd.weight > 0); + LFS_ASSERT(mdir->mid.bid == -1 || mdir->u.m.weight > 0); // parse out any pending gstate, these will get automatically xored // with on-disk gdeltas in lower-level functions @@ -5627,7 +5579,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 ? mdir_ : lfs->mroot); - lfsr_mdir_t msibling_ = {.m.rbyd.trunk=0}; + lfsr_mdir_t msibling_ = {.u.r.rbyd.trunk=0}; lfsr_btree_t mtree_ = lfs->mtree; bool dirtymroot = false; bool dirtymtree = false; @@ -5688,24 +5640,24 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, "-> 0x{%"PRIx32",%"PRIx32"}" ", 0x{%"PRIx32",%"PRIx32"}", mdir->mid.bid, - mdir->m.rbyd.block, mdir->m.redund_block, - mdir_.m.rbyd.block, mdir_.m.redund_block, - msibling_.m.rbyd.block, msibling_.m.redund_block); + mdir->u.m.blocks[1], mdir->u.m.blocks[0], + mdir_.u.m.blocks[1], mdir_.u.m.blocks[0], + msibling_.u.m.blocks[1], msibling_.u.m.blocks[0]); // because of defered commits, both children can still be reduced // to zero, need to catch this here // both siblings reduced to zero - if (mdir_.m.rbyd.weight == 0 && msibling_.m.rbyd.weight == 0) { + if (mdir_.u.m.weight == 0 && msibling_.u.m.weight == 0) { LFS_DEBUG("Dropping mdir %"PRId16" 0x{%"PRIx32",%"PRIx32"}", mdir_.mid.bid, - mdir_.m.rbyd.block, mdir_.m.redund_block); + mdir_.u.m.blocks[1], mdir_.u.m.blocks[0]); LFS_DEBUG("Dropping mdir %"PRId16" 0x{%"PRIx32",%"PRIx32"}", msibling_.mid.bid, - msibling_.m.rbyd.block, msibling_.m.redund_block); + msibling_.u.m.blocks[1], msibling_.u.m.blocks[0]); // mark as dropped - mdir_.m.rbyd.trunk = 0; - msibling_.m.rbyd.trunk = 0; + mdir_.u.r.rbyd.trunk = 0; + msibling_.u.r.rbyd.trunk = 0; // update our mtree int err = lfsr_btree_pop(lfs, &mtree_, mbid); @@ -5714,17 +5666,17 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, } // one sibling reduced to zero - } else if (mdir_.m.rbyd.weight == 0) { + } else if (mdir_.u.m.weight == 0) { LFS_DEBUG("Dropping mdir %"PRId16" 0x{%"PRIx32",%"PRIx32"}", mdir_.mid.bid, - mdir_.m.rbyd.block, mdir_.m.redund_block); + mdir_.u.m.blocks[1], mdir_.u.m.blocks[0]); // mark as dropped - mdir_.m.rbyd.trunk = 0; + mdir_.u.r.rbyd.trunk = 0; // update our mtree - uint8_t buf[LFSR_MPTR_DSIZE]; - lfs_ssize_t d = lfsr_mdir_todisk(lfs, &msibling_, buf); + uint8_t buf[LFSR_MDIR_DSIZE]; + lfs_ssize_t d = lfsr_mdir_todisk(lfs, msibling_.u.m.blocks, buf); if (d < 0) { return d; } @@ -5736,17 +5688,17 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, } // other sibling reduced to zero - } else if (msibling_.m.rbyd.weight == 0) { + } else if (msibling_.u.m.weight == 0) { LFS_DEBUG("Dropping mdir %"PRId16" 0x{%"PRIx32",%"PRIx32"}", msibling_.mid.bid, - msibling_.m.rbyd.block, msibling_.m.redund_block); + msibling_.u.m.blocks[1], msibling_.u.m.blocks[0]); // mark as dropped - msibling_.m.rbyd.trunk = 0; + msibling_.u.r.rbyd.trunk = 0; // update our mtree - uint8_t buf[LFSR_MPTR_DSIZE]; - lfs_ssize_t d = lfsr_mdir_todisk(lfs, &mdir_, buf); + uint8_t buf[LFSR_MDIR_DSIZE]; + lfs_ssize_t d = lfsr_mdir_todisk(lfs, mdir_.u.m.blocks, buf); if (d < 0) { return d; } @@ -5778,13 +5730,13 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, return err; } - uint8_t buf1[LFSR_MPTR_DSIZE]; - lfs_ssize_t d1 = lfsr_mdir_todisk(lfs, &mdir_, buf1); + uint8_t buf1[LFSR_MDIR_DSIZE]; + lfs_ssize_t d1 = lfsr_mdir_todisk(lfs, mdir_.u.m.blocks, buf1); if (d1 < 0) { return d1; } - uint8_t buf2[LFSR_MPTR_DSIZE]; - lfs_ssize_t d2 = lfsr_mdir_todisk(lfs, &msibling_, buf2); + uint8_t buf2[LFSR_MDIR_DSIZE]; + lfs_ssize_t d2 = lfsr_mdir_todisk(lfs, msibling_.u.m.blocks, buf2); if (d2 < 0) { return d2; } @@ -5803,13 +5755,13 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, dirtymtree = true; // mdir reduced to zero? need to drop? - } else if (mdir->mid.bid != -1 && mdir_.m.rbyd.weight == 0) { + } else if (mdir->mid.bid != -1 && mdir_.u.m.weight == 0) { LFS_DEBUG("Dropping mdir %"PRId16" 0x{%"PRIx32",%"PRIx32"}", mdir->mid.bid, - mdir->m.rbyd.block, mdir->m.redund_block); + mdir->u.m.blocks[1], mdir->u.m.blocks[0]); // mark as dropped - mdir_.m.rbyd.trunk = 0; + mdir_.u.r.rbyd.trunk = 0; // update our mtree int err = lfsr_btree_pop(lfs, &mtree_, mdir->mid.bid); @@ -5820,7 +5772,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, dirtymtree = true; // need to relocate? - } else if (lfsr_mdir_cmp(mdir, &mdir_) != 0) { + } else if (lfsr_mdir_cmp(mdir->u.m.blocks, mdir_.u.m.blocks) != 0) { // relocate mroot if (mdir->mid.bid == -1) { // if we're relocating our root, just mark the root as dirty @@ -5832,12 +5784,12 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, LFS_DEBUG("Relocating mdir %"PRId16" 0x{%"PRIx32",%"PRIx32"} " "-> 0x{%"PRIx32",%"PRIx32"}", mdir->mid.bid, - mdir->m.rbyd.block, mdir->m.redund_block, - mdir_.m.rbyd.block, mdir_.m.redund_block); + mdir->u.m.blocks[1], mdir->u.m.blocks[0], + mdir_.u.m.blocks[1], mdir_.u.m.blocks[0]); // update our mtree - uint8_t buf[LFSR_MPTR_DSIZE]; - lfs_ssize_t d = lfsr_mdir_todisk(lfs, &mdir_, buf); + uint8_t buf[LFSR_MDIR_DSIZE]; + lfs_ssize_t d = lfsr_mdir_todisk(lfs, mdir_.u.m.blocks, buf); if (d < 0) { return d; } @@ -5883,15 +5835,15 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, for (uint8_t j = 0; j < 2; j++) { if (grm->mids[j].bid == mdir->mid.bid) { LFS_ASSERT(grm->mids[j].rid - <= (lfs_ssize_t)mdir->m.rbyd.weight); + <= (lfs_ssize_t)mdir->u.m.weight); // TODO do we need this if we allow mid=0 => mroot when // inlined? // update mid if we are uninlining grm->mids[j].bid = lfs_smax32(grm->mids[j].bid, 0); - if (grm->mids[j].rid >= (lfs_ssize_t)mdir_.m.rbyd.weight) { + if (grm->mids[j].rid >= (lfs_ssize_t)mdir_.u.m.weight) { grm->mids[j].bid += 1; - grm->mids[j].rid -= mdir_.m.rbyd.weight; + grm->mids[j].rid -= mdir_.u.m.weight; } // update mid if we had a split or drop } else if (grm->mids[j].bid > mdir->mid.bid @@ -5945,15 +5897,17 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, return err; } - dirtymroot = (lfsr_mdir_cmp(&lfs->mroot, &mroot_) != 0); + dirtymroot = (lfsr_mdir_cmp( + lfs->mroot.u.m.blocks, + mroot_.u.m.blocks) != 0); } // need to update mroot? tail recurse, updating mroots until a commit sticks lfsr_mdir_t mchildroot = lfs->mroot; - lfsr_mdir_t mchildroot_ = mroot_; + lfs_block_t mchildroot_[2] = {mroot_.u.m.blocks[0], mroot_.u.m.blocks[1]}; while (dirtymroot) { lfsr_mdir_t mparentroot; - int err = lfsr_mtree_parent(lfs, lfsr_mdir_mptr(&mchildroot), + int err = lfsr_mtree_parent(lfs, mchildroot.u.m.blocks, &mparentroot); if (err && err != LFS_ERR_NOENT) { return err; @@ -5964,40 +5918,42 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, LFS_DEBUG("Relocating mroot 0x{%"PRIx32",%"PRIx32"} " "-> 0x{%"PRIx32",%"PRIx32"}", - mchildroot.m.rbyd.block, mchildroot.m.redund_block, - mchildroot_.m.rbyd.block, mchildroot_.m.redund_block); + mchildroot.u.m.blocks[1], mchildroot.u.m.blocks[0], + mchildroot_[1], mchildroot_[0]); // commit mrootchild - uint8_t buf[LFSR_MPTR_DSIZE]; - lfs_ssize_t d = lfsr_mdir_todisk(lfs, &mchildroot_, buf); + uint8_t buf[LFSR_MDIR_DSIZE]; + lfs_ssize_t d = lfsr_mdir_todisk(lfs, mchildroot_, buf); if (d < 0) { return d; } - lfsr_mdir_t mparentroot_ = mparentroot; - err = lfsr_mdir_commit_(lfs, &mparentroot_, -1, -1, NULL, LFSR_ATTRS( + mchildroot = mparentroot; + err = lfsr_mdir_commit_(lfs, &mparentroot, -1, -1, NULL, LFSR_ATTRS( LFSR_ATTR(-1, MROOT, 0, buf, d))); if (err) { LFS_ASSERT(err != LFS_ERR_RANGE); return err; } - mchildroot = mparentroot; - mchildroot_ = mparentroot_; - dirtymroot = (lfsr_mdir_cmp(&mchildroot, &mchildroot_) != 0); + mchildroot_[0] = mparentroot.u.m.blocks[0]; + mchildroot_[1] = mparentroot.u.m.blocks[1]; + dirtymroot = (lfsr_mdir_cmp( + mchildroot.u.m.blocks, + mchildroot_) != 0); } // uh oh, we ran out of mrootparents, need to extend mroot chain if (dirtymroot) { // mchildroot should be our initial mroot at this point - LFS_ASSERT(lfsr_mdir_ismrootanchor(&mchildroot)); + LFS_ASSERT(lfsr_mdir_ismrootanchor(mchildroot.u.m.blocks)); LFS_DEBUG("Extending mroot 0x{%"PRIx32",%"PRIx32"}" " -> 0x{%"PRIx32",%"PRIx32"}" ", 0x{%"PRIx32",%"PRIx32"}", - mchildroot.m.rbyd.block, mchildroot.m.redund_block, - mchildroot.m.redund_block, mchildroot.m.rbyd.block, - mchildroot_.m.rbyd.block, mchildroot_.m.redund_block); + mchildroot.u.m.blocks[1], mchildroot.u.m.blocks[0], + mchildroot.u.m.blocks[1], mchildroot.u.m.blocks[0], + mchildroot_[1], mchildroot_[0]); // copy magic/config from current mroot lfsr_data_t magic; @@ -6015,15 +5971,15 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, } // commit mrootchild - uint8_t buf[LFSR_MPTR_DSIZE]; - lfs_ssize_t d = lfsr_mdir_todisk(lfs, &mchildroot_, buf); + uint8_t buf[LFSR_MDIR_DSIZE]; + lfs_ssize_t d = lfsr_mdir_todisk(lfs, mchildroot_, buf); if (d < 0) { return d; } // compact into mparentroot, this should stay our mroot anchor - lfsr_mdir_t mparentroot_ = mchildroot; - err = lfsr_mdir_compact_(lfs, &mparentroot_, LFSR_MDIR_EXTENDING, 0, 0, + lfsr_mdir_t mparentroot = mchildroot; + err = lfsr_mdir_compact_(lfs, &mparentroot, LFSR_MDIR_EXTENDING, 0, 0, &mchildroot, NULL, 0, LFSR_ATTRS( LFSR_ATTR_DATA(-1, SUPERMAGIC, 0, magic), LFSR_ATTR_DATA(-1, SUPERCONFIG, 0, config), @@ -6078,7 +6034,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, < attrs[i].id - attrs[i].delta) { // normal mdirs mark as dropped if (j == 0) { - opened_mdir->m.rbyd.trunk = 0; + opened_mdir->u.r.rbyd.trunk = 0; goto next; } // for dir's second mdir (the position mdir), move @@ -6107,15 +6063,15 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, if (opened_mdir->mid.bid == mdir->mid.bid) { if (!lfsr_mdir_isdropped(&msibling_) && opened_mdir->mid.rid - >= (lfs_ssize_t)mdir_.m.rbyd.weight) { + >= (lfs_ssize_t)mdir_.u.m.weight) { LFS_ASSERT(lfsr_btree_weight(&mtree_) != lfsr_mtree_weight(lfs)); opened_mdir->mid.bid = msibling_.mid.bid; - opened_mdir->mid.rid -= mdir_.m.rbyd.weight; - opened_mdir->m = msibling_.m; + opened_mdir->mid.rid -= mdir_.u.m.weight; + opened_mdir->u = msibling_.u; } else { opened_mdir->mid.bid = mdir_.mid.bid; - opened_mdir->m = mdir_.m; + opened_mdir->u = mdir_.u; } } else if (opened_mdir->mid.bid > mdir->mid.bid) { opened_mdir->mid.bid += lfsr_btree_weight(&mtree_) @@ -6127,21 +6083,21 @@ 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->m.rbyd.weight); + LFS_ASSERT(mdir->mid.rid <= (lfs_ssize_t)mdir->u.m.weight); if (mdir->mid.bid == -1 && mdir->mid.rid == -1) { - mdir->m = mroot_.m; + mdir->u = mroot_.u; } else if (!lfsr_mdir_isdropped(&msibling_) - && mdir->mid.rid >= (lfs_ssize_t)mdir_.m.rbyd.weight) { + && mdir->mid.rid >= (lfs_ssize_t)mdir_.u.m.weight) { LFS_ASSERT(lfsr_btree_weight(&mtree_) != lfsr_mtree_weight(lfs)); mdir->mid.bid = msibling_.mid.bid; - mdir->mid.rid -= mdir_.m.rbyd.weight; - mdir->m = msibling_.m; + mdir->mid.rid -= mdir_.u.m.weight; + mdir->u = msibling_.u; } else { - mdir->m = mdir_.m; + mdir->u = mdir_.u; } // update our mroot and mtree - lfs->mroot.m = mroot_.m; + lfs->mroot.u = mroot_.u; lfs->mtree = mtree_; return 0; @@ -6152,7 +6108,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, static int lfsr_mdir_dnamelookup(lfs_t *lfs, const lfsr_mdir_t *mdir, lfs_size_t did, const char *name, lfs_size_t name_size, lfs_ssize_t *id_, lfsr_tag_t *tag_, lfsr_data_t *data_) { - int err = lfsr_rbyd_dnamelookup(lfs, &mdir->m.rbyd, + int err = lfsr_rbyd_dnamelookup(lfs, &mdir->u.r.rbyd, did, name, name_size, id_, tag_, NULL, data_); @@ -6190,14 +6146,13 @@ static int lfsr_mtree_dnamelookup(lfs_t *lfs, LFS_ASSERT(tag == LFSR_TAG_MDIR); // decode mptr - lfsr_mptr_t mptr; - lfs_ssize_t d = lfsr_mptr_fromdisk(lfs, &mptr, data); + lfs_ssize_t d = lfsr_mdir_fromdisk(lfs, mdir.u.m.blocks, data); if (d < 0) { return d; } // fetch mdir - err = lfsr_mdir_fetch(lfs, &mdir, mptr, LFSR_MID(bid, -1)); + err = lfsr_mdir_fetch(lfs, &mdir, mdir.u.m.blocks, LFSR_MID(bid, -1)); if (err) { return err; } @@ -6365,7 +6320,7 @@ typedef struct lfsr_mtree_traversal { // cycle detection state uint8_t tortoise_power; lfs_size_t tortoise_step; - lfsr_mptr_t tortoise_mptr; + lfs_block_t tortoise_blocks[2]; } lfsr_mtree_traversal_t; enum { @@ -6374,7 +6329,7 @@ enum { #define LFSR_MTREE_TRAVERSAL_INIT(_flags) ((lfsr_mtree_traversal_t){ \ .flags = _flags, \ - .mdir.m.rbyd.trunk = 0, \ + .mdir.u.r.rbyd.trunk = 0, \ .mtraversal = LFSR_BTREE_TRAVERSAL_INIT, \ .tortoise_power = 0, \ .tortoise_step = 0, \ @@ -6387,10 +6342,10 @@ static int lfsr_mtree_traversal_next(lfs_t *lfs, // // note we make sure to include fake mroots! // - if (traversal->mdir.m.rbyd.trunk == 0) { + if (traversal->mdir.u.r.rbyd.trunk == 0) { // fetch the first mroot 0x{0,1} int err = lfsr_mdir_fetch(lfs, &traversal->mdir, - LFSR_MPTR_MROOTANCHOR, LFSR_MID(-1, -1)); + LFSR_MDIR_MROOTANCHOR, LFSR_MID(-1, -1)); if (err) { return err; } @@ -6420,14 +6375,14 @@ static int lfsr_mtree_traversal_next(lfs_t *lfs, // found a new mroot if (err != LFS_ERR_NOENT && tag == LFSR_TAG_MROOT) { - lfsr_mptr_t mptr; - lfs_ssize_t d = lfsr_mptr_fromdisk(lfs, &mptr, data); + lfs_ssize_t d = lfsr_mdir_fromdisk(lfs, traversal->mdir.u.m.blocks, + data); if (d < 0) { return d; } int err = lfsr_mdir_fetch(lfs, &traversal->mdir, - mptr, LFSR_MID(-1, -1)); + traversal->mdir.u.m.blocks, LFSR_MID(-1, -1)); if (err) { return err; } @@ -6539,14 +6494,14 @@ static int lfsr_mtree_traversal_next(lfs_t *lfs, // fetch mdir if we're on a leaf } else if (tag == LFSR_TAG_MDIR) { - lfsr_mptr_t mptr; - lfs_ssize_t d = lfsr_mptr_fromdisk(lfs, &mptr, data); + lfs_ssize_t d = lfsr_mdir_fromdisk(lfs, traversal->mdir.u.m.blocks, + data); if (d < 0) { return d; } int err = lfsr_mdir_fetch(lfs, &traversal->mdir, - mptr, LFSR_MID(bid, -1)); + traversal->mdir.u.m.blocks, LFSR_MID(bid, -1)); if (err) { return err; } @@ -6574,17 +6529,18 @@ cycle_detect:; // require checksums of their pointers, so creating a valid // cycle is actually quite difficult // - if (lfsr_mptr_cmp( - lfsr_mdir_mptr(&traversal->mdir), - traversal->tortoise_mptr) == 0) { + if (lfsr_mdir_cmp( + traversal->mdir.u.m.blocks, + traversal->tortoise_blocks) == 0) { LFS_ERROR("Cycle detected during mtree traversal " "(0x{%"PRIx32",%"PRIx32"})", - traversal->mdir.m.rbyd.block, traversal->mdir.m.redund_block); + traversal->mdir.u.m.blocks[1], traversal->mdir.u.m.blocks[0]); return LFS_ERR_CORRUPT; } if (traversal->tortoise_step == ((lfs_size_t)1 << traversal->tortoise_power)) { - traversal->tortoise_mptr = lfsr_mdir_mptr(&traversal->mdir); + traversal->tortoise_blocks[0] = traversal->mdir.u.m.blocks[0]; + traversal->tortoise_blocks[1] = traversal->mdir.u.m.blocks[1]; traversal->tortoise_step = 0; traversal->tortoise_power += 1; } @@ -7209,8 +7165,8 @@ static int lfs_alloc(lfs_t *lfs, lfs_block_t *block) { // mark any blocks we see at in-use, including any btree/mdir blocks if (tag == LFSR_TAG_MDIR) { lfsr_mdir_t *mdir = (lfsr_mdir_t*)data.buf.buffer; - lfs_alloc_setinuse(lfs, mdir->m.rbyd.block); - lfs_alloc_setinuse(lfs, mdir->m.redund_block); + lfs_alloc_setinuse(lfs, mdir->u.m.blocks[1]); + lfs_alloc_setinuse(lfs, mdir->u.m.blocks[0]); } else if (tag == LFSR_TAG_BTREE) { lfsr_rbyd_t *branch = (lfsr_rbyd_t*)data.buf.buffer; @@ -7797,7 +7753,7 @@ static int lfsr_fs_fixgrm(lfs_t *lfs) { } // remove the rid while also updating our grm - LFS_ASSERT(lfs->grm.mids[0].rid < (lfs_ssize_t)mdir.m.rbyd.weight); + LFS_ASSERT(lfs->grm.mids[0].rid < (lfs_ssize_t)mdir.u.m.weight); err = lfsr_mdir_commit(lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(mdir.mid.rid, UNR, -1, NULL, 0), LFSR_ATTR_GRM(-1, GRM, 0, &grm))); diff --git a/lfs.h b/lfs.h index 4dc781fe..947ede2e 100644 --- a/lfs.h +++ b/lfs.h @@ -53,8 +53,13 @@ typedef uint16_t lfsr_mrid_t; typedef int16_t lfsr_smrid_t; typedef struct lfsr_mid { +#ifdef LFS_BIG_ENDIAN lfsr_smbid_t bid; lfsr_smrid_t rid; +#else + lfsr_smrid_t rid; + lfsr_smbid_t bid; +#endif } lfsr_mid_t; // Maximum name size in bytes, may be redefined to reduce the size of the @@ -341,12 +346,13 @@ typedef struct lfs_cache { // TODO do we get ram savings with a lfsr_rorbyd_t substruct? need to measure typedef struct lfsr_rbyd { + // note this lines up with arrays of redundant blocks in other structures + lfs_block_t block; // note this lines up with weight in lfsr_btree_t lfs_size_t weight; - lfs_block_t block; - // off=0, trunk=0 => not yet committed - // off=0, trunk>0 => not yet fetched - // off=block_size => rbyd not erased/needs compaction + // off=0, trunk=0 => not yet committed + // off=0, trunk>0 => not yet fetched + // off>=block_size => rbyd not erased/needs compaction lfs_off_t trunk; lfs_off_t off; uint32_t crc; @@ -361,30 +367,44 @@ typedef struct lfsr_rbyd { // - mdir addresses => 2 leb128 => 10 bytes (worst case) #define LFSR_BTREE_INLINESIZE 10 -typedef union lfsr_btree { - // note this lines up with weight in lfsr_rbyd_t - // - // sign(weight)=1 => inlined btree - // sign(weight)=0 => normal btree - // - // note due to defered inlining, both normal and inlined - // btrees can have a weight of 0 - lfs_size_t weight; - lfsr_rbyd_t root; - struct { - lfs_ssize_t weight; - lfsr_tag_t tag; - uint16_t size; - uint8_t buffer[LFSR_BTREE_INLINESIZE]; - } inlined; +typedef struct lfsr_btree { + union { + // weight is common to both representations and its sign-bit indicates + // if the btree is inlined + struct { + lfs_size_t _padding; + lfs_size_t weight; + } b; + struct { + // TODO complex ifdefs here to handle tag/size > 1/2 a word? + lfsr_tag_t tag; + uint8_t size; + uint8_t _padding; + lfs_size_t weight; + uint8_t buffer[LFSR_BTREE_INLINESIZE]; + } i; + struct { + // note the sign bit of the rbyd.block indicates if the btree is + // inlined or a normal btree + lfsr_rbyd_t rbyd; + } r; + } u; } lfsr_btree_t; typedef struct lfsr_mdir { lfsr_mid_t mid; - struct { - lfsr_rbyd_t rbyd; - lfs_block_t redund_block; - } m; + 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 + struct { + lfs_block_t blocks[2]; + lfs_size_t weight; + } m; + struct { + lfs_block_t redund_block; + lfsr_rbyd_t rbyd; + } r; + } u; } lfsr_mdir_t; typedef struct lfsr_openedmdir { diff --git a/lfs_util.h b/lfs_util.h index cdad4bf1..787484b5 100644 --- a/lfs_util.h +++ b/lfs_util.h @@ -108,6 +108,31 @@ extern "C" #endif #endif +// We need to know the endianness of the system for some struct packing +#if (defined(BYTE_ORDER) \ + && defined(ORDER_LITTLE_ENDIAN) \ + && BYTE_ORDER == ORDER_LITTLE_ENDIAN) \ + || (defined(__BYTE_ORDER) \ + && defined(__ORDER_LITTLE_ENDIAN) \ + && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN) \ + || (defined(__BYTE_ORDER__) \ + && defined(__ORDER_LITTLE_ENDIAN__) \ + && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#define LFS_LITTLE_ENDIAN +#elif (defined(BYTE_ORDER) \ + && defined(ORDER_BIG_ENDIAN) \ + && BYTE_ORDER == ORDER_BIG_ENDIAN) \ + || (defined(__BYTE_ORDER) \ + && defined(__ORDER_BIG_ENDIAN) \ + && __BYTE_ORDER == __ORDER_BIG_ENDIAN) \ + || (defined(__BYTE_ORDER__) \ + && defined(__ORDER_BIG_ENDIAN__) \ + && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +#define LFS_BIG_ENDIAN +#else +#error "lfs: Unknown endianness?" +#endif + // Builtin functions, these may be replaced by more efficient // toolchain-specific implementations. LFS_NO_INTRINSICS falls back to a more @@ -243,14 +268,9 @@ static inline int lfs_scmp(uint32_t a, uint32_t b) { // Convert between 32-bit little-endian and native order static inline uint32_t lfs_fromle32(uint32_t a) { -#if (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \ - (defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \ - (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) +#if !defined(LFS_NO_INTRINSICS) && defined(LFS_LITTLE_ENDIAN) return a; -#elif !defined(LFS_NO_INTRINSICS) && ( \ - (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \ - (defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \ - (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)) +#elif !defined(LFS_NO_INTRINSICS) return __builtin_bswap32(a); #else return (((uint8_t*)&a)[0] << 0) | @@ -266,14 +286,9 @@ static inline uint32_t lfs_tole32(uint32_t a) { // Convert between 32-bit big-endian and native order static inline uint32_t lfs_frombe32(uint32_t a) { -#if !defined(LFS_NO_INTRINSICS) && ( \ - (defined( BYTE_ORDER ) && defined( ORDER_LITTLE_ENDIAN ) && BYTE_ORDER == ORDER_LITTLE_ENDIAN ) || \ - (defined(__BYTE_ORDER ) && defined(__ORDER_LITTLE_ENDIAN ) && __BYTE_ORDER == __ORDER_LITTLE_ENDIAN ) || \ - (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)) +#if !defined(LFS_NO_INTRINSICS) && defined(LFS_LITTLE_ENDIAN) return __builtin_bswap32(a); -#elif (defined( BYTE_ORDER ) && defined( ORDER_BIG_ENDIAN ) && BYTE_ORDER == ORDER_BIG_ENDIAN ) || \ - (defined(__BYTE_ORDER ) && defined(__ORDER_BIG_ENDIAN ) && __BYTE_ORDER == __ORDER_BIG_ENDIAN ) || \ - (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +#elif !defined(LFS_NO_INTRINSICS) return a; #else return (((uint8_t*)&a)[0] << 24) | diff --git a/tests/test_alloc.toml b/tests/test_alloc.toml index a1bc57d2..b0fd9248 100644 --- a/tests/test_alloc.toml +++ b/tests/test_alloc.toml @@ -149,7 +149,7 @@ code = ''' 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.m.rbyd.weight; + mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; mdir.mid.rid++) { uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_INLINED, diff --git a/tests/test_btree.toml b/tests/test_btree.toml index a8274396..8bd11085 100644 --- a/tests/test_btree.toml +++ b/tests/test_btree.toml @@ -23,9 +23,9 @@ code = ''' // create an empty tree lfsr_btree_t btree = LFSR_BTREE_NULL; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 0); // try looking up tags @@ -56,9 +56,9 @@ code = ''' lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("a", 1)) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 1); // try looking up tags @@ -97,9 +97,9 @@ code = ''' lfsr_btree_push(&lfs, &btree, 1, LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("b", 1)) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 2); // try looking up tags @@ -143,9 +143,9 @@ code = ''' lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("a", 1)) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 2); // try looking up tags @@ -192,9 +192,9 @@ code = ''' lfsr_btree_push(&lfs, &btree, 2, LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("c", 1)) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 3); // try looking up tags @@ -246,9 +246,9 @@ code = ''' lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("a", 1)) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 3); // try looking up tags @@ -309,9 +309,9 @@ code = ''' n += 1; } printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == n); // check that the elements are in the tree @@ -361,9 +361,9 @@ code = ''' n += 1; } printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == n); // check that the elements are in the tree @@ -444,9 +444,9 @@ code = ''' } printf("]\n"); printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == sim_size); uint8_t buffer[4]; @@ -499,9 +499,9 @@ code = ''' n += 1; } printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == n*W); // check that the elements are in the tree @@ -620,9 +620,9 @@ code = ''' } printf("]\n"); printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); lfs_size_t total_weight = 0; for (lfs_size_t j = 0; j < sim_size; j++) { @@ -702,9 +702,9 @@ code = ''' lfsr_btree_set(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("A", 1)) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 1); // try looking up tags @@ -747,9 +747,9 @@ code = ''' lfsr_btree_set(&lfs, &btree, 1, LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("B", 1)) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 2); // try looking up tags @@ -802,9 +802,9 @@ code = ''' lfsr_btree_set(&lfs, &btree, 2, LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("C", 1)) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 3); // try looking up tags @@ -858,9 +858,9 @@ code = ''' // ignore space issues if (err == LFS_ERR_NOSPC) { printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); return; } assert(err == 0); @@ -872,17 +872,17 @@ code = ''' // ignore space issues if (err == LFS_ERR_NOSPC) { printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); return; } assert(err == 0); } printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == N); // check that the elements are in the tree @@ -930,9 +930,9 @@ code = ''' // ignore space issues if (err == LFS_ERR_NOSPC) { printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); return; } assert(err == 0); @@ -977,9 +977,9 @@ code = ''' } printf("]\n"); printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == N); uint8_t buffer[4]; @@ -1026,9 +1026,9 @@ code = ''' // ignore space issues if (err == LFS_ERR_NOSPC) { printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); return; } assert(err == 0); @@ -1040,17 +1040,17 @@ code = ''' // ignore space issues if (err == LFS_ERR_NOSPC) { printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); return; } assert(err == 0); } printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == N*W); // check that the elements are in the tree @@ -1114,9 +1114,9 @@ code = ''' // ignore space issues if (err == LFS_ERR_NOSPC) { printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); return; } assert(err == 0); @@ -1180,9 +1180,9 @@ code = ''' } printf("]\n"); printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); lfs_size_t total_weight = 0; for (lfs_size_t j = 0; j < N; j++) { @@ -1262,9 +1262,9 @@ code = ''' // pop! lfsr_btree_pop(&lfs, &btree, 0) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 0); // try looking up tags @@ -1279,9 +1279,9 @@ code = ''' lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("A", 1)) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 1); // try looking up tags @@ -1317,9 +1317,9 @@ code = ''' // pop! lfsr_btree_pop(&lfs, &btree, 1) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 1); // try looking up tags @@ -1340,9 +1340,9 @@ code = ''' lfsr_btree_push(&lfs, &btree, 1, LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("B", 1)) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 2); // try looking up tags @@ -1384,9 +1384,9 @@ code = ''' // pop! lfsr_btree_pop(&lfs, &btree, 0) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 1); // try looking up tags @@ -1407,9 +1407,9 @@ code = ''' lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("A", 1)) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 2); // try looking up tags @@ -1453,9 +1453,9 @@ code = ''' // pop! lfsr_btree_pop(&lfs, &btree, 2) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 2); // try looking up tags @@ -1482,9 +1482,9 @@ code = ''' lfsr_btree_push(&lfs, &btree, 2, LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("C", 1)) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 3); // try looking up tags @@ -1535,9 +1535,9 @@ code = ''' // ignore space issues if (err == LFS_ERR_NOSPC) { printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); return; } assert(err == 0); @@ -1548,18 +1548,18 @@ code = ''' // ignore space issues if (err == LFS_ERR_NOSPC) { printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); return; } assert(err == 0); } printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == REMAINING); // check that the elements are in the tree @@ -1626,9 +1626,9 @@ code = ''' // ignore space issues if (err == LFS_ERR_NOSPC) { printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); return; } assert(err == 0); @@ -1639,17 +1639,17 @@ code = ''' // ignore space issues if (err == LFS_ERR_NOSPC) { printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); return; } assert(err == 0); } printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == REMAINING); // check that the elements are in the tree @@ -1718,9 +1718,9 @@ code = ''' // ignore space issues if (err == LFS_ERR_NOSPC) { printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); return; } assert(err == 0); @@ -1766,9 +1766,9 @@ code = ''' } printf("]\n"); printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == sim_size); uint8_t buffer[4]; @@ -1816,9 +1816,9 @@ code = ''' // ignore space issues if (err == LFS_ERR_NOSPC) { printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); return; } assert(err == 0); @@ -1829,17 +1829,17 @@ code = ''' // ignore space issues if (err == LFS_ERR_NOSPC) { printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); return; } assert(err == 0); } printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == REMAINING*W); // check that the elements are in the tree @@ -1956,9 +1956,9 @@ code = ''' // ignore space issues if (err == LFS_ERR_NOSPC) { printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); return; } assert(err == 0); @@ -2013,9 +2013,9 @@ code = ''' } printf("]\n"); printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); lfs_size_t total_weight = 0; for (lfs_size_t j = 0; j < sim_size; j++) { @@ -2104,9 +2104,9 @@ code = ''' n += 1; } printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == n); // check that the elements are in the tree @@ -2193,9 +2193,9 @@ code = ''' } printf("]\n"); printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == sim_size); uint8_t buffer[4]; @@ -2251,9 +2251,9 @@ code = ''' n += 1; } printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == n*W); // check that the elements are in the tree @@ -2367,9 +2367,9 @@ code = ''' } printf("]\n"); printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); lfs_size_t total_weight = 0; for (lfs_size_t j = 0; j < sim_size; j++) { @@ -2519,9 +2519,9 @@ code = ''' } printf("]\n"); printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == sim_size); uint8_t buffer[4]; @@ -2660,9 +2660,9 @@ code = ''' } printf("]\n"); printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); lfs_size_t total_weight = 0; for (lfs_size_t j = 0; j < sim_size; j++) { @@ -2735,9 +2735,9 @@ code = ''' // create a zero-entry tree lfsr_btree_t btree = LFSR_BTREE_NULL; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 0); // try to find tags @@ -2770,9 +2770,9 @@ code = ''' lfsr_btree_push(&lfs, &btree, 0, LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("0", 1)) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 1); // try to find tags @@ -2822,9 +2822,9 @@ code = ''' LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("0", 1), LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("1", 1)) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 2); // try to find tags @@ -2885,9 +2885,9 @@ code = ''' LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("1", 1), LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("2", 1)) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 3); // try to find tags @@ -2956,9 +2956,9 @@ code = ''' LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("0", 1), LFSR_TAG_INLINED, 1, LFSR_DATA_BUF("1", 1)) => 0; printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == 3); // try to find tags @@ -3040,9 +3040,9 @@ code = ''' n += 1; } printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == n); // try to find tags @@ -3152,9 +3152,9 @@ code = ''' } printf("]\n"); printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == sim_size); uint8_t buffer[4]; @@ -3218,9 +3218,9 @@ code = ''' n += 1; } printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == n*W); // try to find tags @@ -3358,9 +3358,9 @@ code = ''' } printf("]\n"); printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); lfs_size_t total_weight = 0; for (lfs_size_t j = 0; j < sim_size; j++) { @@ -3546,9 +3546,9 @@ code = ''' } printf("]\n"); printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == sim_size); uint8_t buffer[4]; @@ -3756,9 +3756,9 @@ code = ''' } printf("]\n"); printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); lfs_size_t total_weight = 0; for (lfs_size_t j = 0; j < sim_size; j++) { @@ -3826,9 +3826,9 @@ code = ''' n += 1; } printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == n); // check that the elements are in the tree @@ -3975,9 +3975,9 @@ code = ''' } printf("]\n"); printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == sim_size); uint8_t buffer[4]; @@ -4061,9 +4061,9 @@ code = ''' } printf("]\n"); printf("btree: w%d 0x%x.%x\n", - btree.weight, - btree.root.block, - btree.root.trunk); + btree.u.r.rbyd.weight, + btree.u.r.rbyd.block, + btree.u.r.rbyd.trunk); assert(lfsr_btree_weight(&btree) == sim_size); for (lfs_size_t i = 0; i < sim_size; i++) { diff --git a/tests/test_mtree.toml b/tests/test_mtree.toml index d25c430f..a4d29dbe 100644 --- a/tests/test_mtree.toml +++ b/tests/test_mtree.toml @@ -66,7 +66,7 @@ code = ''' for (lfs_size_t i = 0; i < N; i++) { // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( LFSR_ATTR(-1, UATTR(i), 0, &alphas[i % 26], 1))) => 0; @@ -164,13 +164,13 @@ code = ''' LFSR_ATTR(0, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdir was unininlined correctly assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -180,7 +180,7 @@ code = ''' // assert that our entry is still in the mtree lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -195,7 +195,7 @@ code = ''' // assert mdir was unininlined correctly assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -204,7 +204,7 @@ code = ''' // assert that our entry is still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -238,24 +238,24 @@ code = ''' LFSR_ATTR(1, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs) == 2); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our entries are still in the mtree lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[0 % 26], 1) == 0); lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[1 % 26], 1) == 0); @@ -269,17 +269,17 @@ code = ''' // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs) == 2); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our entries are still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[0 % 26], 1) == 0); lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[1 % 26], 1) == 0); @@ -312,31 +312,31 @@ code = ''' LFSR_ATTR(0, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdir was unininlined correctly assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // now add another large entry to the mdir, forcing a split lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); memset(buffer, alphas[2 % 26], SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(1, INLINED, +1, buffer, SIZE))) => 0; // force mdir to compact - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &mdir, NULL, 0) => 0; // assert mdir was split correctly assert(lfsr_mtree_weight(&lfs) == 2); // assert mroot still has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -345,13 +345,13 @@ code = ''' // assert that our entries are still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[1 % 26], 1) == 0); lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[2 % 26], 1) == 0); @@ -364,7 +364,7 @@ code = ''' // assert mdir was split correctly assert(lfsr_mtree_weight(&lfs) == 2); // assert mroot still has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -373,13 +373,13 @@ code = ''' // assert that our entries are still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[1 % 26], 1) == 0); lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[2 % 26], 1) == 0); @@ -405,14 +405,15 @@ code = ''' // create entries lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(lfsr_mtree_weight(&lfs)-1, -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, LFSR_MID(lfsr_mtree_weight(&lfs)-1, -1), + &mdir) => 0; mdir.mid.rid = 0; for (lfs_size_t i = 0; i < N; i++) { // force a compaction? if (FORCE_COMPACTION) { - mdir.m.rbyd.off = CFG->block_size; - lfs.mroot.m.rbyd.off = CFG->block_size; + mdir.u.r.rbyd.off = CFG->block_size; + lfs.mroot.u.r.rbyd.off = CFG->block_size; } lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( @@ -434,7 +435,7 @@ code = ''' 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.m.rbyd.weight; + mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; mdir.mid.rid++) { uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_INLINED, @@ -459,7 +460,7 @@ code = ''' 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.m.rbyd.weight; + mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; mdir.mid.rid++) { uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_INLINED, @@ -503,12 +504,12 @@ code = ''' 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.m.rbyd.weight+1); + mdir.mid.rid = TEST_PRNG(&prng) % (mdir.u.m.weight+1); // force a compaction? if (FORCE_COMPACTION) { - mdir.m.rbyd.off = CFG->block_size; - lfs.mroot.m.rbyd.off = CFG->block_size; + mdir.u.r.rbyd.off = CFG->block_size; + lfs.mroot.u.r.rbyd.off = CFG->block_size; } // add to rbyd, potentially splitting the mdir @@ -533,7 +534,7 @@ code = ''' 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.m.rbyd.weight; + mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; mdir.mid.rid++) { uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_INLINED, @@ -562,7 +563,7 @@ code = ''' 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.m.rbyd.weight; + mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; mdir.mid.rid++) { uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_INLINED, @@ -608,18 +609,18 @@ code = ''' LFSR_ATTR(0, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdir was unininlined correctly assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // remove the entry, forcing the mdir to be dropped lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(0, UNR, -1, NULL, 0))) => 0; @@ -627,7 +628,7 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 0); // assert mroot still has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -643,7 +644,7 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 0); // assert mroot still has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -678,21 +679,21 @@ code = ''' LFSR_ATTR(0, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdir was unininlined correctly assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // remove the entry, forcing the mdir to be dropped lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); // force mdir to compact while we're removing - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(0, UNR, -1, NULL, 0))) => 0; @@ -700,7 +701,7 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 0); // assert mroot still has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -716,7 +717,7 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 0); // assert mroot still has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -751,7 +752,7 @@ code = ''' LFSR_ATTR(0, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; // remove the entry as we compact, forcing the mdir to be dropped lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( @@ -760,7 +761,7 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 0); // assert mroot has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -776,7 +777,7 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 0); // assert mroot has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -811,7 +812,7 @@ code = ''' LFSR_ATTR(1, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; // remove the left entry as we compact, forcing the left // mdir to be dropped @@ -821,12 +822,12 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that one entry is still in the mtree lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -841,11 +842,11 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that one entry is still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -879,7 +880,7 @@ code = ''' LFSR_ATTR(1, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; // remove the right entry as we compact, forcing the right mdir // to be dropped @@ -889,12 +890,12 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that one entry is still in the mtree lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -909,11 +910,11 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that one entry is still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -947,7 +948,7 @@ code = ''' LFSR_ATTR(1, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; // remove both entries as we compact, forcing both mdirs to be dropped lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( @@ -957,7 +958,7 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 0); // assert mroot has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); lfsr_unmount(&lfs) => 0; @@ -968,7 +969,7 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 0); // assert mroot has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); lfsr_unmount(&lfs) => 0; ''' @@ -998,25 +999,25 @@ code = ''' LFSR_ATTR(0, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdir was unininlined correctly assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // now add another large entry to the mdir, forcing a split lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); memset(buffer, alphas[2 % 26], SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(1, INLINED, +1, buffer, SIZE))) => 0; // force mdir to compact - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; // remove the left entry as we compact, forcing the left // mdir to be dropped @@ -1026,7 +1027,7 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -1035,7 +1036,7 @@ code = ''' // assert that one entry is still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -1050,7 +1051,7 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -1059,7 +1060,7 @@ code = ''' // assert that one entry is still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -1093,25 +1094,25 @@ code = ''' LFSR_ATTR(0, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdir was unininlined correctly assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // now add another large entry to the mdir, forcing a split lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); memset(buffer, alphas[2 % 26], SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(1, INLINED, +1, buffer, SIZE))) => 0; // force mdir to compact - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; // remove the right entry as we compact, forcing the right // mdir to be dropped @@ -1121,7 +1122,7 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -1130,7 +1131,7 @@ code = ''' // assert that one entry is still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -1145,7 +1146,7 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -1154,7 +1155,7 @@ code = ''' // assert that one entry is still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -1188,25 +1189,25 @@ code = ''' LFSR_ATTR(0, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdir was unininlined correctly assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // now add another large entry to the mdir, forcing a split lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); memset(buffer, alphas[2 % 26], SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(1, INLINED, +1, buffer, SIZE))) => 0; // force mdir to compact - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; // remove both entries as we compact, forcing both mdirs to be dropped lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( @@ -1216,7 +1217,7 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 0); // assert mroot has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -1232,7 +1233,7 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 0); // assert mroot has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -1261,7 +1262,8 @@ code = ''' // create entries lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(lfsr_mtree_weight(&lfs)-1, -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, LFSR_MID(lfsr_mtree_weight(&lfs)-1, -1), + &mdir) => 0; mdir.mid.rid = 0; for (lfs_size_t i = 0; i < N; i++) { @@ -1283,12 +1285,12 @@ code = ''' lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; // drop should make sure we never have empty mdirs - assert(mdir.mid.bid == -1 || mdir.m.rbyd.weight > 0); + assert(mdir.mid.bid == -1 || mdir.u.m.weight > 0); // force a compaction? if (FORCE_COMPACTION) { - mdir.m.rbyd.off = CFG->block_size; - lfs.mroot.m.rbyd.off = CFG->block_size; + mdir.u.r.rbyd.off = CFG->block_size; + lfs.mroot.u.r.rbyd.off = CFG->block_size; } lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( @@ -1303,7 +1305,7 @@ code = ''' 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.m.rbyd.weight; + mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; mdir.mid.rid++) { uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_INLINED, @@ -1328,7 +1330,7 @@ code = ''' 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.m.rbyd.weight; + mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; mdir.mid.rid++) { uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_INLINED, @@ -1361,12 +1363,14 @@ code = ''' for (lfs_size_t cycle = 0; cycle < CYCLES; cycle++) { // create entries lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(lfsr_mtree_weight(&lfs)-1, -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, LFSR_MID(lfsr_mtree_weight(&lfs)-1, -1), + &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, INLINED, +1, &alphas[i % 26], 1))) => 0; + LFSR_ATTR(mdir.mid.rid, INLINED, +1, + &alphas[i % 26], 1))) => 0; uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_INLINED, @@ -1384,7 +1388,7 @@ code = ''' 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.m.rbyd.weight; + mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; mdir.mid.rid++) { uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_INLINED, @@ -1402,12 +1406,12 @@ code = ''' lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; // drop should make sure we never have empty mdirs - assert(mdir.mid.bid == -1 || mdir.m.rbyd.weight > 0); + assert(mdir.mid.bid == -1 || mdir.u.m.weight > 0); // force a compaction? if (FORCE_COMPACTION) { - mdir.m.rbyd.off = CFG->block_size; - lfs.mroot.m.rbyd.off = CFG->block_size; + mdir.u.r.rbyd.off = CFG->block_size; + lfs.mroot.u.r.rbyd.off = CFG->block_size; } lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( @@ -1415,7 +1419,7 @@ code = ''' } assert(lfsr_mtree_weight(&lfs) == 0); - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); } lfsr_unmount(&lfs) => 0; @@ -1425,7 +1429,7 @@ code = ''' lfsr_mount(&lfs, CFG) => 0; assert(lfsr_mtree_weight(&lfs) == 0); - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); lfsr_unmount(&lfs) => 0; ''' @@ -1459,16 +1463,16 @@ code = ''' 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.m.rbyd.weight+1); + mdir.mid.rid = TEST_PRNG(&prng) % (mdir.u.m.weight+1); // choose to create or delete - uint8_t op = (lfs_size_t)mdir.mid.rid == mdir.m.rbyd.weight + uint8_t op = (lfs_size_t)mdir.mid.rid == mdir.u.m.weight ? 0 : TEST_PRNG(&prng) % 2; // force a compaction? if (FORCE_COMPACTION) { - mdir.m.rbyd.off = CFG->block_size; - lfs.mroot.m.rbyd.off = CFG->block_size; + mdir.u.r.rbyd.off = CFG->block_size; + lfs.mroot.u.r.rbyd.off = CFG->block_size; } // create @@ -1505,10 +1509,10 @@ code = ''' lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; // drop should make sure we never have empty mdirs - assert(mdir.mid.bid == -1 || mdir.m.rbyd.weight > 0); + assert(mdir.mid.bid == -1 || mdir.u.m.weight > 0); for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.m.rbyd.weight; + mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; mdir.mid.rid++) { uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_INLINED, @@ -1538,10 +1542,10 @@ code = ''' lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; // drop should make sure we never have empty mdirs - assert(mdir.mid.bid == -1 || mdir.m.rbyd.weight > 0); + assert(mdir.mid.bid == -1 || mdir.u.m.weight > 0); for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.m.rbyd.weight; + mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; mdir.mid.rid++) { uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_INLINED, @@ -1590,30 +1594,30 @@ code = ''' LFSR_ATTR(0, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mtree has one mdir assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // force mdir to compact twice, this should relocate lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_t old_mdir = mdir; - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &mdir, NULL, 0) => 0; - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; memset(buffer, alphas[2 % 26], SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(0, INLINED, 0, buffer, SIZE))) => 0; // assert we relocated - assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0); + assert(lfsr_mdir_cmp(old_mdir.u.m.blocks, mdir.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -1622,7 +1626,7 @@ code = ''' // assert that our entry is still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -1637,10 +1641,10 @@ code = ''' // assert mtree has one mdir assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert we relocated - assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0); + assert(lfsr_mdir_cmp(old_mdir.u.m.blocks, mdir.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -1649,7 +1653,7 @@ code = ''' // assert that our entry is still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -1685,40 +1689,40 @@ code = ''' LFSR_ATTR(1, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs) == 2); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // force mdir to compact twice, this should relocate lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_t old_mdir = mdir; - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &mdir, NULL, 0) => 0; - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; memset(buffer, alphas[2 % 26], SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(0, INLINED, 0, buffer, SIZE))) => 0; // assert we relocated - assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0); + 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, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[2 % 26], 1) == 0); lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[1 % 26], 1) == 0); @@ -1732,20 +1736,20 @@ code = ''' // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs) == 2); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert we relocated - assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0); + 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, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[2 % 26], 1) == 0); lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[1 % 26], 1) == 0); @@ -1780,40 +1784,40 @@ code = ''' LFSR_ATTR(1, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs) == 2); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // force mdir to compact twice, this should relocate lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_t old_mdir = mdir; - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &mdir, NULL, 0) => 0; - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; memset(buffer, alphas[2 % 26], SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(0, INLINED, 0, buffer, SIZE))) => 0; // assert we relocated - assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0); + 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, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[0 % 26], 1) == 0); lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[2 % 26], 1) == 0); @@ -1827,20 +1831,20 @@ code = ''' // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs) == 2); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert we relocated - assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0); + 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, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[0 % 26], 1) == 0); lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[2 % 26], 1) == 0); @@ -1873,15 +1877,15 @@ code = ''' // force mroot to compact twice, this should extend the mroot lfsr_mdir_t old_mroot = lfs.mroot; - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; memset(buffer, alphas[1 % 26], SIZE); lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( LFSR_ATTR(-1, UATTR(1), 0, buffer, SIZE))) => 0; // assert we relocated - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -1895,7 +1899,7 @@ code = ''' lfsr_mount(&lfs, CFG) => 0; // assert we relocated - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -1934,16 +1938,16 @@ code = ''' lfsr_mdir_t old_mroot = lfs.mroot; for (int i = 0; i < 4; i++) { - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; } - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; memset(buffer, alphas[1 % 26], SIZE); lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( LFSR_ATTR(-1, UATTR(1), 0, buffer, SIZE))) => 0; // assert we relocated - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -1957,7 +1961,7 @@ code = ''' lfsr_mount(&lfs, CFG) => 0; // assert we relocated - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -1992,26 +1996,26 @@ code = ''' // force mroot to compact twice, this should extend the mroot lfsr_mdir_t old_mroot = lfs.mroot; - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert we relocated - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // force mroot to compact twice again, this should relocate the mroot old_mroot = lfs.mroot; - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; memset(buffer, alphas[1 % 26], SIZE); lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( LFSR_ATTR(-1, UATTR(1), 0, buffer, SIZE))) => 0; // assert we relocated - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -2025,7 +2029,7 @@ code = ''' lfsr_mount(&lfs, CFG) => 0; // assert we relocated - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -2063,38 +2067,38 @@ code = ''' LFSR_ATTR(0, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mtree has one mdir assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // setup mroot to need to compact, this should trigger a relocation when // we relocate the mdir below - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_t old_mroot = lfs.mroot; // force mdir to compact twice, this should relocate lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_t old_mdir = mdir; - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &mdir, NULL, 0) => 0; - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; memset(buffer, alphas[2 % 26], SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(0, INLINED, 0, buffer, SIZE))) => 0; // assert we relocated our mdir - assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0); + assert(lfsr_mdir_cmp(old_mdir.u.m.blocks, mdir.u.m.blocks) != 0); // assert we relocated our mroot - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -2103,7 +2107,7 @@ code = ''' // assert that our entry is still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -2118,13 +2122,13 @@ code = ''' // assert mtree has one mdir assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert we relocated our mdir - assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0); + assert(lfsr_mdir_cmp(old_mdir.u.m.blocks, mdir.u.m.blocks) != 0); // assert we relocated our mroot - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -2133,7 +2137,7 @@ code = ''' // assert that our entry is still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -2169,39 +2173,39 @@ code = ''' LFSR_ATTR(0, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdir was unininlined correctly assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // setup mroot to need to compact, this should trigger a relocation when // we relocate the mdir below - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_t old_mroot = lfs.mroot; // now add another large entry to the mdir, forcing a split lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); memset(buffer, alphas[2 % 26], SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(1, INLINED, +1, buffer, SIZE))) => 0; // force mdir to compact - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &mdir, NULL, 0) => 0; // assert mdir was split correctly assert(lfsr_mtree_weight(&lfs) == 2); // assert mroot still has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert we relocated our mroot - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -2210,13 +2214,13 @@ code = ''' // assert that our entries are still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[1 % 26], 1) == 0); lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[2 % 26], 1) == 0); @@ -2230,10 +2234,10 @@ code = ''' // assert mdir was split correctly assert(lfsr_mtree_weight(&lfs) == 2); // assert mroot still has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert we relocated our mroot - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -2242,13 +2246,13 @@ code = ''' // assert that our entries are still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[1 % 26], 1) == 0); lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[2 % 26], 1) == 0); @@ -2283,23 +2287,23 @@ code = ''' LFSR_ATTR(0, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdir was unininlined correctly assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // setup mroot to need to compact, this should trigger a relocation when // we relocate the mdir below - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_t old_mroot = lfs.mroot; // remove the entry, forcing the mdir to be dropped lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(0, UNR, -1, NULL, 0))) => 0; @@ -2307,10 +2311,10 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 0); // assert mroot still has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert we relocated our mroot - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -2326,10 +2330,10 @@ code = ''' // assert mdir was dropped assert(lfsr_mtree_weight(&lfs) == 0); // assert mroot still has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert we relocated our mroot - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -2357,7 +2361,7 @@ code = ''' // force mroot to compact once, so the second compact below will trigger // a relocation - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // prepare mroot with a large attr so the next entry can not fit @@ -2373,16 +2377,16 @@ code = ''' // force mroot to compact, this should trigger a relocation lfsr_mdir_t old_mroot = lfs.mroot; - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdir was unininlined correctly assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert we relocated our mroot - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -2392,7 +2396,7 @@ code = ''' // assert that our entry is still in the mtree lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -2407,10 +2411,10 @@ code = ''' // assert mdir was unininlined correctly assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert we relocated our mroot - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -2419,7 +2423,7 @@ code = ''' // assert that our entry is still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -2446,7 +2450,7 @@ code = ''' // force mroot to compact once, so the second compact below will trigger // a relocation - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // create 2 large entries that needs to be uninlined and split @@ -2461,27 +2465,27 @@ code = ''' // force mroot to compact, this should trigger a relocation lfsr_mdir_t old_mroot = lfs.mroot; - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs) == 2); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert we relocated our mroot - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + 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_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[0 % 26], 1) == 0); lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[1 % 26], 1) == 0); @@ -2495,20 +2499,20 @@ code = ''' // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs) == 2); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert we relocated our mroot - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + 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, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[0 % 26], 1) == 0); lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[1 % 26], 1) == 0); @@ -2547,16 +2551,16 @@ code = ''' 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.m.rbyd.weight+1); + mdir.mid.rid = TEST_PRNG(&prng) % (mdir.u.m.weight+1); // choose to create or delete - uint8_t op = (lfs_size_t)mdir.mid.rid == mdir.m.rbyd.weight + uint8_t op = (lfs_size_t)mdir.mid.rid == mdir.u.m.weight ? 0 : TEST_PRNG(&prng) % 3; // force a compaction? if (FORCE_COMPACTION) { - mdir.m.rbyd.off = CFG->block_size; - lfs.mroot.m.rbyd.off = CFG->block_size; + mdir.u.r.rbyd.off = CFG->block_size; + lfs.mroot.u.r.rbyd.off = CFG->block_size; } // create @@ -2606,10 +2610,10 @@ code = ''' lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; // drop should make sure we never have empty mdirs - assert(mdir.mid.bid == -1 || mdir.m.rbyd.weight > 0); + assert(mdir.mid.bid == -1 || mdir.u.m.weight > 0); for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.m.rbyd.weight; + mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; mdir.mid.rid++) { uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_INLINED, @@ -2639,10 +2643,10 @@ code = ''' lfsr_mtree_lookup(&lfs, LFSR_MID(mid, -1), &mdir) => 0; // drop should make sure we never have empty mdirs - assert(mdir.mid.bid == -1 || mdir.m.rbyd.weight > 0); + assert(mdir.mid.bid == -1 || mdir.u.m.weight > 0); for (mdir.mid.rid = 0; - mdir.mid.rid < (lfs_ssize_t)mdir.m.rbyd.weight; + mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; mdir.mid.rid++) { uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_INLINED, @@ -2682,9 +2686,9 @@ code = ''' assert(lfsr_mtree_isinlined(&lfs)); lfsr_openedmdir_t left_neighbor = { - .mdir={.mid=LFSR_MID(-1, 0), .m=lfs.mroot.m}}; + .mdir={.mid=LFSR_MID(-1, 0), .u=lfs.mroot.u}}; lfsr_openedmdir_t right_neighbor = { - .mdir={.mid=LFSR_MID(-1, 1), .m=lfs.mroot.m}}; + .mdir={.mid=LFSR_MID(-1, 1), .u=lfs.mroot.u}}; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -2693,7 +2697,7 @@ code = ''' LFSR_ATTR(1, INLINED, +1, &alphas[2 % 26], 1))) => 0; // assert that our entry is still in the mtree - assert(lfs.mroot.m.rbyd.weight == 3); + assert(lfs.mroot.u.m.weight == 3); uint8_t buffer[1]; lfsr_mdir_get(&lfs, &lfs.mroot, 1, LFSR_TAG_INLINED, @@ -2704,13 +2708,13 @@ code = ''' assert(!lfsr_mdir_isdropped(&left_neighbor.mdir)); assert(left_neighbor.mdir.mid.bid == -1); assert(left_neighbor.mdir.mid.rid == 0); - assert(memcmp(&left_neighbor.mdir.m, &lfs.mroot.m, - sizeof(lfs.mroot.m)) == 0); + assert(memcmp(&left_neighbor.mdir.u, &lfs.mroot.u, + sizeof(lfs.mroot.u)) == 0); assert(!lfsr_mdir_isdropped(&right_neighbor.mdir)); assert(right_neighbor.mdir.mid.bid == -1); assert(right_neighbor.mdir.mid.rid == 2); - assert(memcmp(&right_neighbor.mdir.m, &lfs.mroot.m, - sizeof(lfs.mroot.m)) == 0); + assert(memcmp(&right_neighbor.mdir.u, &lfs.mroot.u, + sizeof(lfs.mroot.u)) == 0); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -2737,9 +2741,9 @@ code = ''' assert(lfsr_mtree_isinlined(&lfs)); lfsr_openedmdir_t left_neighbor = { - .mdir={.mid=LFSR_MID(-1, 0), .m=lfs.mroot.m}}; + .mdir={.mid=LFSR_MID(-1, 0), .u=lfs.mroot.u}}; lfsr_openedmdir_t right_neighbor = { - .mdir={.mid=LFSR_MID(-1, 1), .m=lfs.mroot.m}}; + .mdir={.mid=LFSR_MID(-1, 1), .u=lfs.mroot.u}}; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -2748,15 +2752,15 @@ code = ''' LFSR_ATTR(0, UNR, -1, NULL, 0))) => 0; // assert that an entry was removed - assert(lfs.mroot.m.rbyd.weight == 1); + assert(lfs.mroot.u.m.weight == 1); // 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 == -1); assert(right_neighbor.mdir.mid.rid == 0); - assert(memcmp(&right_neighbor.mdir.m, &lfs.mroot.m, - sizeof(lfs.mroot.m)) == 0); + assert(memcmp(&right_neighbor.mdir.u, &lfs.mroot.u, + sizeof(lfs.mroot.u)) == 0); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -2783,9 +2787,9 @@ code = ''' assert(lfsr_mtree_isinlined(&lfs)); lfsr_openedmdir_t left_neighbor = { - .mdir={.mid=LFSR_MID(-1, 0), .m=lfs.mroot.m}}; + .mdir={.mid=LFSR_MID(-1, 0), .u=lfs.mroot.u}}; lfsr_openedmdir_t right_neighbor = { - .mdir={.mid=LFSR_MID(-1, 1), .m=lfs.mroot.m}}; + .mdir={.mid=LFSR_MID(-1, 1), .u=lfs.mroot.u}}; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -2794,14 +2798,14 @@ code = ''' LFSR_ATTR(1, UNR, -1, NULL, 0))) => 0; // assert that an entry was removed - assert(lfs.mroot.m.rbyd.weight == 1); + assert(lfs.mroot.u.m.weight == 1); // assert that our neighbors were updated correctly assert(!lfsr_mdir_isdropped(&left_neighbor.mdir)); assert(left_neighbor.mdir.mid.bid == -1); assert(left_neighbor.mdir.mid.rid == 0); - assert(memcmp(&left_neighbor.mdir.m, &lfs.mroot.m, - sizeof(lfs.mroot.m)) == 0); + assert(memcmp(&left_neighbor.mdir.u, &lfs.mroot.u, + sizeof(lfs.mroot.u)) == 0); assert(lfsr_mdir_isdropped(&right_neighbor.mdir)); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); @@ -2831,9 +2835,9 @@ code = ''' assert(lfsr_mtree_isinlined(&lfs)); lfsr_openedmdir_t left_neighbor = { - .mdir={.mid=LFSR_MID(-1, 0), .m=lfs.mroot.m}}; + .mdir={.mid=LFSR_MID(-1, 0), .u=lfs.mroot.u}}; lfsr_openedmdir_t right_neighbor = { - .mdir={.mid=LFSR_MID(-1, 1), .m=lfs.mroot.m}}; + .mdir={.mid=LFSR_MID(-1, 1), .u=lfs.mroot.u}}; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -2849,13 +2853,13 @@ code = ''' LFSR_ATTR(1, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdir was unininlined correctly assert(lfsr_mtree_weight(&lfs) == 2); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -2865,7 +2869,7 @@ code = ''' // assert that our entry is still in the mtree lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 2); + assert(mdir.u.m.weight == 2); lfsr_mdir_get(&lfs, &mdir, 1, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[3 % 26], 1) == 0); @@ -2874,19 +2878,19 @@ code = ''' // but saves on code size lfsr_mdir_t msibling; lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &msibling) => 0; - assert(msibling.m.rbyd.weight == 1); + 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); assert(left_neighbor.mdir.mid.rid == 0); - assert(memcmp(&left_neighbor.mdir.m, &mdir.m, - sizeof(mdir.m)) == 0); + assert(memcmp(&left_neighbor.mdir.u, &mdir.u, + sizeof(mdir.u)) == 0); assert(!lfsr_mdir_isdropped(&right_neighbor.mdir)); assert(right_neighbor.mdir.mid.bid == 1); assert(right_neighbor.mdir.mid.rid == 0); - assert(memcmp(&right_neighbor.mdir.m, &msibling.m, - sizeof(msibling.m)) == 0); + assert(memcmp(&right_neighbor.mdir.u, &msibling.u, + sizeof(msibling.u)) == 0); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -2915,9 +2919,9 @@ code = ''' assert(lfsr_mtree_isinlined(&lfs)); lfsr_openedmdir_t left_neighbor = { - .mdir={.mid=LFSR_MID(-1, 0), .m=lfs.mroot.m}}; + .mdir={.mid=LFSR_MID(-1, 0), .u=lfs.mroot.u}}; lfsr_openedmdir_t right_neighbor = { - .mdir={.mid=LFSR_MID(-1, 1), .m=lfs.mroot.m}}; + .mdir={.mid=LFSR_MID(-1, 1), .u=lfs.mroot.u}}; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -2932,25 +2936,25 @@ code = ''' LFSR_ATTR(2, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs) == 2); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our entries are still in the mtree lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 2); + assert(mdir.u.m.weight == 2); lfsr_mdir_get(&lfs, &mdir, 1, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[2 % 26], 1) == 0); lfsr_mdir_t msibling; lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &msibling) => 0; - assert(msibling.m.rbyd.weight == 2); + assert(msibling.u.m.weight == 2); lfsr_mdir_get(&lfs, &msibling, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[3 % 26], 1) == 0); @@ -2959,13 +2963,13 @@ code = ''' assert(!lfsr_mdir_isdropped(&left_neighbor.mdir)); assert(left_neighbor.mdir.mid.bid == 0); assert(left_neighbor.mdir.mid.rid == 0); - assert(memcmp(&left_neighbor.mdir.m, &mdir.m, - sizeof(mdir.m)) == 0); + assert(memcmp(&left_neighbor.mdir.u, &mdir.u, + sizeof(mdir.u)) == 0); assert(!lfsr_mdir_isdropped(&right_neighbor.mdir)); assert(right_neighbor.mdir.mid.bid == 1); assert(right_neighbor.mdir.mid.rid == 1); - assert(memcmp(&right_neighbor.mdir.m, &msibling.m, - sizeof(msibling.m)) == 0); + assert(memcmp(&right_neighbor.mdir.u, &msibling.u, + sizeof(msibling.u)) == 0); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -2997,13 +3001,13 @@ code = ''' LFSR_ATTR(0, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdir was unininlined correctly assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // setup our neighbors // @@ -3011,19 +3015,19 @@ code = ''' // aggresively split the mtree if there are already neighbors in the mdir lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(0, INLINED, +1, &alphas[0 % 26], 1), LFSR_ATTR(2, INLINED, +1, &alphas[1 % 26], 1))) => 0; // this test only works if these all fit in the mdir assert(lfsr_mtree_weight(&lfs) == 1); - assert(mdir.m.rbyd.weight == 3); + assert(mdir.u.m.weight == 3); lfsr_openedmdir_t left_neighbor = { - .mdir={.mid=LFSR_MID(mdir.mid.bid, 0), .m=mdir.m}}; + .mdir={.mid=LFSR_MID(mdir.mid.bid, 0), .u=mdir.u}}; lfsr_openedmdir_t right_neighbor = { - .mdir={.mid=LFSR_MID(mdir.mid.bid, 2), .m=mdir.m}}; + .mdir={.mid=LFSR_MID(mdir.mid.bid, 2), .u=mdir.u}}; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -3033,13 +3037,13 @@ code = ''' LFSR_ATTR(2, INLINED, +1, buffer, SIZE))) => 0; // force mdir to compact - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &mdir, NULL, 0) => 0; // assert mdir was split correctly assert(lfsr_mtree_weight(&lfs) == 2); // assert mroot still has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -3048,14 +3052,14 @@ code = ''' // assert that our entries are still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 2); + assert(mdir.u.m.weight == 2); lfsr_mdir_get(&lfs, &mdir, 1, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[3 % 26], 1) == 0); lfsr_mdir_t msibling; lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &msibling) => 0; - assert(msibling.m.rbyd.weight == 2); + assert(msibling.u.m.weight == 2); lfsr_mdir_get(&lfs, &msibling, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[4 % 26], 1) == 0); @@ -3064,13 +3068,13 @@ code = ''' assert(!lfsr_mdir_isdropped(&left_neighbor.mdir)); assert(left_neighbor.mdir.mid.bid == 0); assert(left_neighbor.mdir.mid.rid == 0); - assert(memcmp(&left_neighbor.mdir.m, &mdir.m, - sizeof(mdir.m)) == 0); + assert(memcmp(&left_neighbor.mdir.u, &mdir.u, + sizeof(mdir.u)) == 0); assert(!lfsr_mdir_isdropped(&right_neighbor.mdir)); assert(right_neighbor.mdir.mid.bid == 1); assert(right_neighbor.mdir.mid.rid == 1); - assert(memcmp(&right_neighbor.mdir.m, &msibling.m, - sizeof(msibling.m)) == 0); + assert(memcmp(&right_neighbor.mdir.u, &msibling.u, + sizeof(msibling.u)) == 0); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -3101,9 +3105,9 @@ code = ''' assert(lfsr_mtree_isinlined(&lfs)); lfsr_openedmdir_t left_neighbor = { - .mdir={.mid=LFSR_MID(-1, 0), .m=lfs.mroot.m}}; + .mdir={.mid=LFSR_MID(-1, 0), .u=lfs.mroot.u}}; lfsr_openedmdir_t right_neighbor = { - .mdir={.mid=LFSR_MID(-1, 1), .m=lfs.mroot.m}}; + .mdir={.mid=LFSR_MID(-1, 1), .u=lfs.mroot.u}}; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -3116,15 +3120,15 @@ code = ''' // force mroot to compact twice, this should extend the mroot lfsr_mdir_t old_mroot = lfs.mroot; - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; memset(buffer, alphas[1 % 26], SIZE); lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( LFSR_ATTR(-1, UATTR(1), 0, buffer, SIZE))) => 0; // assert we relocated - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -3135,13 +3139,13 @@ code = ''' assert(!lfsr_mdir_isdropped(&left_neighbor.mdir)); assert(left_neighbor.mdir.mid.bid == -1); assert(left_neighbor.mdir.mid.rid == 0); - assert(memcmp(&left_neighbor.mdir.m, &lfs.mroot.m, - sizeof(lfs.mroot.m)) == 0); + assert(memcmp(&left_neighbor.mdir.u, &lfs.mroot.u, + sizeof(lfs.mroot.u)) == 0); assert(!lfsr_mdir_isdropped(&right_neighbor.mdir)); assert(right_neighbor.mdir.mid.bid == -1); assert(right_neighbor.mdir.mid.rid == 1); - assert(memcmp(&right_neighbor.mdir.m, &lfs.mroot.m, - sizeof(lfs.mroot.m)) == 0); + assert(memcmp(&right_neighbor.mdir.u, &lfs.mroot.u, + sizeof(lfs.mroot.u)) == 0); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -3175,13 +3179,13 @@ code = ''' LFSR_ATTR(0, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdir was unininlined correctly assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // setup our neighbors // @@ -3189,34 +3193,34 @@ code = ''' // aggresively split the mtree if there are already neighbors in the mdir lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(0, INLINED, +1, &alphas[0 % 26], 1), LFSR_ATTR(2, INLINED, +1, &alphas[1 % 26], 1))) => 0; // this test only works if these all fit in the mdir assert(lfsr_mtree_weight(&lfs) == 1); - assert(mdir.m.rbyd.weight == 3); + assert(mdir.u.m.weight == 3); lfsr_openedmdir_t left_neighbor = { - .mdir={.mid=LFSR_MID(mdir.mid.bid, 0), .m=mdir.m}}; + .mdir={.mid=LFSR_MID(mdir.mid.bid, 0), .u=mdir.u}}; lfsr_openedmdir_t right_neighbor = { - .mdir={.mid=LFSR_MID(mdir.mid.bid, 2), .m=mdir.m}}; + .mdir={.mid=LFSR_MID(mdir.mid.bid, 2), .u=mdir.u}}; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); // force mdir to compact twice, this should relocate lfsr_mdir_t old_mdir = mdir; - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &mdir, NULL, 0) => 0; - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; memset(buffer, alphas[4 % 26], SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(1, INLINED, 0, buffer, SIZE))) => 0; // assert we relocated - assert(lfsr_mdir_cmp(&old_mdir, &mdir) != 0); + assert(lfsr_mdir_cmp(old_mdir.u.m.blocks, mdir.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -3225,7 +3229,7 @@ code = ''' // assert that our entry is still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 3); + assert(mdir.u.m.weight == 3); lfsr_mdir_get(&lfs, &mdir, 1, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -3235,11 +3239,11 @@ code = ''' assert(!lfsr_mdir_isdropped(&left_neighbor.mdir)); assert(left_neighbor.mdir.mid.bid == 0); assert(left_neighbor.mdir.mid.rid == 0); - assert(memcmp(&left_neighbor.mdir.m, &mdir.m, sizeof(mdir.m)) == 0); + assert(memcmp(&left_neighbor.mdir.u, &mdir.u, sizeof(mdir.u)) == 0); assert(!lfsr_mdir_isdropped(&right_neighbor.mdir)); assert(right_neighbor.mdir.mid.bid == 0); assert(right_neighbor.mdir.mid.rid == 2); - assert(memcmp(&right_neighbor.mdir.m, &mdir.m, sizeof(mdir.m)) == 0); + assert(memcmp(&right_neighbor.mdir.u, &mdir.u, sizeof(mdir.u)) == 0); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -3274,7 +3278,7 @@ code = ''' LFSR_ATTR(1, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // we should now have 2 mdirs @@ -3283,13 +3287,13 @@ code = ''' // now force one of our siblings to split lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); memset(buffer, alphas[2 % 26], SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(1, INLINED, +1, buffer, SIZE))) => 0; // force mdir to compact - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &mdir, NULL, 0) => 0; // we should now have 3 mdirs @@ -3301,12 +3305,12 @@ code = ''' // setup our neighbors lfsr_openedmdir_t left_neighbor; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &left_neighbor.mdir) => 0; - assert(left_neighbor.mdir.m.rbyd.weight == 1); + 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, -1), &right_neighbor.mdir) => 0; - assert(right_neighbor.mdir.m.rbyd.weight == 1); + assert(right_neighbor.mdir.u.m.weight == 1); right_neighbor.mdir.mid.rid = 0; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); @@ -3314,13 +3318,13 @@ code = ''' // cause middle mdir to split lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); memset(buffer, alphas[3 % 26], SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(1, INLINED, +1, buffer, SIZE))) => 0; // force mdir to compact - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &mdir, NULL, 0) => 0; // we should now have 4 mdirs @@ -3331,12 +3335,12 @@ code = ''' assert(left_neighbor.mdir.mid.bid == 0); assert(left_neighbor.mdir.mid.rid == 0); lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(memcmp(&left_neighbor.mdir.m, &mdir.m, sizeof(mdir.m)) == 0); + assert(memcmp(&left_neighbor.mdir.u, &mdir.u, sizeof(mdir.u)) == 0); assert(right_neighbor.mdir.mid.bid == 3); assert(right_neighbor.mdir.mid.rid == 0); lfsr_mtree_lookup(&lfs, LFSR_MID(3, -1), &mdir) => 0; - assert(memcmp(&right_neighbor.mdir.m, &mdir.m, sizeof(mdir.m)) == 0); + assert(memcmp(&right_neighbor.mdir.u, &mdir.u, sizeof(mdir.u)) == 0); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -3371,7 +3375,7 @@ code = ''' LFSR_ATTR(1, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // we should now have 2 mdirs @@ -3380,13 +3384,13 @@ code = ''' // now force one of our siblings to split lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); memset(buffer, alphas[2 % 26], SIZE); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(1, INLINED, +1, buffer, SIZE))) => 0; // force mdir to compact - mdir.m.rbyd.off = BLOCK_SIZE; + mdir.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &mdir, NULL, 0) => 0; // we should now have 3 mdirs @@ -3398,12 +3402,12 @@ code = ''' // setup our neighbors lfsr_openedmdir_t left_neighbor; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &left_neighbor.mdir) => 0; - assert(left_neighbor.mdir.m.rbyd.weight == 1); + 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, -1), &right_neighbor.mdir) => 0; - assert(right_neighbor.mdir.m.rbyd.weight == 1); + assert(right_neighbor.mdir.u.m.weight == 1); right_neighbor.mdir.mid.rid = 0; lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); @@ -3411,7 +3415,7 @@ code = ''' // cause middle mdir to drop lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( LFSR_ATTR(0, UNR, -1, NULL, 0))) => 0; @@ -3423,13 +3427,13 @@ code = ''' assert(left_neighbor.mdir.mid.bid == 0); assert(left_neighbor.mdir.mid.rid == 0); lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(memcmp(&left_neighbor.mdir.m, &mdir.m, sizeof(mdir.m)) == 0); + assert(memcmp(&left_neighbor.mdir.u, &mdir.u, sizeof(mdir.u)) == 0); assert(!lfsr_mdir_isdropped(&right_neighbor.mdir)); assert(right_neighbor.mdir.mid.bid == 1); assert(right_neighbor.mdir.mid.rid == 0); lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &mdir) => 0; - assert(memcmp(&right_neighbor.mdir.m, &mdir.m, sizeof(mdir.m)) == 0); + assert(memcmp(&right_neighbor.mdir.u, &mdir.u, sizeof(mdir.u)) == 0); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); @@ -3458,7 +3462,7 @@ code = ''' LFSR_ATTR(0, INLINED, +1, &alphas[0 % 26], 1))) => 0; // assert that our entry is still in the mtree - assert(lfs.mroot.m.rbyd.weight == 1); + assert(lfs.mroot.u.m.weight == 1); uint8_t buffer[1]; lfsr_mdir_get(&lfs, &lfs.mroot, 0, LFSR_TAG_INLINED, @@ -3502,11 +3506,11 @@ code = ''' mid_.bid, mid_.rid, tag_, - mdir->m.rbyd.block, mdir->m.redund_block); + mdir->u.m.blocks[1], mdir->u.m.blocks[0]); // keep track of seen blocks - seen[mdir->m.rbyd.block / 8] |= 1 << (mdir->m.rbyd.block % 8); - seen[mdir->m.redund_block / 8] |= 1 << (mdir->m.redund_block % 8); + seen[mdir->u.m.blocks[1] / 8] |= 1 << (mdir->u.m.blocks[1] % 8); + 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", @@ -3532,7 +3536,7 @@ code = ''' // and the tree should still work // assert that our entry is still in the mtree - assert(lfs.mroot.m.rbyd.weight == 1); + assert(lfs.mroot.u.m.weight == 1); lfsr_mdir_get(&lfs, &lfs.mroot, 0, LFSR_TAG_INLINED, buffer, 1) => 1; @@ -3568,13 +3572,13 @@ code = ''' LFSR_ATTR(0, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdir was unininlined correctly assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -3584,7 +3588,7 @@ code = ''' // assert that our entry is still in the mtree lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -3627,11 +3631,11 @@ code = ''' mid_.bid, mid_.rid, tag_, - mdir->m.rbyd.block, mdir->m.redund_block); + mdir->u.m.blocks[1], mdir->u.m.blocks[0]); // keep track of seen blocks - seen[mdir->m.rbyd.block / 8] |= 1 << (mdir->m.rbyd.block % 8); - seen[mdir->m.redund_block / 8] |= 1 << (mdir->m.redund_block % 8); + seen[mdir->u.m.blocks[1] / 8] |= 1 << (mdir->u.m.blocks[1] % 8); + 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", @@ -3659,7 +3663,7 @@ code = ''' // assert mdir was unininlined correctly assert(lfsr_mtree_weight(&lfs) == 1); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -3668,7 +3672,7 @@ code = ''' // assert that our entry is still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; @@ -3703,25 +3707,25 @@ code = ''' LFSR_ATTR(1, INLINED, +1, buffer, SIZE))) => 0; // force mroot to compact - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs) == 2); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our entries are still in the mtree lfsr_mdir_t mdir; lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[0 % 26], 1) == 0); lfsr_mdir_t msibling; lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &msibling) => 0; - assert(msibling.m.rbyd.weight == 1); + assert(msibling.u.m.weight == 1); lfsr_mdir_get(&lfs, &msibling, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[1 % 26], 1) == 0); @@ -3763,11 +3767,11 @@ code = ''' mid_.bid, mid_.rid, tag_, - mdir->m.rbyd.block, mdir->m.redund_block); + mdir->u.m.blocks[1], mdir->u.m.blocks[0]); // keep track of seen blocks - seen[mdir->m.rbyd.block / 8] |= 1 << (mdir->m.rbyd.block % 8); - seen[mdir->m.redund_block / 8] |= 1 << (mdir->m.redund_block % 8); + seen[mdir->u.m.blocks[1] / 8] |= 1 << (mdir->u.m.blocks[1] % 8); + 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", @@ -3795,17 +3799,17 @@ code = ''' // assert mdirs were unininlined and split assert(lfsr_mtree_weight(&lfs) == 2); // assert mroot now has no entries - assert(lfs.mroot.m.rbyd.weight == 0); + assert(lfs.mroot.u.m.weight == 0); // assert that our entries are still in the mtree lfsr_mtree_lookup(&lfs, LFSR_MID(0, -1), &mdir) => 0; - assert(mdir.m.rbyd.weight == 1); + assert(mdir.u.m.weight == 1); lfsr_mdir_get(&lfs, &mdir, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[0 % 26], 1) == 0); lfsr_mtree_lookup(&lfs, LFSR_MID(1, -1), &msibling) => 0; - assert(msibling.m.rbyd.weight == 1); + assert(msibling.u.m.weight == 1); lfsr_mdir_get(&lfs, &msibling, 0, LFSR_TAG_INLINED, buffer, SIZE) => SIZE; assert(memcmp(buffer, &alphas[1 % 26], 1) == 0); @@ -3839,15 +3843,15 @@ code = ''' // force mroot to compact twice, this should extend the mroot lfsr_mdir_t old_mroot = lfs.mroot; - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; memset(buffer, alphas[1 % 26], SIZE); lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( LFSR_ATTR(-1, UATTR(1), 0, buffer, SIZE))) => 0; // assert we relocated - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -3891,11 +3895,11 @@ code = ''' mid_.bid, mid_.rid, tag_, - mdir->m.rbyd.block, mdir->m.redund_block); + mdir->u.m.blocks[1], mdir->u.m.blocks[0]); // keep track of seen blocks - seen[mdir->m.rbyd.block / 8] |= 1 << (mdir->m.rbyd.block % 8); - seen[mdir->m.redund_block / 8] |= 1 << (mdir->m.redund_block % 8); + seen[mdir->u.m.blocks[1] / 8] |= 1 << (mdir->u.m.blocks[1] % 8); + 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", @@ -3921,7 +3925,7 @@ code = ''' // and the tree should still work // assert we relocated - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -3949,14 +3953,15 @@ code = ''' // create entries lfsr_mdir_t mdir; - lfsr_mtree_lookup(&lfs, LFSR_MID(lfsr_mtree_weight(&lfs)-1, -1), &mdir) => 0; + lfsr_mtree_lookup(&lfs, LFSR_MID(lfsr_mtree_weight(&lfs)-1, -1), + &mdir) => 0; mdir.mid.rid = 0; for (lfs_size_t i = 0; i < N; i++) { // force a compaction? if (FORCE_COMPACTION) { - mdir.m.rbyd.off = CFG->block_size; - lfs.mroot.m.rbyd.off = CFG->block_size; + mdir.u.r.rbyd.off = CFG->block_size; + lfs.mroot.u.r.rbyd.off = CFG->block_size; } lfsr_mdir_commit(&lfs, &mdir, LFSR_ATTRS( @@ -3978,7 +3983,7 @@ code = ''' 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.m.rbyd.weight; + mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; mdir.mid.rid++) { uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_INLINED, @@ -4026,11 +4031,11 @@ code = ''' mid_.bid, mid_.rid, tag_, - mdir->m.rbyd.block, mdir->m.redund_block); + mdir->u.m.blocks[1], mdir->u.m.blocks[0]); // keep track of seen blocks - seen[mdir->m.rbyd.block / 8] |= 1 << (mdir->m.rbyd.block % 8); - seen[mdir->m.redund_block / 8] |= 1 << (mdir->m.redund_block % 8); + seen[mdir->u.m.blocks[1] / 8] |= 1 << (mdir->u.m.blocks[1] % 8); + 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", @@ -4063,7 +4068,7 @@ code = ''' 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.m.rbyd.weight; + mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; mdir.mid.rid++) { uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_INLINED, @@ -4107,12 +4112,12 @@ code = ''' 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.m.rbyd.weight+1); + mdir.mid.rid = TEST_PRNG(&prng) % (mdir.u.m.weight+1); // force a compaction? if (FORCE_COMPACTION) { - mdir.m.rbyd.off = CFG->block_size; - lfs.mroot.m.rbyd.off = CFG->block_size; + mdir.u.r.rbyd.off = CFG->block_size; + lfs.mroot.u.r.rbyd.off = CFG->block_size; } // add to rbyd, potentially splitting the mdir @@ -4137,7 +4142,7 @@ code = ''' 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.m.rbyd.weight; + mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; mdir.mid.rid++) { uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_INLINED, @@ -4189,11 +4194,11 @@ code = ''' mid_.bid, mid_.rid, tag_, - mdir->m.rbyd.block, mdir->m.redund_block); + mdir->u.m.blocks[1], mdir->u.m.blocks[0]); // keep track of seen blocks - seen[mdir->m.rbyd.block / 8] |= 1 << (mdir->m.rbyd.block % 8); - seen[mdir->m.redund_block / 8] |= 1 << (mdir->m.redund_block % 8); + seen[mdir->u.m.blocks[1] / 8] |= 1 << (mdir->u.m.blocks[1] % 8); + 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", @@ -4227,7 +4232,7 @@ code = ''' 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.m.rbyd.weight; + mdir.mid.rid < (lfs_ssize_t)mdir.u.m.weight; mdir.mid.rid++) { uint8_t buffer[4]; lfsr_mdir_get(&lfs, &mdir, mdir.mid.rid, LFSR_TAG_INLINED, @@ -4256,8 +4261,8 @@ code = ''' lfsr_mount(&lfs, CFG) => 0; lfs_alloc_ack(&lfs); - uint8_t buffer[LFSR_MPTR_DSIZE]; - lfs_ssize_t d = lfsr_mptr_todisk(&lfs, LFSR_MPTR_MROOTANCHOR, buffer); + uint8_t buffer[LFSR_MDIR_DSIZE]; + lfs_ssize_t d = lfsr_mdir_todisk(&lfs, LFSR_MDIR_MROOTANCHOR, buffer); assert(d >= 0); lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( LFSR_ATTR(-1, MROOT, 0, buffer, d))) => 0; @@ -4293,7 +4298,7 @@ code = ''' mid_.bid, mid_.rid, tag_, - mdir->m.rbyd.block, mdir->m.redund_block); + mdir->u.m.blocks[1], mdir->u.m.blocks[0]); } else { // this shouldn't happen printf("traversal: %d.%d 0x%x %d\n", @@ -4353,15 +4358,15 @@ code = ''' // force mroot to compact twice, this should extend the mroot lfsr_mdir_t old_mroot = lfs.mroot; - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; memset(buffer, alphas[1 % 26], SIZE); lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( LFSR_ATTR(-1, UATTR(1), 0, buffer, SIZE))) => 0; // assert we relocated - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1), @@ -4409,16 +4414,16 @@ code = ''' lfsr_mdir_t old_mroot = lfs.mroot; for (int i = 0; i < 4; i++) { - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; lfsr_mdir_commit(&lfs, &lfs.mroot, NULL, 0) => 0; } - lfs.mroot.m.rbyd.off = BLOCK_SIZE; + lfs.mroot.u.r.rbyd.off = BLOCK_SIZE; memset(buffer, alphas[1 % 26], SIZE); lfsr_mdir_commit(&lfs, &lfs.mroot, LFSR_ATTRS( LFSR_ATTR(-1, UATTR(1), 0, buffer, SIZE))) => 0; // assert we relocated - assert(lfsr_mdir_cmp(&old_mroot, &lfs.mroot) != 0); + assert(lfsr_mdir_cmp(old_mroot.u.m.blocks, lfs.mroot.u.m.blocks) != 0); // assert that our attr is still in the mroot lfsr_mdir_get(&lfs, &lfs.mroot, -1, LFSR_TAG_UATTR(1),