t: Tweaked lfsr_btree_traverse so btinfo/mtinfo alias

The traversal logic is a bit simpler if everything can pass around/
populate the same struct, so this reverts some changes made when
implementing lfsr_traversal_t, bringing back bid as a side-channel and
making btinfo/mtinfo typedef aliases.

btinfo/mtinfo are also required arguments for lfsr_btree_traverse/
lfsr_fs_traverse now, so it's even easier to forward these to lower
layers if they alias.

What return-pointers should/shouldn't be optional is still an open
question, but at least for btinfo/mtinfo matching lfs_stat makes sense.

This saves a bit of code/stack:

           code          stack
  before: 34474           2552
  after:  34454 (-0.0%)   2544 (-0.3%)
This commit is contained in:
Christopher Haster
2024-06-15 12:06:24 -05:00
parent 635e1fe8d4
commit ab9b975ac1
2 changed files with 56 additions and 53 deletions
+44 -43
View File
@@ -4961,17 +4961,19 @@ static lfs_scmp_t lfsr_btree_namelookup(lfs_t *lfs, const lfsr_btree_t *btree,
// note this is different from iteration, iteration should use // note this is different from iteration, iteration should use
// lfsr_btree_lookupnext, traversal includes inner btree nodes // lfsr_btree_lookupnext, traversal includes inner btree nodes
#define LFSR_BTRAVERSAL() \ #define LFSR_BTRAVERSAL(_bid) \
((lfsr_btraversal_t){ \ ((lfsr_btraversal_t){ \
.bid=0, \ .bid=_bid, \
.rid=0, \ .rid=0, \
.branch.trunk=0, \ .branch.trunk=0, \
.branch.weight=0}) .branch.weight=0})
typedef struct lfsr_btinfo { typedef struct lfsr_btinfo {
lfsr_bid_t bid;
lfsr_tag_t tag; lfsr_tag_t tag;
union { union {
// ignore the mdir here, things get a bit simpler if we can
// alias mtinfo=btinfo
lfsr_mdir_t mdir;
lfsr_rbyd_t rbyd; lfsr_rbyd_t rbyd;
lfsr_data_t data; lfsr_data_t data;
lfsr_bptr_t bptr; lfsr_bptr_t bptr;
@@ -4979,7 +4981,8 @@ typedef struct lfsr_btinfo {
} lfsr_btinfo_t; } lfsr_btinfo_t;
static int lfsr_btree_traverse_(lfs_t *lfs, const lfsr_btree_t *btree, static int lfsr_btree_traverse_(lfs_t *lfs, const lfsr_btree_t *btree,
lfsr_btraversal_t *bt, lfsr_btinfo_t *btinfo) { lfsr_btraversal_t *bt,
lfsr_bid_t *bid_, lfsr_btinfo_t *btinfo) {
// explicitly traverse the root even if weight=0 // explicitly traverse the root even if weight=0
if (bt->branch.trunk == 0 if (bt->branch.trunk == 0
// unless we don't even have a root yet // unless we don't even have a root yet
@@ -4991,7 +4994,9 @@ static int lfsr_btree_traverse_(lfs_t *lfs, const lfsr_btree_t *btree,
// traverse the root // traverse the root
if (bt->rid == 0) { if (bt->rid == 0) {
btinfo->bid = btree->weight-1; if (bid_) {
*bid_ = btree->weight-1;
}
btinfo->tag = LFSR_TAG_BRANCH; btinfo->tag = LFSR_TAG_BRANCH;
btinfo->u.rbyd = bt->branch; btinfo->u.rbyd = bt->branch;
return 0; return 0;
@@ -5041,7 +5046,9 @@ static int lfsr_btree_traverse_(lfs_t *lfs, const lfsr_btree_t *btree,
// return inner btree nodes if this is the first time we've // return inner btree nodes if this is the first time we've
// seen them // seen them
if (bt->rid == 0) { if (bt->rid == 0) {
btinfo->bid = bt->bid + (rid__ - bt->rid); if (bid_) {
*bid_ = bt->bid + (rid__ - bt->rid);
}
btinfo->tag = LFSR_TAG_BRANCH; btinfo->tag = LFSR_TAG_BRANCH;
btinfo->u.rbyd = bt->branch; btinfo->u.rbyd = bt->branch;
return 0; return 0;
@@ -5057,7 +5064,9 @@ static int lfsr_btree_traverse_(lfs_t *lfs, const lfsr_btree_t *btree,
bt->bid = bid__ + 1; bt->bid = bid__ + 1;
bt->rid = rid__ + 1; bt->rid = rid__ + 1;
btinfo->bid = bid__; if (bid_) {
*bid_ = bid__;
}
btinfo->tag = tag__; btinfo->tag = tag__;
btinfo->u.data = data__; btinfo->u.data = data__;
return 0; return 0;
@@ -5066,8 +5075,9 @@ static int lfsr_btree_traverse_(lfs_t *lfs, const lfsr_btree_t *btree,
} }
static int lfsr_btree_traverse(lfs_t *lfs, const lfsr_btree_t *btree, static int lfsr_btree_traverse(lfs_t *lfs, const lfsr_btree_t *btree,
lfsr_btraversal_t *bt, lfsr_btinfo_t *btinfo) { lfsr_btraversal_t *bt,
return lfsr_btree_traverse_(lfs, btree, bt, btinfo); lfsr_bid_t *bid_, lfsr_btinfo_t *btinfo) {
return lfsr_btree_traverse_(lfs, btree, bt, bid_, btinfo);
} }
@@ -7789,19 +7799,13 @@ static inline bool lfsr_f_isdirty(uint32_t flags) {
} }
typedef struct lfsr_mtinfo { // alias mtinfo=btinfo
lfsr_tag_t tag; typedef lfsr_btinfo_t lfsr_mtinfo_t;
union {
lfsr_mdir_t mdir;
lfsr_rbyd_t rbyd;
lfsr_data_t data;
lfsr_bptr_t bptr;
} u;
} lfsr_mtinfo_t;
// needed in lfsr_fs_traverse_ // needed in lfsr_fs_traverse_
static int lfsr_bshrub_traverse(lfs_t *lfs, const lfsr_file_t *file, static int lfsr_bshrub_traverse(lfs_t *lfs, const lfsr_file_t *file,
lfsr_btraversal_t *bt, lfsr_btinfo_t *btinfo); lfsr_btraversal_t *bt,
lfsr_bid_t *bid_, lfsr_btinfo_t *btinfo);
// low-level traversal _only_ finds blocks // low-level traversal _only_ finds blocks
static int lfsr_fs_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt, static int lfsr_fs_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
@@ -7917,7 +7921,7 @@ static int lfsr_fs_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
// transition to traversing the mtree // transition to traversing the mtree
mt->o.state = LFSR_TSTATE_MTREE; mt->o.state = LFSR_TSTATE_MTREE;
mt->u.mt = LFSR_BTRAVERSAL(); mt->u.mt = LFSR_BTRAVERSAL(0);
mtinfo->tag = LFSR_TAG_BRANCH; mtinfo->tag = LFSR_TAG_BRANCH;
mtinfo->u.rbyd = mtree; mtinfo->u.rbyd = mtree;
@@ -7938,9 +7942,9 @@ static int lfsr_fs_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
} }
// traverse through the mtree // traverse through the mtree
lfsr_btinfo_t btinfo; lfsr_bid_t bid;
err = lfsr_btree_traverse(lfs, &lfs->mtree.u.btree, &mt->u.mt, err = lfsr_btree_traverse(lfs, &lfs->mtree.u.btree, &mt->u.mt,
&btinfo); &bid, mtinfo);
if (err) { if (err) {
// end of mtree? transition to traversing any opened mdirs // end of mtree? transition to traversing any opened mdirs
if (err == LFS_ERR_NOENT) { if (err == LFS_ERR_NOENT) {
@@ -7955,28 +7959,26 @@ static int lfsr_fs_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
// seen it above (this gets a bit weird because 1. mtree may be // seen it above (this gets a bit weird because 1. mtree may be
// uninitialized in mountinited and 2. stack really matters since // uninitialized in mountinited and 2. stack really matters since
// we're at the bottom of lfs_alloc) // we're at the bottom of lfs_alloc)
if (btinfo.tag == LFSR_TAG_BRANCH if (mtinfo->tag == LFSR_TAG_BRANCH
&& btinfo.u.rbyd.blocks[0] && mtinfo->u.rbyd.blocks[0]
== lfs->mtree.u.btree.blocks[0]) { == lfs->mtree.u.btree.blocks[0]) {
continue; continue;
} }
// inner btree nodes already decoded // inner btree nodes already decoded
if (btinfo.tag == LFSR_TAG_BRANCH) { if (mtinfo->tag == LFSR_TAG_BRANCH) {
mtinfo->tag = LFSR_TAG_BRANCH;
mtinfo->u.rbyd = btinfo.u.rbyd;
return 0; return 0;
// fetch mdir if we're on a leaf // fetch mdir if we're on a leaf
} else if (btinfo.tag == LFSR_TAG_MDIR) { } else if (mtinfo->tag == LFSR_TAG_MDIR) {
lfsr_mptr_t mptr; lfsr_mptr_t mptr;
err = lfsr_data_readmptr(lfs, &btinfo.u.data, &mptr); err = lfsr_data_readmptr(lfs, &mtinfo->u.data, &mptr);
if (err) { if (err) {
return err; return err;
} }
err = lfsr_mdir_fetch(lfs, &mt->o.mdir, err = lfsr_mdir_fetch(lfs, &mt->o.mdir,
LFSR_MID(lfs, btinfo.bid, 0), LFSR_MID(lfs, bid, 0),
&mptr); &mptr);
if (err) { if (err) {
return err; return err;
@@ -8042,7 +8044,7 @@ static int lfsr_fs_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
} }
// start traversing // start traversing
mt->bt = LFSR_BTRAVERSAL(); mt->bt = LFSR_BTRAVERSAL(0);
mt->o.state = LFSR_TSTATE_MDIRBTREE; mt->o.state = LFSR_TSTATE_MDIRBTREE;
continue; continue;
@@ -8064,7 +8066,7 @@ static int lfsr_fs_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
const lfsr_file_t *file = (const lfsr_file_t*)mt->u.o; const lfsr_file_t *file = (const lfsr_file_t*)mt->u.o;
mt->o.mdir = file->o.mdir; mt->o.mdir = file->o.mdir;
mt->bshrub = file->bshrub; mt->bshrub = file->bshrub;
mt->bt = LFSR_BTRAVERSAL(); mt->bt = LFSR_BTRAVERSAL(0);
mt->o.state = LFSR_TSTATE_OMDIRBTREE; mt->o.state = LFSR_TSTATE_OMDIRBTREE;
continue; continue;
@@ -8074,7 +8076,7 @@ static int lfsr_fs_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
case LFSR_TSTATE_OMDIRBTREE:; case LFSR_TSTATE_OMDIRBTREE:;
// traverse through our file // traverse through our file
err = lfsr_bshrub_traverse(lfs, (const lfsr_file_t*)mt, &mt->bt, err = lfsr_bshrub_traverse(lfs, (const lfsr_file_t*)mt, &mt->bt,
&btinfo); NULL, mtinfo);
if (err) { if (err) {
if (err == LFS_ERR_NOENT) { if (err == LFS_ERR_NOENT) {
// end of btree? go to next file // end of btree? go to next file
@@ -8094,19 +8096,15 @@ static int lfsr_fs_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
} }
// found an inner btree node? // found an inner btree node?
if (btinfo.tag == LFSR_TAG_BRANCH) { if (mtinfo->tag == LFSR_TAG_BRANCH) {
mtinfo->tag = LFSR_TAG_BRANCH;
mtinfo->u.rbyd = btinfo.u.rbyd;
return 0; return 0;
// found inlined data? ignore this // found inlined data? ignore this
} else if (btinfo.tag == LFSR_TAG_DATA) { } else if (mtinfo->tag == LFSR_TAG_DATA) {
continue; continue;
// found an indirect block? // found an indirect block?
} else if (btinfo.tag == LFSR_TAG_BLOCK) { } else if (mtinfo->tag == LFSR_TAG_BLOCK) {
mtinfo->tag = LFSR_TAG_BLOCK;
mtinfo->u.bptr = btinfo.u.bptr;
return 0; return 0;
} else { } else {
@@ -10769,7 +10767,8 @@ static int lfsr_bshrub_lookupnext(lfs_t *lfs, const lfsr_file_t *file,
} }
static int lfsr_bshrub_traverse(lfs_t *lfs, const lfsr_file_t *file, static int lfsr_bshrub_traverse(lfs_t *lfs, const lfsr_file_t *file,
lfsr_btraversal_t *bt, lfsr_btinfo_t *btinfo) { lfsr_btraversal_t *bt,
lfsr_bid_t *bid_, lfsr_btinfo_t *btinfo) {
// bnull/bsprout do nothing // bnull/bsprout do nothing
if (lfsr_bshrub_isbnull(&file->bshrub) if (lfsr_bshrub_isbnull(&file->bshrub)
|| lfsr_bshrub_isbsprout(&file->o.mdir, &file->bshrub)) { || lfsr_bshrub_isbsprout(&file->o.mdir, &file->bshrub)) {
@@ -10782,7 +10781,9 @@ static int lfsr_bshrub_traverse(lfs_t *lfs, const lfsr_file_t *file,
return LFS_ERR_NOENT; return LFS_ERR_NOENT;
} }
btinfo->bid = lfsr_data_size(file->bshrub.u.bptr.data)-1; if (bid_) {
*bid_ = lfsr_data_size(file->bshrub.u.bptr.data)-1;
}
btinfo->tag = LFSR_TAG_BLOCK; btinfo->tag = LFSR_TAG_BLOCK;
btinfo->u.bptr = file->bshrub.u.bptr; btinfo->u.bptr = file->bshrub.u.bptr;
return 0; return 0;
@@ -10790,7 +10791,7 @@ static int lfsr_bshrub_traverse(lfs_t *lfs, const lfsr_file_t *file,
// bshrub/btree? // bshrub/btree?
} else if (lfsr_bshrub_isbshruborbtree(&file->bshrub)) { } else if (lfsr_bshrub_isbshruborbtree(&file->bshrub)) {
int err = lfsr_btree_traverse_(lfs, &file->bshrub.u.btree, bt, int err = lfsr_btree_traverse_(lfs, &file->bshrub.u.btree, bt,
btinfo); bid_, btinfo);
if (err) { if (err) {
return err; return err;
} }
+12 -10
View File
@@ -4092,13 +4092,14 @@ code = '''
uint8_t *seen = malloc((BLOCK_COUNT+7)/8); uint8_t *seen = malloc((BLOCK_COUNT+7)/8);
memset(seen, 0, (BLOCK_COUNT+7)/8); memset(seen, 0, (BLOCK_COUNT+7)/8);
lfsr_btraversal_t bt = LFSR_BTRAVERSAL(); lfsr_btraversal_t bt = LFSR_BTRAVERSAL(0);
for (lfs_block_t i = 0;; i++) { for (lfs_block_t i = 0;; i++) {
// a bit hacky, but this catches infinite loops // a bit hacky, but this catches infinite loops
assert(i <= 2*N); assert(i <= 2*N);
lfsr_bid_t bid;
lfsr_btinfo_t btinfo; lfsr_btinfo_t btinfo;
int err = lfsr_btree_traverse(&lfs, &btree, &bt, &btinfo); int err = lfsr_btree_traverse(&lfs, &btree, &bt, &bid, &btinfo);
assert(!err || err == LFS_ERR_NOENT); assert(!err || err == LFS_ERR_NOENT);
if (err == LFS_ERR_NOENT) { if (err == LFS_ERR_NOENT) {
break; break;
@@ -4106,7 +4107,7 @@ code = '''
if (btinfo.tag == LFSR_TAG_BRANCH) { if (btinfo.tag == LFSR_TAG_BRANCH) {
printf("traversal: %d 0x%x btree 0x%x.%x\n", printf("traversal: %d 0x%x btree 0x%x.%x\n",
btinfo.bid, bid,
btinfo.tag, btinfo.tag,
btinfo.u.rbyd.blocks[0], btinfo.u.rbyd.trunk); btinfo.u.rbyd.blocks[0], btinfo.u.rbyd.trunk);
@@ -4116,14 +4117,14 @@ code = '''
} else if (btinfo.tag == LFSR_TAG_DATA) { } else if (btinfo.tag == LFSR_TAG_DATA) {
printf("traversal: %d 0x%x data %d\n", printf("traversal: %d 0x%x data %d\n",
btinfo.bid, bid,
btinfo.tag, btinfo.tag,
lfsr_data_size(btinfo.u.data)); lfsr_data_size(btinfo.u.data));
} else { } else {
// well this shouldn't happen // well this shouldn't happen
printf("traversal: %d 0x%x\n", printf("traversal: %d 0x%x\n",
btinfo.bid, bid,
btinfo.tag); btinfo.tag);
assert(false); assert(false);
} }
@@ -4240,13 +4241,14 @@ code = '''
uint8_t *seen = malloc((BLOCK_COUNT+7)/8); uint8_t *seen = malloc((BLOCK_COUNT+7)/8);
memset(seen, 0, (BLOCK_COUNT+7)/8); memset(seen, 0, (BLOCK_COUNT+7)/8);
lfsr_btraversal_t bt = LFSR_BTRAVERSAL(); lfsr_btraversal_t bt = LFSR_BTRAVERSAL(0);
for (lfs_block_t i = 0;; i++) { for (lfs_block_t i = 0;; i++) {
// a bit hacky, but this catches infinite loops // a bit hacky, but this catches infinite loops
assert(i <= 2*N); assert(i <= 2*N);
lfsr_bid_t bid;
lfsr_btinfo_t btinfo; lfsr_btinfo_t btinfo;
int err = lfsr_btree_traverse(&lfs, &btree, &bt, &btinfo); int err = lfsr_btree_traverse(&lfs, &btree, &bt, &bid, &btinfo);
assert(!err || err == LFS_ERR_NOENT); assert(!err || err == LFS_ERR_NOENT);
if (err == LFS_ERR_NOENT) { if (err == LFS_ERR_NOENT) {
break; break;
@@ -4254,7 +4256,7 @@ code = '''
if (btinfo.tag == LFSR_TAG_BRANCH) { if (btinfo.tag == LFSR_TAG_BRANCH) {
printf("traversal: %d 0x%x btree 0x%x.%x\n", printf("traversal: %d 0x%x btree 0x%x.%x\n",
btinfo.bid, bid,
btinfo.tag, btinfo.tag,
btinfo.u.rbyd.blocks[0], btinfo.u.rbyd.trunk); btinfo.u.rbyd.blocks[0], btinfo.u.rbyd.trunk);
@@ -4264,14 +4266,14 @@ code = '''
} else if (btinfo.tag == LFSR_TAG_DATA) { } else if (btinfo.tag == LFSR_TAG_DATA) {
printf("traversal: %d 0x%x data %d\n", printf("traversal: %d 0x%x data %d\n",
btinfo.bid, bid,
btinfo.tag, btinfo.tag,
lfsr_data_size(btinfo.u.data)); lfsr_data_size(btinfo.u.data));
} else { } else {
// well this shouldn't happen // well this shouldn't happen
printf("traversal: %d 0x%x\n", printf("traversal: %d 0x%x\n",
btinfo.bid, bid,
btinfo.tag); btinfo.tag);
assert(false); assert(false);
} }