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%)
This commit is contained in:
Christopher Haster
2025-06-27 18:03:13 -05:00
parent d2847f5f0e
commit 10c0a60ced
2 changed files with 151 additions and 183 deletions
+71 -133
View File
@@ -2604,6 +2604,51 @@ static int lfs3_data_readbptr(lfs3_t *lfs3, lfs3_data_t *data,
} }
#endif #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 // check the contents of a bptr
#ifndef LFS3_2BONLY #ifndef LFS3_2BONLY
static int lfs3_bptr_ck(lfs3_t *lfs3, const lfs3_bptr_t *bptr) { 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 #endif
// needed in lfs3_branch_fetch
#ifdef LFS3_CKFETCHES
static inline bool lfs3_m_isckfetches(uint32_t flags);
#endif
#ifndef LFS3_2BONLY #ifndef LFS3_2BONLY
static int lfs3_branch_fetch(lfs3_t *lfs3, lfs3_rbyd_t *branch, static int lfs3_branch_fetch(lfs3_t *lfs3, lfs3_rbyd_t *branch,
lfs3_block_t block, lfs3_size_t trunk, lfs3_bid_t weight, 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; 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 // low-level traversal _only_ finds blocks
static int lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_traversal_t *t, static int lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_traversal_t *t,
lfs3_tag_t *tag_, lfs3_bptr_t *bptr) { 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_BTREE:;
case LFS3_TSTATE_OBTREE:; case LFS3_TSTATE_OBTREE:;
// traverse through our bshrub/btree // traverse through our bshrub/btree
// err = lfs3_bshrub_traverse(lfs3, &t->b, &t->u.bt,
// it probably looks a bit weird to go through NULL, &tag, &data);
// lfs3_file_traverse_, but this gets us bptr decoding
// for free
err = lfs3_file_traverse_(lfs3, &t->b, &t->u.bt,
NULL, &tag, bptr);
if (err) { if (err) {
if (err == LFS3_ERR_NOENT) { if (err == LFS3_ERR_NOENT) {
// clear the bshrub state // clear the bshrub state
@@ -9964,14 +9995,22 @@ static int lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_traversal_t *t,
if (tag_) { if (tag_) {
*tag_ = tag; *tag_ = tag;
} }
bptr->data = data;
return 0; return 0;
// found an indirect block? // 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_) { if (tag_) {
*tag_ = tag; *tag_ = tag;
} }
err = lfs3_data_readbptr(lfs3, &data,
bptr);
if (err) {
return err;
}
return 0; return 0;
#endif
} }
continue; continue;
@@ -11930,24 +11969,12 @@ static int lfs3_file_lookupnext_(lfs3_t *lfs3, const lfs3_file_t *file,
LFS3_ASSERT(tag == LFS3_TAG_DATA LFS3_ASSERT(tag == LFS3_TAG_DATA
|| tag == LFS3_TAG_BLOCK); || tag == LFS3_TAG_BLOCK);
// decode bptrs // fetch the bptr/data fragment
if (tag == LFS3_TAG_DATA) { err = lfs3_bptr_fetch(lfs3, bptr_, tag, weight, data);
bptr_->data = data; if (err) {
} else if (LFS3_IFDEF_2BONLY(false, tag == LFS3_TAG_BLOCK)) { return err;
#ifndef LFS3_2BONLY
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);
if (weight_) { if (weight_) {
*weight_ = weight; *weight_ = weight;
} }
@@ -12072,17 +12099,6 @@ static lfs3_ssize_t lfs3_file_readnext(lfs3_t *lfs3, lfs3_file_t *file,
return err; 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 #ifndef LFS3_KVONLY
file->leaf.pos = bid - (weight-1); file->leaf.pos = bid - (weight-1);
file->leaf.weight = weight; file->leaf.weight = weight;
@@ -12317,17 +12333,6 @@ static int lfs3_file_graft(lfs3_t *lfs3, lfs3_file_t *file,
return err; 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 // note, an entry can be both a left and right sibling
l = bptr_; l = bptr_;
l.data = LFS3_DATA_SLICE(bptr_.data, 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; 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) // is this data a pure hole? stop early to (FUTURE)
// better leverage erased-state in sparse files, and to // better leverage erased-state in sparse files, and to
// try to avoid writing a bunch of unnecessary zeros // try to avoid writing a bunch of unnecessary zeros
@@ -13235,17 +13229,6 @@ fragment:;
return err; 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? // can we coalesce?
if (bid-(weight-1) + lfs3_bptr_size(&bptr) >= fragment_start if (bid-(weight-1) + lfs3_bptr_size(&bptr) >= fragment_start
&& fragment_end - (bid-(weight-1)) && fragment_end - (bid-(weight-1))
@@ -13282,17 +13265,6 @@ fragment:;
return err; 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? // can we coalesce?
if (fragment_end < bid-(weight-1) + lfs3_bptr_size(&bptr) if (fragment_end < bid-(weight-1) + lfs3_bptr_size(&bptr)
&& bid-(weight-1) + lfs3_bptr_size(&bptr) && bid-(weight-1) + lfs3_bptr_size(&bptr)
@@ -14201,47 +14173,6 @@ failed:;
// file check functions // 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) #if !defined(LFS3_KVONLY) && !defined(LFS3_2BONLY)
static int lfs3_file_ck(lfs3_t *lfs3, const lfs3_file_t *file, static int lfs3_file_ck(lfs3_t *lfs3, const lfs3_file_t *file,
uint32_t flags) { uint32_t flags) {
@@ -14260,9 +14191,9 @@ static int lfs3_file_ck(lfs3_t *lfs3, const lfs3_file_t *file,
lfs3_btraversal_init(&bt); lfs3_btraversal_init(&bt);
while (true) { while (true) {
lfs3_tag_t tag; lfs3_tag_t tag;
lfs3_bptr_t bptr; lfs3_data_t data;
int err = lfs3_file_traverse(lfs3, file, &bt, int err = lfs3_bshrub_traverse(lfs3, &file->b, &bt,
NULL, &tag, &bptr); NULL, &tag, &data);
if (err) { if (err) {
if (err == LFS3_ERR_NOENT) { if (err == LFS3_ERR_NOENT) {
break; break;
@@ -14278,7 +14209,7 @@ static int lfs3_file_ck(lfs3_t *lfs3, const lfs3_file_t *file,
if ((lfs3_t_isckmeta(flags) if ((lfs3_t_isckmeta(flags)
|| lfs3_t_isckdata(flags)) || lfs3_t_isckdata(flags))
&& tag == LFS3_TAG_BRANCH) { && 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, err = lfs3_rbyd_fetchck(lfs3, rbyd,
rbyd->blocks[0], rbyd->trunk, rbyd->blocks[0], rbyd->trunk,
rbyd->cksum); rbyd->cksum);
@@ -14290,6 +14221,13 @@ static int lfs3_file_ck(lfs3_t *lfs3, const lfs3_file_t *file,
// validate data blocks? // validate data blocks?
if (lfs3_t_isckdata(flags) if (lfs3_t_isckdata(flags)
&& tag == LFS3_TAG_BLOCK) { && 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); err = lfs3_bptr_ck(lfs3, &bptr);
if (err) { if (err) {
return err; return err;
+80 -50
View File
@@ -191,16 +191,16 @@ code = '''
lfs3_bid_t bid; lfs3_bid_t bid;
lfs3_tag_t tag; lfs3_tag_t tag;
lfs3_bptr_t bptr; lfs3_data_t data;
int err = lfs3_file_traverse(&lfs3, &file, &bt, int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &bptr); &bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT); assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) { if (err == LFS3_ERR_NOENT) {
break; break;
} }
if (tag == LFS3_TAG_BRANCH) { 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", printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid, bid,
tag, tag,
@@ -210,12 +210,15 @@ code = '''
printf("traversal: %d 0x%x data %d\n", printf("traversal: %d 0x%x data %d\n",
bid, bid,
tag, tag,
lfs3_data_size(bptr.data)); lfs3_data_size(data));
// keep track of how many fragments we've seen // keep track of how many fragments we've seen
fragments += 1; fragments += 1;
} else if (tag == LFS3_TAG_BLOCK) { } 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", printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid, bid,
tag, tag,
@@ -331,16 +334,16 @@ code = '''
lfs3_bid_t bid; lfs3_bid_t bid;
lfs3_tag_t tag; lfs3_tag_t tag;
lfs3_bptr_t bptr; lfs3_data_t data;
int err = lfs3_file_traverse(&lfs3, &file, &bt, int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &bptr); &bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT); assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) { if (err == LFS3_ERR_NOENT) {
break; break;
} }
if (tag == LFS3_TAG_BRANCH) { 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", printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid, bid,
tag, tag,
@@ -350,13 +353,16 @@ code = '''
printf("traversal: %d 0x%x data %d\n", printf("traversal: %d 0x%x data %d\n",
bid, bid,
tag, tag,
lfs3_data_size(bptr.data)); lfs3_data_size(data));
// if block crystallization is working we shouldn't be // if block crystallization is working we shouldn't be
// left with any inlined data fragments // left with any inlined data fragments
assert(false); assert(false);
} else if (tag == LFS3_TAG_BLOCK) { } 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", printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid, bid,
tag, tag,
@@ -589,16 +595,16 @@ code = '''
lfs3_bid_t bid; lfs3_bid_t bid;
lfs3_tag_t tag; lfs3_tag_t tag;
lfs3_bptr_t bptr; lfs3_data_t data;
int err = lfs3_file_traverse(&lfs3, &file, &bt, int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &bptr); &bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT); assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) { if (err == LFS3_ERR_NOENT) {
break; break;
} }
if (tag == LFS3_TAG_BRANCH) { 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", printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid, bid,
tag, tag,
@@ -608,12 +614,15 @@ code = '''
printf("traversal: %d 0x%x data %d\n", printf("traversal: %d 0x%x data %d\n",
bid, bid,
tag, tag,
lfs3_data_size(bptr.data)); lfs3_data_size(data));
// keep track of how many fragments we've seen // keep track of how many fragments we've seen
fragments += 1; fragments += 1;
} else if (tag == LFS3_TAG_BLOCK) { } 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", printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid, bid,
tag, tag,
@@ -744,16 +753,16 @@ code = '''
lfs3_bid_t bid; lfs3_bid_t bid;
lfs3_tag_t tag; lfs3_tag_t tag;
lfs3_bptr_t bptr; lfs3_data_t data;
int err = lfs3_file_traverse(&lfs3, &file, &bt, int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &bptr); &bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT); assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) { if (err == LFS3_ERR_NOENT) {
break; break;
} }
if (tag == LFS3_TAG_BRANCH) { 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", printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid, bid,
tag, tag,
@@ -763,13 +772,16 @@ code = '''
printf("traversal: %d 0x%x data %d\n", printf("traversal: %d 0x%x data %d\n",
bid, bid,
tag, tag,
lfs3_data_size(bptr.data)); lfs3_data_size(data));
// if block crystallization is working we shouldn't be // if block crystallization is working we shouldn't be
// left with any inlined data fragments // left with any inlined data fragments
assert(false); assert(false);
} else if (tag == LFS3_TAG_BLOCK) { } 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", printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid, bid,
tag, tag,
@@ -2064,16 +2076,16 @@ code = '''
lfs3_bid_t bid; lfs3_bid_t bid;
lfs3_tag_t tag; lfs3_tag_t tag;
lfs3_bptr_t bptr; lfs3_data_t data;
int err = lfs3_file_traverse(&lfs3, &file, &bt, int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &bptr); &bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT); assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) { if (err == LFS3_ERR_NOENT) {
break; break;
} }
if (tag == LFS3_TAG_BRANCH) { 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", printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid, bid,
tag, tag,
@@ -2083,12 +2095,15 @@ code = '''
printf("traversal: %d 0x%x data %d\n", printf("traversal: %d 0x%x data %d\n",
bid, bid,
tag, tag,
lfs3_data_size(bptr.data)); lfs3_data_size(data));
// keep track of how many fragments we've seen // keep track of how many fragments we've seen
fragments += 1; fragments += 1;
} else if (tag == LFS3_TAG_BLOCK) { } 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", printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid, bid,
tag, tag,
@@ -2208,16 +2223,16 @@ code = '''
lfs3_bid_t bid; lfs3_bid_t bid;
lfs3_tag_t tag; lfs3_tag_t tag;
lfs3_bptr_t bptr; lfs3_data_t data;
int err = lfs3_file_traverse(&lfs3, &file, &bt, int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &bptr); &bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT); assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) { if (err == LFS3_ERR_NOENT) {
break; break;
} }
if (tag == LFS3_TAG_BRANCH) { 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", printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid, bid,
tag, tag,
@@ -2227,12 +2242,15 @@ code = '''
printf("traversal: %d 0x%x data %d\n", printf("traversal: %d 0x%x data %d\n",
bid, bid,
tag, tag,
lfs3_data_size(bptr.data)); lfs3_data_size(data));
// keep track of how many fragments we've seen // keep track of how many fragments we've seen
fragments += 1; fragments += 1;
} else if (tag == LFS3_TAG_BLOCK) { } 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", printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid, bid,
tag, tag,
@@ -2499,16 +2517,16 @@ code = '''
lfs3_bid_t bid; lfs3_bid_t bid;
lfs3_tag_t tag; lfs3_tag_t tag;
lfs3_bptr_t bptr; lfs3_data_t data;
int err = lfs3_file_traverse(&lfs3, &file, &bt, int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &bptr); &bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT); assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) { if (err == LFS3_ERR_NOENT) {
break; break;
} }
if (tag == LFS3_TAG_BRANCH) { 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", printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid, bid,
tag, tag,
@@ -2518,12 +2536,15 @@ code = '''
printf("traversal: %d 0x%x data %d\n", printf("traversal: %d 0x%x data %d\n",
bid, bid,
tag, tag,
lfs3_data_size(bptr.data)); lfs3_data_size(data));
// keep track of how many fragments we've seen // keep track of how many fragments we've seen
fragments += 1; fragments += 1;
} else if (tag == LFS3_TAG_BLOCK) { } 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", printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid, bid,
tag, tag,
@@ -2658,16 +2679,16 @@ code = '''
lfs3_bid_t bid; lfs3_bid_t bid;
lfs3_tag_t tag; lfs3_tag_t tag;
lfs3_bptr_t bptr; lfs3_data_t data;
int err = lfs3_file_traverse(&lfs3, &file, &bt, int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &bptr); &bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT); assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) { if (err == LFS3_ERR_NOENT) {
break; break;
} }
if (tag == LFS3_TAG_BRANCH) { 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", printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid, bid,
tag, tag,
@@ -2677,13 +2698,16 @@ code = '''
printf("traversal: %d 0x%x data %d\n", printf("traversal: %d 0x%x data %d\n",
bid, bid,
tag, tag,
lfs3_data_size(bptr.data)); lfs3_data_size(data));
// if block crystallization is working we shouldn't be // if block crystallization is working we shouldn't be
// left with any inlined data fragments // left with any inlined data fragments
assert(false); assert(false);
} else if (tag == LFS3_TAG_BLOCK) { } 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", printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid, bid,
tag, tag,
@@ -2943,16 +2967,16 @@ code = '''
lfs3_bid_t bid; lfs3_bid_t bid;
lfs3_tag_t tag; lfs3_tag_t tag;
lfs3_bptr_t bptr; lfs3_data_t data;
int err = lfs3_file_traverse(&lfs3, &file, &bt, int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &bptr); &bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT); assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) { if (err == LFS3_ERR_NOENT) {
break; break;
} }
if (tag == LFS3_TAG_BRANCH) { 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", printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid, bid,
tag, tag,
@@ -2962,12 +2986,15 @@ code = '''
printf("traversal: %d 0x%x data %d\n", printf("traversal: %d 0x%x data %d\n",
bid, bid,
tag, tag,
lfs3_data_size(bptr.data)); lfs3_data_size(data));
// keep track of how many fragments we've seen // keep track of how many fragments we've seen
fragments += 1; fragments += 1;
} else if (tag == LFS3_TAG_BLOCK) { } 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", printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid, bid,
tag, tag,
@@ -3106,16 +3133,16 @@ code = '''
lfs3_bid_t bid; lfs3_bid_t bid;
lfs3_tag_t tag; lfs3_tag_t tag;
lfs3_bptr_t bptr; lfs3_data_t data;
int err = lfs3_file_traverse(&lfs3, &file, &bt, int err = lfs3_bshrub_traverse(&lfs3, &file.b, &bt,
&bid, &tag, &bptr); &bid, &tag, &data);
assert(!err || err == LFS3_ERR_NOENT); assert(!err || err == LFS3_ERR_NOENT);
if (err == LFS3_ERR_NOENT) { if (err == LFS3_ERR_NOENT) {
break; break;
} }
if (tag == LFS3_TAG_BRANCH) { 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", printf("traversal: %d 0x%x btree 0x%x.%x\n",
bid, bid,
tag, tag,
@@ -3125,13 +3152,16 @@ code = '''
printf("traversal: %d 0x%x data %d\n", printf("traversal: %d 0x%x data %d\n",
bid, bid,
tag, tag,
lfs3_data_size(bptr.data)); lfs3_data_size(data));
// if block crystallization is working we shouldn't be // if block crystallization is working we shouldn't be
// left with any inlined data fragments // left with any inlined data fragments
assert(false); assert(false);
} else if (tag == LFS3_TAG_BLOCK) { } 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", printf("traversal: %d 0x%x block 0x%x.%x %d\n",
bid, bid,
tag, tag,