From 10c0a60ced753679527ffad5af4afcf2af41b431 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Fri, 27 Jun 2025 18:03:13 -0500 Subject: [PATCH] Tried to dedup bptr/data fetching Like the bshrub/btree dedup, this add lfs3_bptr_fetch to help dedup bptr/data fetching. The original plan was to eliminate bptrs from lfs3_file_lookupnext and lfs3_file_traverse, and just return tagged data like the other lookup/traverse functions. But this didn't work out very well. We return arbitrary attrs from lfs3_file_traverse, so all this would've accomplished is making every lfs3_file_lookupnext call messier. But I think I'm still going to keep lfs3_bptr_fetch around as it provides a nice place to deduplicate some other bits of logic: - It makes sense to limit bptrs to compressed weights here, as opposed to the somewhat arbitrary lfs3_file_lookupnext function. - And it would be a bit silly to not put the bptr's LFS3_CKFETCHES logic in lfs3_bptr_fetch. This may fetch more than previously (during crystallization pokes?), but better safe than sorry. LFS3_CKFETCHES will likely be a relatively niche feature anyways. As for lfs3_file_traverse, I got rid of it completely. We already have special logic in lfs3_mtree_traverse_ and lfs3_file_ck for bptrs anyways, since bptrs, unlike data fragments, reference actual blocks. And this disentangles lfs3_mtree_traverse_ from the file APIs, which was a bit of an awkward design. --- This adds a bit of code to the default build, but I think it's worth it for the better code organization: code stack ctx before: 37896 2424 636 after: 37964 (+0.2%) 2424 (+0.0%) 636 (+0.0%) It also saves some code in LFS3_CKFETCHES mode, thanks to deduping all the fetch ckfetches fetch checkhes: code stack ctx ckfetches before: 38144 2464 636 ckfetches after: 38072 (-0.2%) 2472 (+0.3%) 636 (+0.0%) --- lfs3.c | 204 ++++++++++++++--------------------------- tests/test_fwrite.toml | 130 ++++++++++++++++---------- 2 files changed, 151 insertions(+), 183 deletions(-) diff --git a/lfs3.c b/lfs3.c index c5cdd904..18d624dc 100644 --- a/lfs3.c +++ b/lfs3.c @@ -2604,6 +2604,51 @@ static int lfs3_data_readbptr(lfs3_t *lfs3, lfs3_data_t *data, } #endif +// needed in lfs3_bptr_fetch +#ifdef LFS3_CKFETCHES +static inline bool lfs3_m_isckfetches(uint32_t flags); +#endif +static int lfs3_bptr_ck(lfs3_t *lfs3, const lfs3_bptr_t *bptr); + +// fetch a bptr or data fragment +static int lfs3_bptr_fetch(lfs3_t *lfs3, lfs3_bptr_t *bptr, + lfs3_tag_t tag, lfs3_bid_t weight, lfs3_data_t data) { + // fragment? (inlined data) + if (tag == LFS3_TAG_DATA) { + bptr->data = data; + + // bptr? + } else if (LFS3_IFDEF_2BONLY(false, tag == LFS3_TAG_BLOCK)) { + #ifndef LFS3_2BONLY + int err = lfs3_data_readbptr(lfs3, &data, + bptr); + if (err) { + return err; + } + #endif + + } else { + LFS3_UNREACHABLE(); + } + + // limit bptrs to btree weights, this may be useful for + // compression in the future + bptr->data = LFS3_DATA_TRUNCATE(bptr->data, weight); + + // checking fetches? + #ifdef LFS3_CKFETCHES + if (lfs3_m_isckfetches(lfs3->flags) + && lfs3_bptr_isbptr(bptr)) { + int err = lfs3_bptr_ck(lfs3, bptr); + if (err) { + return err; + } + } + #endif + + return 0; +} + // check the contents of a bptr #ifndef LFS3_2BONLY static int lfs3_bptr_ck(lfs3_t *lfs3, const lfs3_bptr_t *bptr) { @@ -5068,11 +5113,6 @@ static int lfs3_data_readbranch(lfs3_t *lfs3, } #endif -// needed in lfs3_branch_fetch -#ifdef LFS3_CKFETCHES -static inline bool lfs3_m_isckfetches(uint32_t flags); -#endif - #ifndef LFS3_2BONLY static int lfs3_branch_fetch(lfs3_t *lfs3, lfs3_rbyd_t *branch, lfs3_block_t block, lfs3_size_t trunk, lfs3_bid_t weight, @@ -9694,11 +9734,6 @@ static void lfs3_traversal_init(lfs3_traversal_t *t, uint32_t flags) { t->gcksum = 0; } -// needed in lfs3_mtree_traverse_ -static int lfs3_file_traverse_(lfs3_t *lfs3, const lfs3_bshrub_t *bshrub, - lfs3_btraversal_t *bt, - lfs3_bid_t *bid_, lfs3_tag_t *tag_, lfs3_bptr_t *bptr); - // low-level traversal _only_ finds blocks static int lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_traversal_t *t, lfs3_tag_t *tag_, lfs3_bptr_t *bptr) { @@ -9923,12 +9958,8 @@ static int lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_traversal_t *t, case LFS3_TSTATE_BTREE:; case LFS3_TSTATE_OBTREE:; // traverse through our bshrub/btree - // - // it probably looks a bit weird to go through - // lfs3_file_traverse_, but this gets us bptr decoding - // for free - err = lfs3_file_traverse_(lfs3, &t->b, &t->u.bt, - NULL, &tag, bptr); + err = lfs3_bshrub_traverse(lfs3, &t->b, &t->u.bt, + NULL, &tag, &data); if (err) { if (err == LFS3_ERR_NOENT) { // clear the bshrub state @@ -9964,14 +9995,22 @@ static int lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_traversal_t *t, if (tag_) { *tag_ = tag; } + bptr->data = data; return 0; // found an indirect block? - } else if (tag == LFS3_TAG_BLOCK) { + } else if (LFS3_IFDEF_2BONLY(false, tag == LFS3_TAG_BLOCK)) { + #ifndef LFS3_2BONLY if (tag_) { *tag_ = tag; } + err = lfs3_data_readbptr(lfs3, &data, + bptr); + if (err) { + return err; + } return 0; + #endif } continue; @@ -11930,24 +11969,12 @@ static int lfs3_file_lookupnext_(lfs3_t *lfs3, const lfs3_file_t *file, LFS3_ASSERT(tag == LFS3_TAG_DATA || tag == LFS3_TAG_BLOCK); - // decode bptrs - if (tag == LFS3_TAG_DATA) { - bptr_->data = data; - } else if (LFS3_IFDEF_2BONLY(false, tag == LFS3_TAG_BLOCK)) { - #ifndef LFS3_2BONLY - err = lfs3_data_readbptr(lfs3, &data, bptr_); - if (err) { - return err; - } - #endif - } else { - LFS3_UNREACHABLE(); + // fetch the bptr/data fragment + err = lfs3_bptr_fetch(lfs3, bptr_, tag, weight, data); + if (err) { + return err; } - // limit bptrs to btree weights, this may be useful for - // compression in the future - bptr_->data = LFS3_DATA_TRUNCATE(bptr_->data, weight); - if (weight_) { *weight_ = weight; } @@ -12072,17 +12099,6 @@ static lfs3_ssize_t lfs3_file_readnext(lfs3_t *lfs3, lfs3_file_t *file, return err; } - // checking fetches? - #ifdef LFS3_CKFETCHES - if (lfs3_m_isckfetches(lfs3->flags) - && lfs3_bptr_isbptr(&bptr)) { - err = lfs3_bptr_ck(lfs3, &bptr); - if (err) { - return err; - } - } - #endif - #ifndef LFS3_KVONLY file->leaf.pos = bid - (weight-1); file->leaf.weight = weight; @@ -12317,17 +12333,6 @@ static int lfs3_file_graft(lfs3_t *lfs3, lfs3_file_t *file, return err; } - // checking fetches? - #ifdef LFS3_CKFETCHES - if (lfs3_m_isckfetches(lfs3->flags) - && lfs3_bptr_isbptr(&bptr_)) { - err = lfs3_bptr_ck(lfs3, &bptr_); - if (err) { - return err; - } - } - #endif - // note, an entry can be both a left and right sibling l = bptr_; l.data = LFS3_DATA_SLICE(bptr_.data, @@ -12628,17 +12633,6 @@ static int lfs3_file_crystallize_(lfs3_t *lfs3, lfs3_file_t *file, return err; } - // checking fetches? - #ifdef LFS3_CKFETCHES - if (lfs3_m_isckfetches(lfs3->flags) - && lfs3_bptr_isbptr(&bptr__)) { - err = lfs3_bptr_ck(lfs3, &bptr__); - if (err) { - return err; - } - } - #endif - // is this data a pure hole? stop early to (FUTURE) // better leverage erased-state in sparse files, and to // try to avoid writing a bunch of unnecessary zeros @@ -13235,17 +13229,6 @@ fragment:; return err; } - // checking fetches? - #ifdef LFS3_CKFETCHES - if (lfs3_m_isckfetches(lfs3->flags) - && lfs3_bptr_isbptr(&bptr)) { - err = lfs3_bptr_ck(lfs3, &bptr); - if (err) { - return err; - } - } - #endif - // can we coalesce? if (bid-(weight-1) + lfs3_bptr_size(&bptr) >= fragment_start && fragment_end - (bid-(weight-1)) @@ -13282,17 +13265,6 @@ fragment:; return err; } - // checking fetches? - #ifdef LFS3_CKFETCHES - if (lfs3_m_isckfetches(lfs3->flags) - && lfs3_bptr_isbptr(&bptr)) { - err = lfs3_bptr_ck(lfs3, &bptr); - if (err) { - return err; - } - } - #endif - // can we coalesce? if (fragment_end < bid-(weight-1) + lfs3_bptr_size(&bptr) && bid-(weight-1) + lfs3_bptr_size(&bptr) @@ -14201,47 +14173,6 @@ failed:; // file check functions -#ifndef LFS3_2BONLY -static int lfs3_file_traverse_(lfs3_t *lfs3, const lfs3_bshrub_t *bshrub, - lfs3_btraversal_t *bt, - lfs3_bid_t *bid_, lfs3_tag_t *tag_, lfs3_bptr_t *bptr) { - lfs3_tag_t tag; - lfs3_data_t data; - int err = lfs3_bshrub_traverse(lfs3, bshrub, bt, - bid_, &tag, &data); - if (err) { - return err; - } - - // decode bptrs - if (LFS3_IFDEF_2BONLY(false, tag == LFS3_TAG_BLOCK)) { - #ifndef LFS3_2BONLY - err = lfs3_data_readbptr(lfs3, &data, - bptr); - if (err) { - return err; - } - #endif - } else { - bptr->data = data; - } - - if (tag_) { - *tag_ = tag; - } - return 0; -} -#endif - -#if !defined(LFS3_KVONLY) && !defined(LFS3_2BONLY) -static int lfs3_file_traverse(lfs3_t *lfs3, const lfs3_file_t *file, - lfs3_btraversal_t *bt, - lfs3_bid_t *bid_, lfs3_tag_t *tag_, lfs3_bptr_t *bptr) { - return lfs3_file_traverse_(lfs3, &file->b, bt, - bid_, tag_, bptr); -} -#endif - #if !defined(LFS3_KVONLY) && !defined(LFS3_2BONLY) static int lfs3_file_ck(lfs3_t *lfs3, const lfs3_file_t *file, uint32_t flags) { @@ -14260,9 +14191,9 @@ static int lfs3_file_ck(lfs3_t *lfs3, const lfs3_file_t *file, lfs3_btraversal_init(&bt); while (true) { lfs3_tag_t tag; - lfs3_bptr_t bptr; - int err = lfs3_file_traverse(lfs3, file, &bt, - NULL, &tag, &bptr); + lfs3_data_t data; + int err = lfs3_bshrub_traverse(lfs3, &file->b, &bt, + NULL, &tag, &data); if (err) { if (err == LFS3_ERR_NOENT) { break; @@ -14278,7 +14209,7 @@ static int lfs3_file_ck(lfs3_t *lfs3, const lfs3_file_t *file, if ((lfs3_t_isckmeta(flags) || lfs3_t_isckdata(flags)) && tag == LFS3_TAG_BRANCH) { - lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer; + lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer; err = lfs3_rbyd_fetchck(lfs3, rbyd, rbyd->blocks[0], rbyd->trunk, rbyd->cksum); @@ -14290,6 +14221,13 @@ static int lfs3_file_ck(lfs3_t *lfs3, const lfs3_file_t *file, // validate data blocks? if (lfs3_t_isckdata(flags) && tag == LFS3_TAG_BLOCK) { + lfs3_bptr_t bptr; + err = lfs3_data_readbptr(lfs3, &data, + &bptr); + if (err) { + return err; + } + err = lfs3_bptr_ck(lfs3, &bptr); if (err) { return err; diff --git a/tests/test_fwrite.toml b/tests/test_fwrite.toml index 4c5f38e7..ae3f8bf8 100644 --- a/tests/test_fwrite.toml +++ b/tests/test_fwrite.toml @@ -191,16 +191,16 @@ code = ''' lfs3_bid_t bid; lfs3_tag_t tag; - lfs3_bptr_t bptr; - int err = lfs3_file_traverse(&lfs3, &file, &bt, - &bid, &tag, &bptr); + lfs3_data_t data; + int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt, + &bid, &tag, &data); assert(!err || err == LFS3_ERR_NOENT); if (err == LFS3_ERR_NOENT) { break; } if (tag == LFS3_TAG_BRANCH) { - lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer; + lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer; printf("traversal: %d 0x%x btree 0x%x.%x\n", bid, tag, @@ -210,12 +210,15 @@ code = ''' printf("traversal: %d 0x%x data %d\n", bid, tag, - lfs3_data_size(bptr.data)); + lfs3_data_size(data)); // keep track of how many fragments we've seen fragments += 1; } else if (tag == LFS3_TAG_BLOCK) { + lfs3_bptr_t bptr; + lfs3_data_readbptr(&lfs3, &data, + &bptr) => 0; printf("traversal: %d 0x%x block 0x%x.%x %d\n", bid, tag, @@ -331,16 +334,16 @@ code = ''' lfs3_bid_t bid; lfs3_tag_t tag; - lfs3_bptr_t bptr; - int err = lfs3_file_traverse(&lfs3, &file, &bt, - &bid, &tag, &bptr); + lfs3_data_t data; + int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt, + &bid, &tag, &data); assert(!err || err == LFS3_ERR_NOENT); if (err == LFS3_ERR_NOENT) { break; } if (tag == LFS3_TAG_BRANCH) { - lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer; + lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer; printf("traversal: %d 0x%x btree 0x%x.%x\n", bid, tag, @@ -350,13 +353,16 @@ code = ''' printf("traversal: %d 0x%x data %d\n", bid, tag, - lfs3_data_size(bptr.data)); + lfs3_data_size(data)); // if block crystallization is working we shouldn't be // left with any inlined data fragments assert(false); } else if (tag == LFS3_TAG_BLOCK) { + lfs3_bptr_t bptr; + lfs3_data_readbptr(&lfs3, &data, + &bptr) => 0; printf("traversal: %d 0x%x block 0x%x.%x %d\n", bid, tag, @@ -589,16 +595,16 @@ code = ''' lfs3_bid_t bid; lfs3_tag_t tag; - lfs3_bptr_t bptr; - int err = lfs3_file_traverse(&lfs3, &file, &bt, - &bid, &tag, &bptr); + lfs3_data_t data; + int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt, + &bid, &tag, &data); assert(!err || err == LFS3_ERR_NOENT); if (err == LFS3_ERR_NOENT) { break; } if (tag == LFS3_TAG_BRANCH) { - lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer; + lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer; printf("traversal: %d 0x%x btree 0x%x.%x\n", bid, tag, @@ -608,12 +614,15 @@ code = ''' printf("traversal: %d 0x%x data %d\n", bid, tag, - lfs3_data_size(bptr.data)); + lfs3_data_size(data)); // keep track of how many fragments we've seen fragments += 1; } else if (tag == LFS3_TAG_BLOCK) { + lfs3_bptr_t bptr; + lfs3_data_readbptr(&lfs3, &data, + &bptr) => 0; printf("traversal: %d 0x%x block 0x%x.%x %d\n", bid, tag, @@ -744,16 +753,16 @@ code = ''' lfs3_bid_t bid; lfs3_tag_t tag; - lfs3_bptr_t bptr; - int err = lfs3_file_traverse(&lfs3, &file, &bt, - &bid, &tag, &bptr); + lfs3_data_t data; + int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt, + &bid, &tag, &data); assert(!err || err == LFS3_ERR_NOENT); if (err == LFS3_ERR_NOENT) { break; } if (tag == LFS3_TAG_BRANCH) { - lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer; + lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer; printf("traversal: %d 0x%x btree 0x%x.%x\n", bid, tag, @@ -763,13 +772,16 @@ code = ''' printf("traversal: %d 0x%x data %d\n", bid, tag, - lfs3_data_size(bptr.data)); + lfs3_data_size(data)); // if block crystallization is working we shouldn't be // left with any inlined data fragments assert(false); } else if (tag == LFS3_TAG_BLOCK) { + lfs3_bptr_t bptr; + lfs3_data_readbptr(&lfs3, &data, + &bptr) => 0; printf("traversal: %d 0x%x block 0x%x.%x %d\n", bid, tag, @@ -2064,16 +2076,16 @@ code = ''' lfs3_bid_t bid; lfs3_tag_t tag; - lfs3_bptr_t bptr; - int err = lfs3_file_traverse(&lfs3, &file, &bt, - &bid, &tag, &bptr); + lfs3_data_t data; + int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt, + &bid, &tag, &data); assert(!err || err == LFS3_ERR_NOENT); if (err == LFS3_ERR_NOENT) { break; } if (tag == LFS3_TAG_BRANCH) { - lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer; + lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer; printf("traversal: %d 0x%x btree 0x%x.%x\n", bid, tag, @@ -2083,12 +2095,15 @@ code = ''' printf("traversal: %d 0x%x data %d\n", bid, tag, - lfs3_data_size(bptr.data)); + lfs3_data_size(data)); // keep track of how many fragments we've seen fragments += 1; } else if (tag == LFS3_TAG_BLOCK) { + lfs3_bptr_t bptr; + lfs3_data_readbptr(&lfs3, &data, + &bptr) => 0; printf("traversal: %d 0x%x block 0x%x.%x %d\n", bid, tag, @@ -2208,16 +2223,16 @@ code = ''' lfs3_bid_t bid; lfs3_tag_t tag; - lfs3_bptr_t bptr; - int err = lfs3_file_traverse(&lfs3, &file, &bt, - &bid, &tag, &bptr); + lfs3_data_t data; + int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt, + &bid, &tag, &data); assert(!err || err == LFS3_ERR_NOENT); if (err == LFS3_ERR_NOENT) { break; } if (tag == LFS3_TAG_BRANCH) { - lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer; + lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer; printf("traversal: %d 0x%x btree 0x%x.%x\n", bid, tag, @@ -2227,12 +2242,15 @@ code = ''' printf("traversal: %d 0x%x data %d\n", bid, tag, - lfs3_data_size(bptr.data)); + lfs3_data_size(data)); // keep track of how many fragments we've seen fragments += 1; } else if (tag == LFS3_TAG_BLOCK) { + lfs3_bptr_t bptr; + lfs3_data_readbptr(&lfs3, &data, + &bptr) => 0; printf("traversal: %d 0x%x block 0x%x.%x %d\n", bid, tag, @@ -2499,16 +2517,16 @@ code = ''' lfs3_bid_t bid; lfs3_tag_t tag; - lfs3_bptr_t bptr; - int err = lfs3_file_traverse(&lfs3, &file, &bt, - &bid, &tag, &bptr); + lfs3_data_t data; + int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt, + &bid, &tag, &data); assert(!err || err == LFS3_ERR_NOENT); if (err == LFS3_ERR_NOENT) { break; } if (tag == LFS3_TAG_BRANCH) { - lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer; + lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer; printf("traversal: %d 0x%x btree 0x%x.%x\n", bid, tag, @@ -2518,12 +2536,15 @@ code = ''' printf("traversal: %d 0x%x data %d\n", bid, tag, - lfs3_data_size(bptr.data)); + lfs3_data_size(data)); // keep track of how many fragments we've seen fragments += 1; } else if (tag == LFS3_TAG_BLOCK) { + lfs3_bptr_t bptr; + lfs3_data_readbptr(&lfs3, &data, + &bptr) => 0; printf("traversal: %d 0x%x block 0x%x.%x %d\n", bid, tag, @@ -2658,16 +2679,16 @@ code = ''' lfs3_bid_t bid; lfs3_tag_t tag; - lfs3_bptr_t bptr; - int err = lfs3_file_traverse(&lfs3, &file, &bt, - &bid, &tag, &bptr); + lfs3_data_t data; + int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt, + &bid, &tag, &data); assert(!err || err == LFS3_ERR_NOENT); if (err == LFS3_ERR_NOENT) { break; } if (tag == LFS3_TAG_BRANCH) { - lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer; + lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer; printf("traversal: %d 0x%x btree 0x%x.%x\n", bid, tag, @@ -2677,13 +2698,16 @@ code = ''' printf("traversal: %d 0x%x data %d\n", bid, tag, - lfs3_data_size(bptr.data)); + lfs3_data_size(data)); // if block crystallization is working we shouldn't be // left with any inlined data fragments assert(false); } else if (tag == LFS3_TAG_BLOCK) { + lfs3_bptr_t bptr; + lfs3_data_readbptr(&lfs3, &data, + &bptr) => 0; printf("traversal: %d 0x%x block 0x%x.%x %d\n", bid, tag, @@ -2943,16 +2967,16 @@ code = ''' lfs3_bid_t bid; lfs3_tag_t tag; - lfs3_bptr_t bptr; - int err = lfs3_file_traverse(&lfs3, &file, &bt, - &bid, &tag, &bptr); + lfs3_data_t data; + int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt, + &bid, &tag, &data); assert(!err || err == LFS3_ERR_NOENT); if (err == LFS3_ERR_NOENT) { break; } if (tag == LFS3_TAG_BRANCH) { - lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer; + lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer; printf("traversal: %d 0x%x btree 0x%x.%x\n", bid, tag, @@ -2962,12 +2986,15 @@ code = ''' printf("traversal: %d 0x%x data %d\n", bid, tag, - lfs3_data_size(bptr.data)); + lfs3_data_size(data)); // keep track of how many fragments we've seen fragments += 1; } else if (tag == LFS3_TAG_BLOCK) { + lfs3_bptr_t bptr; + lfs3_data_readbptr(&lfs3, &data, + &bptr) => 0; printf("traversal: %d 0x%x block 0x%x.%x %d\n", bid, tag, @@ -3106,16 +3133,16 @@ code = ''' lfs3_bid_t bid; lfs3_tag_t tag; - lfs3_bptr_t bptr; - int err = lfs3_file_traverse(&lfs3, &file, &bt, - &bid, &tag, &bptr); + lfs3_data_t data; + int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt, + &bid, &tag, &data); assert(!err || err == LFS3_ERR_NOENT); if (err == LFS3_ERR_NOENT) { break; } if (tag == LFS3_TAG_BRANCH) { - lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)bptr.data.u.buffer; + lfs3_rbyd_t *rbyd = (lfs3_rbyd_t*)data.u.buffer; printf("traversal: %d 0x%x btree 0x%x.%x\n", bid, tag, @@ -3125,13 +3152,16 @@ code = ''' printf("traversal: %d 0x%x data %d\n", bid, tag, - lfs3_data_size(bptr.data)); + lfs3_data_size(data)); // if block crystallization is working we shouldn't be // left with any inlined data fragments assert(false); } else if (tag == LFS3_TAG_BLOCK) { + lfs3_bptr_t bptr; + lfs3_data_readbptr(&lfs3, &data, + &bptr) => 0; printf("traversal: %d 0x%x block 0x%x.%x %d\n", bid, tag,