t: Changed lfsr_mtree_traverse to operate on mdir+mtraversal
Separated out omdir/mdir and mtraversal. You still need to allocate an
mdir for mtraversal to work, but this avoids the extra cost of omdir's
linked-list.
To avoid _too_ many pointers, I duplicated the flags field into both
lfsr_traversal_t and lfsr_mtraversal_t. This is basically free since we
end up with a bunch of padding for mtraversal's state field, but comes
with the risk of getting confused when the two flag fields don't match
in the future.
I also merged the intermediary btype field into flags to avoid yet
another single-byte field, where it fits comfortably in 3-bits.
Note that the mdir can be uninitialized in cases where we don't need to
worry about traversal clobbering.
---
This has the same problems as separating out mdirs/bshrubs in bshrub
functions: more stack/code to move the multiple pointers around, but is
necessary to avoid strict aliasing issues. There's no way to represent
overlapping omdir/mdir/mtraversal struct in standard C99 otherwise.
The end result saves a bit of code, but adds a bit of stack:
code stack
before: 34576 2632
after: 34524 (-0.2%) 2640 (+0.3%)
Though these numbers may be close enough to the compiler noise floor to
not really care about...
This commit is contained in:
@@ -5909,7 +5909,7 @@ static void lfsr_omdir_clobber(lfs_t *lfs, lfsr_omdir_t *o, bool dirty) {
|
|||||||
|
|
||||||
// clobber any traversals referencing our mdir
|
// clobber any traversals referencing our mdir
|
||||||
lfsr_traversal_t *t = (lfsr_traversal_t*)o_;
|
lfsr_traversal_t *t = (lfsr_traversal_t*)o_;
|
||||||
if (t->mt.ot == o) {
|
if (t->mt.o == o) {
|
||||||
lfsr_traversal_clobber(lfs, t, -1);
|
lfsr_traversal_clobber(lfs, t, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8144,18 +8144,26 @@ enum {
|
|||||||
LFSR_MTRAVERSAL_DONE = 8,
|
LFSR_MTRAVERSAL_DONE = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// this mdir should be ignored by mdir commit
|
||||||
|
#define LFSR_MDIR_NULL() \
|
||||||
|
((lfsr_mdir_t){ \
|
||||||
|
.mid=-1, \
|
||||||
|
.rbyd.blocks={-1,-1}})
|
||||||
|
|
||||||
#define LFSR_MTRAVERSAL(_flags) \
|
#define LFSR_MTRAVERSAL(_flags) \
|
||||||
((lfsr_mtraversal_t){ \
|
((lfsr_mtraversal_t){ \
|
||||||
.o.type=LFS_TYPE_TRAVERSAL, \
|
.state=LFSR_MTRAVERSAL_MROOTANCHOR, \
|
||||||
.o.state=LFSR_MTRAVERSAL_MROOTANCHOR, \
|
.flags=_flags, \
|
||||||
.o.flags=_flags, \
|
.o=NULL, \
|
||||||
.o.mdir.mid=-1, \
|
|
||||||
.o.mdir.rbyd.blocks={-1,-1}, \
|
|
||||||
.ot=NULL, \
|
|
||||||
.u.mtortoise.mptr={{0, 0}}, \
|
.u.mtortoise.mptr={{0, 0}}, \
|
||||||
.u.mtortoise.step=0, \
|
.u.mtortoise.step=0, \
|
||||||
.u.mtortoise.power=0})
|
.u.mtortoise.power=0})
|
||||||
|
|
||||||
|
static inline uint8_t lfsr_t_btype(uint32_t flags) {
|
||||||
|
// store btype in flags to avoid needing an extra field
|
||||||
|
return flags & 0x7;
|
||||||
|
}
|
||||||
|
|
||||||
static inline bool lfsr_t_ismtreeonly(uint32_t flags) {
|
static inline bool lfsr_t_ismtreeonly(uint32_t flags) {
|
||||||
return flags & LFS_T_MTREEONLY;
|
return flags & LFS_T_MTREEONLY;
|
||||||
}
|
}
|
||||||
@@ -8188,39 +8196,6 @@ static inline bool lfsr_f_isdirty(uint32_t flags) {
|
|||||||
return flags & LFS_F_DIRTY;
|
return flags & LFS_F_DIRTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void lfsr_mtree_traverserewind(lfs_t *lfs, lfsr_mtraversal_t *mt) {
|
|
||||||
(void)lfs;
|
|
||||||
mt->o.flags &= ~LFS_F_DIRTY;
|
|
||||||
mt->o.state = LFSR_MTRAVERSAL_MROOTANCHOR;
|
|
||||||
mt->o.mdir.mid = -1;
|
|
||||||
mt->o.mdir.rbyd.blocks[0] = -1;
|
|
||||||
mt->o.mdir.rbyd.blocks[1] = -1;
|
|
||||||
mt->ot = NULL;
|
|
||||||
mt->u.mtortoise.mptr.blocks[0] = 0;
|
|
||||||
mt->u.mtortoise.mptr.blocks[1] = 0;
|
|
||||||
mt->u.mtortoise.step = 0;
|
|
||||||
mt->u.mtortoise.power = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void lfsr_mtree_traverseclobber(lfs_t *lfs, lfsr_mtraversal_t *mt,
|
|
||||||
lfsr_smid_t mid) {
|
|
||||||
(void)lfs;
|
|
||||||
if (mid != -1) {
|
|
||||||
// increment the mid (to make progress) and reset to mdir iteration
|
|
||||||
mt->o.state = LFSR_MTRAVERSAL_MDIRS;
|
|
||||||
mt->o.mdir.mid = mid;
|
|
||||||
mt->o.mdir.rbyd.blocks[0] = -1;
|
|
||||||
mt->o.mdir.rbyd.blocks[1] = -1;
|
|
||||||
mt->ot = NULL;
|
|
||||||
} else {
|
|
||||||
// move to next omdir
|
|
||||||
LFS_ASSERT(mt->o.state == LFSR_MTRAVERSAL_OMDIRS
|
|
||||||
|| mt->o.state == LFSR_MTRAVERSAL_OBTREE);
|
|
||||||
mt->o.state = LFSR_MTRAVERSAL_OMDIRS;
|
|
||||||
mt->ot = mt->ot->next;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// alias mtinfo=btinfo
|
// alias mtinfo=btinfo
|
||||||
@@ -8230,27 +8205,28 @@ typedef lfsr_btinfo_t lfsr_mtinfo_t;
|
|||||||
static inline bool lfsr_f_isunsync(uint32_t flags);
|
static inline bool lfsr_f_isunsync(uint32_t flags);
|
||||||
|
|
||||||
// low-level traversal _only_ finds blocks
|
// low-level traversal _only_ finds blocks
|
||||||
static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
|
static int lfsr_mtree_traverse_(lfs_t *lfs,
|
||||||
|
lfsr_mdir_t *mdir, lfsr_mtraversal_t *mt,
|
||||||
lfsr_mtinfo_t *mtinfo) {
|
lfsr_mtinfo_t *mtinfo) {
|
||||||
while (true) {
|
while (true) {
|
||||||
switch (mt->o.state) {
|
switch (mt->state) {
|
||||||
// start with the mrootanchor 0x{0,1}
|
// start with the mrootanchor 0x{0,1}
|
||||||
//
|
//
|
||||||
// note we make sure to include all mroots in our mroot chain!
|
// note we make sure to include all mroots in our mroot chain!
|
||||||
//
|
//
|
||||||
case LFSR_MTRAVERSAL_MROOTANCHOR:;
|
case LFSR_MTRAVERSAL_MROOTANCHOR:;
|
||||||
// fetch the first mroot 0x{0,1}
|
// fetch the first mroot 0x{0,1}
|
||||||
int err = lfsr_mdir_fetch(lfs, &mt->o.mdir,
|
int err = lfsr_mdir_fetch(lfs, mdir,
|
||||||
-1, &LFSR_MPTR_MROOTANCHOR());
|
-1, &LFSR_MPTR_MROOTANCHOR());
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// transition to traversing the mroot chain
|
// transition to traversing the mroot chain
|
||||||
mt->o.state = LFSR_MTRAVERSAL_MROOTCHAIN;
|
mt->state = LFSR_MTRAVERSAL_MROOTCHAIN;
|
||||||
|
|
||||||
mtinfo->tag = LFSR_TAG_MDIR;
|
mtinfo->tag = LFSR_TAG_MDIR;
|
||||||
mtinfo->u.mdir = mt->o.mdir;
|
mtinfo->u.mdir = *mdir;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// traverse the mroot chain, checking for mroot/mtree/mdir
|
// traverse the mroot chain, checking for mroot/mtree/mdir
|
||||||
@@ -8258,15 +8234,14 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
|
|||||||
// lookup mroot, if we find one this is not the active mroot
|
// lookup mroot, if we find one this is not the active mroot
|
||||||
lfsr_tag_t tag;
|
lfsr_tag_t tag;
|
||||||
lfsr_data_t data;
|
lfsr_data_t data;
|
||||||
err = lfsr_mdir_sublookup(lfs, &mt->o.mdir,
|
err = lfsr_mdir_sublookup(lfs, mdir, LFSR_TAG_STRUCT,
|
||||||
LFSR_TAG_STRUCT,
|
|
||||||
&tag, &data);
|
&tag, &data);
|
||||||
if (err) {
|
if (err) {
|
||||||
// if we have no mtree/mdir (inlined mdir), we need to
|
// if we have no mtree/mdir (inlined mdir), we need to
|
||||||
// traverse any files in our mroot next
|
// traverse any files in our mroot next
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
mt->o.mdir.mid = 0;
|
mdir->mid = 0;
|
||||||
mt->o.state = LFSR_MTRAVERSAL_MDIR;
|
mt->state = LFSR_MTRAVERSAL_MDIR;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
@@ -8301,13 +8276,13 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
|
|||||||
mt->u.mtortoise.step += 1;
|
mt->u.mtortoise.step += 1;
|
||||||
|
|
||||||
// fetch this mroot
|
// fetch this mroot
|
||||||
err = lfsr_mdir_fetch(lfs, &mt->o.mdir, -1, &mptr);
|
err = lfsr_mdir_fetch(lfs, mdir, -1, &mptr);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
mtinfo->tag = LFSR_TAG_MDIR;
|
mtinfo->tag = LFSR_TAG_MDIR;
|
||||||
mtinfo->u.mdir = mt->o.mdir;
|
mtinfo->u.mdir = *mdir;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// found an mdir?
|
// found an mdir?
|
||||||
@@ -8319,16 +8294,16 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
err = lfsr_mdir_fetch(lfs, &mt->o.mdir, 0, &mptr);
|
err = lfsr_mdir_fetch(lfs, mdir, 0, &mptr);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// transition to traversing the mdir
|
// transition to traversing the mdir
|
||||||
mt->o.state = LFSR_MTRAVERSAL_MDIR;
|
mt->state = LFSR_MTRAVERSAL_MDIR;
|
||||||
|
|
||||||
mtinfo->tag = LFSR_TAG_MDIR;
|
mtinfo->tag = LFSR_TAG_MDIR;
|
||||||
mtinfo->u.mdir = mt->o.mdir;
|
mtinfo->u.mdir = *mdir;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// found an mtree?
|
// found an mtree?
|
||||||
@@ -8341,7 +8316,7 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
|
|||||||
|
|
||||||
// transition to traversing the mtree
|
// transition to traversing the mtree
|
||||||
mt->u.bt = LFSR_BTRAVERSAL();
|
mt->u.bt = LFSR_BTRAVERSAL();
|
||||||
mt->o.state = LFSR_MTRAVERSAL_MTREE;
|
mt->state = LFSR_MTRAVERSAL_MTREE;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -8352,38 +8327,38 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
|
|||||||
// iterate over mdirs in the mtree
|
// iterate over mdirs in the mtree
|
||||||
case LFSR_MTRAVERSAL_MDIRS:;
|
case LFSR_MTRAVERSAL_MDIRS:;
|
||||||
// find the next mdir
|
// find the next mdir
|
||||||
err = lfsr_mtree_lookup(lfs, mt->o.mdir.mid,
|
err = lfsr_mtree_lookup(lfs, mdir->mid,
|
||||||
&mt->o.mdir);
|
mdir);
|
||||||
if (err) {
|
if (err) {
|
||||||
// end of mtree? guess we're done
|
// end of mtree? guess we're done
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
mt->o.state = LFSR_MTRAVERSAL_DONE;
|
mt->state = LFSR_MTRAVERSAL_DONE;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// transition to traversing the mdir
|
// transition to traversing the mdir
|
||||||
mt->o.state = LFSR_MTRAVERSAL_MDIR;
|
mt->state = LFSR_MTRAVERSAL_MDIR;
|
||||||
|
|
||||||
mtinfo->tag = LFSR_TAG_MDIR;
|
mtinfo->tag = LFSR_TAG_MDIR;
|
||||||
mtinfo->u.mdir = mt->o.mdir;
|
mtinfo->u.mdir = *mdir;
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// scan for blocks/btrees in the current mdir
|
// scan for blocks/btrees in the current mdir
|
||||||
case LFSR_MTRAVERSAL_MDIR:;
|
case LFSR_MTRAVERSAL_MDIR:;
|
||||||
// not traversing all blocks? have we exceeded our mdir's weight?
|
// not traversing all blocks? have we exceeded our mdir's weight?
|
||||||
// return to mtree iteration
|
// return to mtree iteration
|
||||||
if (lfsr_t_ismtreeonly(mt->o.flags)
|
if (lfsr_t_ismtreeonly(mt->flags)
|
||||||
|| lfsr_mid_rid(lfs, mt->o.mdir.mid)
|
|| lfsr_mid_rid(lfs, mdir->mid)
|
||||||
>= (lfsr_srid_t)mt->o.mdir.rbyd.weight) {
|
>= (lfsr_srid_t)mdir->rbyd.weight) {
|
||||||
mt->o.mdir.mid = lfsr_mid_bid(lfs, mt->o.mdir.mid) + 1;
|
mdir->mid = lfsr_mid_bid(lfs, mdir->mid) + 1;
|
||||||
mt->o.state = LFSR_MTRAVERSAL_MDIRS;
|
mt->state = LFSR_MTRAVERSAL_MDIRS;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// do we have a block/btree?
|
// do we have a block/btree?
|
||||||
err = lfsr_mdir_lookupnext(lfs, &mt->o.mdir, LFSR_TAG_DATA,
|
err = lfsr_mdir_lookupnext(lfs, mdir, LFSR_TAG_DATA,
|
||||||
&tag, &data);
|
&tag, &data);
|
||||||
if (err && err != LFS_ERR_NOENT) {
|
if (err && err != LFS_ERR_NOENT) {
|
||||||
return err;
|
return err;
|
||||||
@@ -8398,7 +8373,7 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
|
|||||||
|
|
||||||
// found a bshrub (inlined btree)?
|
// found a bshrub (inlined btree)?
|
||||||
} else if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BSHRUB) {
|
} else if (err != LFS_ERR_NOENT && tag == LFSR_TAG_BSHRUB) {
|
||||||
err = lfsr_data_readshrub(lfs, &data, &mt->o.mdir,
|
err = lfsr_data_readshrub(lfs, &data, mdir,
|
||||||
&mt->bshrub.u.bshrub);
|
&mt->bshrub.u.bshrub);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
@@ -8414,22 +8389,22 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
|
|||||||
|
|
||||||
// no? next we need to check any opened files
|
// no? next we need to check any opened files
|
||||||
} else {
|
} else {
|
||||||
mt->ot = lfs->omdirs;
|
mt->o = lfs->omdirs;
|
||||||
mt->o.state = LFSR_MTRAVERSAL_OMDIRS;
|
mt->state = LFSR_MTRAVERSAL_OMDIRS;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// start traversing
|
// start traversing
|
||||||
mt->u.bt = LFSR_BTRAVERSAL();
|
mt->u.bt = LFSR_BTRAVERSAL();
|
||||||
mt->o.state = LFSR_MTRAVERSAL_BTREE;
|
mt->state = LFSR_MTRAVERSAL_BTREE;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// scan for blocks/btrees in our opened file list
|
// scan for blocks/btrees in our opened file list
|
||||||
case LFSR_MTRAVERSAL_OMDIRS:;
|
case LFSR_MTRAVERSAL_OMDIRS:;
|
||||||
// reached end of opened files? return to mdir traversal
|
// reached end of opened files? return to mdir traversal
|
||||||
if (!mt->ot) {
|
if (!mt->o) {
|
||||||
mt->o.mdir.mid += 1;
|
mdir->mid += 1;
|
||||||
mt->o.state = LFSR_MTRAVERSAL_MDIR;
|
mt->state = LFSR_MTRAVERSAL_MDIR;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -8441,18 +8416,18 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
|
|||||||
// literally every file open, but other things grow O(n^2) with
|
// literally every file open, but other things grow O(n^2) with
|
||||||
// this list anyways
|
// this list anyways
|
||||||
//
|
//
|
||||||
if (mt->ot->mdir.mid != mt->o.mdir.mid
|
if (mt->o->mdir.mid != mdir->mid
|
||||||
|| mt->ot->type != LFS_TYPE_REG
|
|| mt->o->type != LFS_TYPE_REG
|
||||||
|| !lfsr_f_isunsync(mt->ot->flags)) {
|
|| !lfsr_f_isunsync(mt->o->flags)) {
|
||||||
mt->ot = mt->ot->next;
|
mt->o = mt->o->next;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
// start traversing the file
|
// start traversing the file
|
||||||
const lfsr_file_t *file = (const lfsr_file_t*)mt->ot;
|
const lfsr_file_t *file = (const lfsr_file_t*)mt->o;
|
||||||
mt->bshrub = file->bshrub;
|
mt->bshrub = file->bshrub;
|
||||||
mt->u.bt = LFSR_BTRAVERSAL();
|
mt->u.bt = LFSR_BTRAVERSAL();
|
||||||
mt->o.state = LFSR_MTRAVERSAL_OBTREE;
|
mt->state = LFSR_MTRAVERSAL_OBTREE;
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// traverse any btrees we see, this includes the mtree and any file
|
// traverse any btrees we see, this includes the mtree and any file
|
||||||
@@ -8461,25 +8436,24 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_mtraversal_t *mt,
|
|||||||
case LFSR_MTRAVERSAL_BTREE:;
|
case LFSR_MTRAVERSAL_BTREE:;
|
||||||
case LFSR_MTRAVERSAL_OBTREE:;
|
case LFSR_MTRAVERSAL_OBTREE:;
|
||||||
// traverse through our file
|
// traverse through our file
|
||||||
err = lfsr_bshrub_traverse(lfs, &mt->o.mdir, &mt->bshrub,
|
err = lfsr_bshrub_traverse(lfs, mdir, &mt->bshrub, &mt->u.bt,
|
||||||
&mt->u.bt,
|
|
||||||
NULL, mtinfo);
|
NULL, mtinfo);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
// end of mtree? start iterating over mdirs
|
// end of mtree? start iterating over mdirs
|
||||||
if (mt->o.state == LFSR_MTRAVERSAL_MTREE) {
|
if (mt->state == LFSR_MTRAVERSAL_MTREE) {
|
||||||
mt->o.mdir.mid = 0;
|
mdir->mid = 0;
|
||||||
mt->o.state = LFSR_MTRAVERSAL_MDIRS;
|
mt->state = LFSR_MTRAVERSAL_MDIRS;
|
||||||
continue;
|
continue;
|
||||||
// end of mdir btree? start iterating over opened files
|
// end of mdir btree? start iterating over opened files
|
||||||
} else if (mt->o.state == LFSR_MTRAVERSAL_BTREE) {
|
} else if (mt->state == LFSR_MTRAVERSAL_BTREE) {
|
||||||
mt->ot = lfs->omdirs;
|
mt->o = lfs->omdirs;
|
||||||
mt->o.state = LFSR_MTRAVERSAL_OMDIRS;
|
mt->state = LFSR_MTRAVERSAL_OMDIRS;
|
||||||
continue;
|
continue;
|
||||||
// end of opened btree? go to next opened file
|
// end of opened btree? go to next opened file
|
||||||
} else if (mt->o.state == LFSR_MTRAVERSAL_OBTREE) {
|
} else if (mt->state == LFSR_MTRAVERSAL_OBTREE) {
|
||||||
mt->ot = mt->ot->next;
|
mt->o = mt->o->next;
|
||||||
mt->o.state = LFSR_MTRAVERSAL_OMDIRS;
|
mt->state = LFSR_MTRAVERSAL_OMDIRS;
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
LFS_UNREACHABLE();
|
LFS_UNREACHABLE();
|
||||||
@@ -8514,15 +8488,16 @@ static void lfs_alloc_markinuse(lfs_t *lfs, lfs_block_t block);
|
|||||||
// high-level immutable traversal, handle extra features here,
|
// high-level immutable traversal, handle extra features here,
|
||||||
// but no mutation! (we're called in lfs_alloc, so things would end up
|
// but no mutation! (we're called in lfs_alloc, so things would end up
|
||||||
// recursive)
|
// recursive)
|
||||||
static int lfsr_mtree_traverse(lfs_t *lfs, lfsr_mtraversal_t *mt,
|
static int lfsr_mtree_traverse(lfs_t *lfs,
|
||||||
|
lfsr_mdir_t *mdir, lfsr_mtraversal_t *mt,
|
||||||
lfsr_mtinfo_t *mtinfo) {
|
lfsr_mtinfo_t *mtinfo) {
|
||||||
int err = lfsr_mtree_traverse_(lfs, mt, mtinfo);
|
int err = lfsr_mtree_traverse_(lfs, mdir, mt, mtinfo);
|
||||||
if (err) {
|
if (err) {
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
// validate btree nodes? note mdirs are already validated
|
// validate btree nodes? note mdirs are already validated
|
||||||
if (lfsr_t_isckmeta(mt->o.flags)
|
if (lfsr_t_isckmeta(mt->flags)
|
||||||
&& mtinfo->tag == LFSR_TAG_BRANCH) {
|
&& mtinfo->tag == LFSR_TAG_BRANCH) {
|
||||||
err = lfsr_rbyd_fetchck(lfs, &mtinfo->u.rbyd,
|
err = lfsr_rbyd_fetchck(lfs, &mtinfo->u.rbyd,
|
||||||
mtinfo->u.rbyd.blocks[0], mtinfo->u.rbyd.trunk,
|
mtinfo->u.rbyd.blocks[0], mtinfo->u.rbyd.trunk,
|
||||||
@@ -8533,7 +8508,7 @@ static int lfsr_mtree_traverse(lfs_t *lfs, lfsr_mtraversal_t *mt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// validate data blocks?
|
// validate data blocks?
|
||||||
if (lfsr_t_isckdata(mt->o.flags)
|
if (lfsr_t_isckdata(mt->flags)
|
||||||
&& mtinfo->tag == LFSR_TAG_BLOCK) {
|
&& mtinfo->tag == LFSR_TAG_BLOCK) {
|
||||||
err = lfsr_bptr_ck(lfs, &mtinfo->u.bptr);
|
err = lfsr_bptr_ck(lfs, &mtinfo->u.bptr);
|
||||||
if (err) {
|
if (err) {
|
||||||
@@ -8542,7 +8517,7 @@ static int lfsr_mtree_traverse(lfs_t *lfs, lfsr_mtraversal_t *mt,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// track in-use blocks
|
// track in-use blocks
|
||||||
if (lfsr_t_islookahead(mt->o.flags)) {
|
if (lfsr_t_islookahead(mt->flags)) {
|
||||||
if (mtinfo->tag == LFSR_TAG_MDIR) {
|
if (mtinfo->tag == LFSR_TAG_MDIR) {
|
||||||
lfs_alloc_markinuse(lfs, mtinfo->u.mdir.rbyd.blocks[0]);
|
lfs_alloc_markinuse(lfs, mtinfo->u.mdir.rbyd.blocks[0]);
|
||||||
lfs_alloc_markinuse(lfs, mtinfo->u.mdir.rbyd.blocks[1]);
|
lfs_alloc_markinuse(lfs, mtinfo->u.mdir.rbyd.blocks[1]);
|
||||||
@@ -8563,10 +8538,11 @@ static int lfsr_mtree_traverse(lfs_t *lfs, lfsr_mtraversal_t *mt,
|
|||||||
|
|
||||||
// high-level mutating traversal, handle extra features that require
|
// high-level mutating traversal, handle extra features that require
|
||||||
// mutation here, upper layers should call lfs_alloc_ckpoint as needed
|
// mutation here, upper layers should call lfs_alloc_ckpoint as needed
|
||||||
static int lfsr_mtree_traversemut(lfs_t *lfs, lfsr_mtraversal_t *mt,
|
static int lfsr_mtree_traversemut(lfs_t *lfs,
|
||||||
|
lfsr_mdir_t *mdir, lfsr_mtraversal_t *mt,
|
||||||
lfsr_mtinfo_t *mtinfo) {
|
lfsr_mtinfo_t *mtinfo) {
|
||||||
// TODO
|
// TODO
|
||||||
return lfsr_mtree_traverse(lfs, mt, mtinfo);
|
return lfsr_mtree_traverse(lfs, mdir, mt, mtinfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -8712,10 +8688,11 @@ static lfs_sblock_t lfs_alloc(lfs_t *lfs, bool erase) {
|
|||||||
|
|
||||||
// traverse the filesystem, building up knowledge of what blocks are
|
// traverse the filesystem, building up knowledge of what blocks are
|
||||||
// in use in our lookahead window
|
// in use in our lookahead window
|
||||||
|
lfsr_mdir_t mdir;
|
||||||
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(LFS_T_LOOKAHEAD);
|
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(LFS_T_LOOKAHEAD);
|
||||||
while (true) {
|
while (true) {
|
||||||
lfsr_mtinfo_t mtinfo;
|
lfsr_mtinfo_t mtinfo;
|
||||||
int err = lfsr_mtree_traverse(lfs, &mt, &mtinfo);
|
int err = lfsr_mtree_traverse(lfs, &mdir, &mt, &mtinfo);
|
||||||
if (err) {
|
if (err) {
|
||||||
LFS_ASSERT(err != LFS_ERR_BUSY);
|
LFS_ASSERT(err != LFS_ERR_BUSY);
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
@@ -12063,11 +12040,12 @@ static int lfsr_mountinited(lfs_t *lfs) {
|
|||||||
// we do validate btree inner nodes here, how can we trust our
|
// we do validate btree inner nodes here, how can we trust our
|
||||||
// mdirs are valid if we haven't checked the btree inner nodes at
|
// mdirs are valid if we haven't checked the btree inner nodes at
|
||||||
// least once?
|
// least once?
|
||||||
|
lfsr_mdir_t mdir;
|
||||||
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
|
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
|
||||||
LFS_T_MTREEONLY | LFS_T_CKMETA);
|
LFS_T_MTREEONLY | LFS_T_CKMETA);
|
||||||
while (true) {
|
while (true) {
|
||||||
lfsr_mtinfo_t mtinfo;
|
lfsr_mtinfo_t mtinfo;
|
||||||
int err = lfsr_mtree_traverse(lfs, &mt, &mtinfo);
|
int err = lfsr_mtree_traverse(lfs, &mdir, &mt, &mtinfo);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
break;
|
break;
|
||||||
@@ -12373,10 +12351,11 @@ int lfsr_fs_stat(lfs_t *lfs, struct lfs_fsinfo *fsinfo) {
|
|||||||
|
|
||||||
lfs_ssize_t lfsr_fs_size(lfs_t *lfs) {
|
lfs_ssize_t lfsr_fs_size(lfs_t *lfs) {
|
||||||
lfs_size_t count = 0;
|
lfs_size_t count = 0;
|
||||||
|
lfsr_mdir_t mdir;
|
||||||
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(0);
|
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(0);
|
||||||
while (true) {
|
while (true) {
|
||||||
lfsr_mtinfo_t mtinfo;
|
lfsr_mtinfo_t mtinfo;
|
||||||
int err = lfsr_mtree_traverse(lfs, &mt, &mtinfo);
|
int err = lfsr_mtree_traverse(lfs, &mdir, &mt, &mtinfo);
|
||||||
if (err) {
|
if (err) {
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
break;
|
break;
|
||||||
@@ -12589,22 +12568,12 @@ failed:;
|
|||||||
|
|
||||||
/// High-level filesystem traversal ///
|
/// High-level filesystem traversal ///
|
||||||
|
|
||||||
static void lfsr_traversal_clobber(lfs_t *lfs, lfsr_traversal_t *t,
|
|
||||||
lfsr_smid_t mid) {
|
|
||||||
// clobber low-level traversal
|
|
||||||
lfsr_mtree_traverseclobber(lfs, &t->mt, mid);
|
|
||||||
|
|
||||||
// and clear any pending blocks
|
|
||||||
t->blocks[0] = -1;
|
|
||||||
t->blocks[1] = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// needed in lfsr_traversal_open
|
// needed in lfsr_traversal_open
|
||||||
static int lfsr_traversal_rewind_(lfs_t *lfs, lfsr_traversal_t *t);
|
static int lfsr_traversal_rewind_(lfs_t *lfs, lfsr_traversal_t *t);
|
||||||
|
|
||||||
int lfsr_traversal_open(lfs_t *lfs, lfsr_traversal_t *t, uint32_t flags) {
|
int lfsr_traversal_open(lfs_t *lfs, lfsr_traversal_t *t, uint32_t flags) {
|
||||||
// already open?
|
// already open?
|
||||||
LFS_ASSERT(!lfsr_omdir_isopen(lfs, &t->mt.o));
|
LFS_ASSERT(!lfsr_omdir_isopen(lfs, &t->o));
|
||||||
// some flags don't make sense when only traversing the mtree
|
// some flags don't make sense when only traversing the mtree
|
||||||
LFS_ASSERT(!lfsr_t_ismtreeonly(flags) || !lfsr_t_islookahead(flags));
|
LFS_ASSERT(!lfsr_t_ismtreeonly(flags) || !lfsr_t_islookahead(flags));
|
||||||
LFS_ASSERT(!lfsr_t_ismtreeonly(flags) || !lfsr_t_isckdata(flags));
|
LFS_ASSERT(!lfsr_t_ismtreeonly(flags) || !lfsr_t_isckdata(flags));
|
||||||
@@ -12622,8 +12591,8 @@ int lfsr_traversal_open(lfs_t *lfs, lfsr_traversal_t *t, uint32_t flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// setup traversal state
|
// setup traversal state
|
||||||
t->mt.o.type = LFS_TYPE_TRAVERSAL;
|
t->o.type = LFS_TYPE_TRAVERSAL;
|
||||||
t->mt.o.flags = flags;
|
t->o.flags = flags;
|
||||||
|
|
||||||
// let rewind initialize/reset things
|
// let rewind initialize/reset things
|
||||||
int err = lfsr_traversal_rewind_(lfs, t);
|
int err = lfsr_traversal_rewind_(lfs, t);
|
||||||
@@ -12632,25 +12601,25 @@ int lfsr_traversal_open(lfs_t *lfs, lfsr_traversal_t *t, uint32_t flags) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add to tracked mdirs
|
// add to tracked mdirs
|
||||||
lfsr_omdir_open(lfs, &t->mt.o);
|
lfsr_omdir_open(lfs, &t->o);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lfsr_traversal_close(lfs_t *lfs, lfsr_traversal_t *t) {
|
int lfsr_traversal_close(lfs_t *lfs, lfsr_traversal_t *t) {
|
||||||
LFS_ASSERT(lfsr_omdir_isopen(lfs, &t->mt.o));
|
LFS_ASSERT(lfsr_omdir_isopen(lfs, &t->o));
|
||||||
|
|
||||||
// remove from tracked mdirs
|
// remove from tracked mdirs
|
||||||
lfsr_omdir_close(lfs, &t->mt.o);
|
lfsr_omdir_close(lfs, &t->o);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *t,
|
int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *t,
|
||||||
struct lfs_tinfo *tinfo) {
|
struct lfs_tinfo *tinfo) {
|
||||||
LFS_ASSERT(lfsr_omdir_isopen(lfs, &t->mt.o));
|
LFS_ASSERT(lfsr_omdir_isopen(lfs, &t->o));
|
||||||
|
|
||||||
// traversal dirty and excl? terminate early
|
// traversal dirty and excl? terminate early
|
||||||
if (lfsr_t_isexcl(t->mt.o.flags)
|
if (lfsr_t_isexcl(t->o.flags)
|
||||||
&& lfsr_f_isdirty(t->mt.o.flags)) {
|
&& lfsr_f_isdirty(t->o.flags)) {
|
||||||
return LFS_ERR_BUSY;
|
return LFS_ERR_BUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12658,7 +12627,7 @@ int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *t,
|
|||||||
// some redund blocks left over?
|
// some redund blocks left over?
|
||||||
if (t->blocks[0] != -1) {
|
if (t->blocks[0] != -1) {
|
||||||
// write our traversal info
|
// write our traversal info
|
||||||
tinfo->btype = t->btype;
|
tinfo->btype = lfsr_t_btype(t->o.flags);
|
||||||
tinfo->block = t->blocks[0];
|
tinfo->block = t->blocks[0];
|
||||||
|
|
||||||
t->blocks[0] = t->blocks[1];
|
t->blocks[0] = t->blocks[1];
|
||||||
@@ -12668,7 +12637,7 @@ int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *t,
|
|||||||
|
|
||||||
// find next block
|
// find next block
|
||||||
lfsr_mtinfo_t mtinfo;
|
lfsr_mtinfo_t mtinfo;
|
||||||
int err = lfsr_mtree_traversemut(lfs, &t->mt, &mtinfo);
|
int err = lfsr_mtree_traversemut(lfs, &t->o.mdir, &t->mt, &mtinfo);
|
||||||
if (err) {
|
if (err) {
|
||||||
// end of traversal?
|
// end of traversal?
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
@@ -12679,17 +12648,17 @@ int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *t,
|
|||||||
|
|
||||||
// figure out type/blocks
|
// figure out type/blocks
|
||||||
if (mtinfo.tag == LFSR_TAG_MDIR) {
|
if (mtinfo.tag == LFSR_TAG_MDIR) {
|
||||||
t->btype = LFS_BTYPE_MDIR;
|
t->o.flags = (t->o.flags & ~0x7) | LFS_BTYPE_MDIR;
|
||||||
t->blocks[0] = mtinfo.u.mdir.rbyd.blocks[0];
|
t->blocks[0] = mtinfo.u.mdir.rbyd.blocks[0];
|
||||||
t->blocks[1] = mtinfo.u.mdir.rbyd.blocks[1];
|
t->blocks[1] = mtinfo.u.mdir.rbyd.blocks[1];
|
||||||
|
|
||||||
} else if (mtinfo.tag == LFSR_TAG_BRANCH) {
|
} else if (mtinfo.tag == LFSR_TAG_BRANCH) {
|
||||||
t->btype = LFS_BTYPE_BTREE;
|
t->o.flags = (t->o.flags & ~0x7) | LFS_BTYPE_BTREE;
|
||||||
t->blocks[0] = mtinfo.u.rbyd.blocks[0];
|
t->blocks[0] = mtinfo.u.rbyd.blocks[0];
|
||||||
t->blocks[1] = -1;
|
t->blocks[1] = -1;
|
||||||
|
|
||||||
} else if (mtinfo.tag == LFSR_TAG_BLOCK) {
|
} else if (mtinfo.tag == LFSR_TAG_BLOCK) {
|
||||||
t->btype = LFS_BTYPE_DATA;
|
t->o.flags = (t->o.flags & ~0x7) | LFS_BTYPE_DATA;
|
||||||
t->blocks[0] = mtinfo.u.bptr.data.u.disk.block;
|
t->blocks[0] = mtinfo.u.bptr.data.u.disk.block;
|
||||||
t->blocks[1] = -1;
|
t->blocks[1] = -1;
|
||||||
|
|
||||||
@@ -12700,22 +12669,52 @@ int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *t,
|
|||||||
|
|
||||||
done:;
|
done:;
|
||||||
// was a lookahead scan successful?
|
// was a lookahead scan successful?
|
||||||
if (lfsr_t_islookahead(t->mt.o.flags)
|
if (lfsr_t_islookahead(t->o.flags)
|
||||||
&& !lfsr_f_isdirty(t->mt.o.flags)) {
|
&& !lfsr_f_isdirty(t->o.flags)) {
|
||||||
lfs_alloc_markfree(lfs);
|
lfs_alloc_markfree(lfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return LFS_ERR_NOENT;
|
return LFS_ERR_NOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lfsr_traversal_clobber(lfs_t *lfs, lfsr_traversal_t *t,
|
||||||
|
lfsr_smid_t mid) {
|
||||||
|
(void)lfs;
|
||||||
|
// clobber low-level traversal
|
||||||
|
if (mid != -1) {
|
||||||
|
// increment the mid (to make progress) and reset to mdir iteration
|
||||||
|
t->mt.state = LFSR_MTRAVERSAL_MDIRS;
|
||||||
|
t->o.mdir.mid = mid;
|
||||||
|
t->o.mdir.rbyd.blocks[0] = -1;
|
||||||
|
t->o.mdir.rbyd.blocks[1] = -1;
|
||||||
|
t->mt.o = NULL;
|
||||||
|
} else {
|
||||||
|
// move to next omdir
|
||||||
|
LFS_ASSERT(t->mt.state == LFSR_MTRAVERSAL_OMDIRS
|
||||||
|
|| t->mt.state == LFSR_MTRAVERSAL_OBTREE);
|
||||||
|
t->mt.state = LFSR_MTRAVERSAL_OMDIRS;
|
||||||
|
t->mt.o = t->mt.o->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
// and clear any pending blocks
|
||||||
|
t->blocks[0] = -1;
|
||||||
|
t->blocks[1] = -1;
|
||||||
|
}
|
||||||
|
|
||||||
static int lfsr_traversal_rewind_(lfs_t *lfs, lfsr_traversal_t *t) {
|
static int lfsr_traversal_rewind_(lfs_t *lfs, lfsr_traversal_t *t) {
|
||||||
// reset traversal state
|
(void)lfs;
|
||||||
lfsr_mtree_traverserewind(lfs, &t->mt);
|
// clear sticky flags
|
||||||
|
t->o.flags &= ~LFS_F_DIRTY;
|
||||||
|
// reset traversal
|
||||||
|
t->o.mdir = LFSR_MDIR_NULL();
|
||||||
|
t->mt = LFSR_MTRAVERSAL(t->o.flags);
|
||||||
|
|
||||||
|
// and clear any pending blocks
|
||||||
t->blocks[0] = -1;
|
t->blocks[0] = -1;
|
||||||
t->blocks[1] = -1;
|
t->blocks[1] = -1;
|
||||||
|
|
||||||
// shift the lookahead buffer if requested
|
// shift the lookahead buffer if requested
|
||||||
if (lfsr_t_islookahead(t->mt.o.flags)) {
|
if (lfsr_t_islookahead(t->o.flags)) {
|
||||||
lfs_alloc_shift(lfs);
|
lfs_alloc_shift(lfs);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12723,7 +12722,7 @@ static int lfsr_traversal_rewind_(lfs_t *lfs, lfsr_traversal_t *t) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
int lfsr_traversal_rewind(lfs_t *lfs, lfsr_traversal_t *t) {
|
int lfsr_traversal_rewind(lfs_t *lfs, lfsr_traversal_t *t) {
|
||||||
LFS_ASSERT(lfsr_omdir_isopen(lfs, &t->mt.o));
|
LFS_ASSERT(lfsr_omdir_isopen(lfs, &t->o));
|
||||||
|
|
||||||
return lfsr_traversal_rewind_(lfs, t);
|
return lfsr_traversal_rewind_(lfs, t);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -474,7 +474,6 @@ typedef struct lfsr_mdir {
|
|||||||
typedef struct lfsr_omdir {
|
typedef struct lfsr_omdir {
|
||||||
struct lfsr_omdir *next;
|
struct lfsr_omdir *next;
|
||||||
uint8_t type;
|
uint8_t type;
|
||||||
uint8_t state;
|
|
||||||
uint16_t flags;
|
uint16_t flags;
|
||||||
lfsr_mdir_t mdir;
|
lfsr_mdir_t mdir;
|
||||||
} lfsr_omdir_t;
|
} lfsr_omdir_t;
|
||||||
@@ -603,10 +602,11 @@ typedef struct lfsr_btraversal {
|
|||||||
} lfsr_btraversal_t;
|
} lfsr_btraversal_t;
|
||||||
|
|
||||||
typedef struct lfsr_mtraversal {
|
typedef struct lfsr_mtraversal {
|
||||||
// core state machine in o.state
|
// core state machine
|
||||||
lfsr_omdir_t o;
|
uint8_t state;
|
||||||
|
uint16_t flags;
|
||||||
// opened file state
|
// opened file state
|
||||||
lfsr_omdir_t *ot;
|
lfsr_omdir_t *o;
|
||||||
// bshrub/btree state
|
// bshrub/btree state
|
||||||
lfsr_bshrub_t bshrub;
|
lfsr_bshrub_t bshrub;
|
||||||
union {
|
union {
|
||||||
@@ -622,9 +622,8 @@ typedef struct lfsr_mtraversal {
|
|||||||
} lfsr_mtraversal_t;
|
} lfsr_mtraversal_t;
|
||||||
|
|
||||||
typedef struct lfsr_traversal {
|
typedef struct lfsr_traversal {
|
||||||
// lfsr_mtraversal_t contains most of what we need
|
lfsr_omdir_t o;
|
||||||
lfsr_mtraversal_t mt;
|
lfsr_mtraversal_t mt;
|
||||||
uint8_t btype;
|
|
||||||
lfs_sblock_t blocks[2];
|
lfs_sblock_t blocks[2];
|
||||||
} lfsr_traversal_t;
|
} lfsr_traversal_t;
|
||||||
|
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ 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_mdir_t mdir;
|
||||||
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
|
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
|
||||||
(CKMETA) ? LFS_T_CKMETA : 0);
|
(CKMETA) ? LFS_T_CKMETA : 0);
|
||||||
for (lfs_block_t i = 0;; i++) {
|
for (lfs_block_t i = 0;; i++) {
|
||||||
@@ -170,7 +171,7 @@ code = '''
|
|||||||
assert(i < 2*BLOCK_COUNT);
|
assert(i < 2*BLOCK_COUNT);
|
||||||
|
|
||||||
lfsr_mtinfo_t mtinfo;
|
lfsr_mtinfo_t mtinfo;
|
||||||
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
|
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
|
||||||
assert(!err || err == LFS_ERR_NOENT);
|
assert(!err || err == LFS_ERR_NOENT);
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
break;
|
break;
|
||||||
@@ -331,6 +332,7 @@ 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_mdir_t mdir;
|
||||||
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
|
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
|
||||||
((CKMETA) ? LFS_T_CKMETA : 0));
|
((CKMETA) ? LFS_T_CKMETA : 0));
|
||||||
for (lfs_block_t i = 0;; i++) {
|
for (lfs_block_t i = 0;; i++) {
|
||||||
@@ -338,7 +340,7 @@ code = '''
|
|||||||
assert(i < 2*BLOCK_COUNT);
|
assert(i < 2*BLOCK_COUNT);
|
||||||
|
|
||||||
lfsr_mtinfo_t mtinfo;
|
lfsr_mtinfo_t mtinfo;
|
||||||
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
|
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
|
||||||
assert(!err || err == LFS_ERR_NOENT);
|
assert(!err || err == LFS_ERR_NOENT);
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
break;
|
break;
|
||||||
@@ -485,6 +487,7 @@ 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_mdir_t mdir;
|
||||||
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
|
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
|
||||||
((CKMETA) ? LFS_T_CKMETA : 0));
|
((CKMETA) ? LFS_T_CKMETA : 0));
|
||||||
for (lfs_block_t i = 0;; i++) {
|
for (lfs_block_t i = 0;; i++) {
|
||||||
@@ -492,7 +495,7 @@ code = '''
|
|||||||
assert(i < 2*BLOCK_COUNT);
|
assert(i < 2*BLOCK_COUNT);
|
||||||
|
|
||||||
lfsr_mtinfo_t mtinfo;
|
lfsr_mtinfo_t mtinfo;
|
||||||
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
|
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
|
||||||
assert(!err || err == LFS_ERR_NOENT);
|
assert(!err || err == LFS_ERR_NOENT);
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
+11
-10
@@ -3370,7 +3370,7 @@ code = '''
|
|||||||
assert(i < 2*BLOCK_COUNT);
|
assert(i < 2*BLOCK_COUNT);
|
||||||
|
|
||||||
lfsr_mtinfo_t mtinfo;
|
lfsr_mtinfo_t mtinfo;
|
||||||
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
|
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
|
||||||
assert(!err || err == LFS_ERR_NOENT);
|
assert(!err || err == LFS_ERR_NOENT);
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
break;
|
break;
|
||||||
@@ -3485,7 +3485,7 @@ code = '''
|
|||||||
assert(i < 2*BLOCK_COUNT);
|
assert(i < 2*BLOCK_COUNT);
|
||||||
|
|
||||||
lfsr_mtinfo_t mtinfo;
|
lfsr_mtinfo_t mtinfo;
|
||||||
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
|
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
|
||||||
assert(!err || err == LFS_ERR_NOENT);
|
assert(!err || err == LFS_ERR_NOENT);
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
break;
|
break;
|
||||||
@@ -3622,7 +3622,7 @@ code = '''
|
|||||||
assert(i < 2*BLOCK_COUNT);
|
assert(i < 2*BLOCK_COUNT);
|
||||||
|
|
||||||
lfsr_mtinfo_t mtinfo;
|
lfsr_mtinfo_t mtinfo;
|
||||||
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
|
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
|
||||||
assert(!err || err == LFS_ERR_NOENT);
|
assert(!err || err == LFS_ERR_NOENT);
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
break;
|
break;
|
||||||
@@ -3780,7 +3780,7 @@ code = '''
|
|||||||
assert(i < 2*BLOCK_COUNT);
|
assert(i < 2*BLOCK_COUNT);
|
||||||
|
|
||||||
lfsr_mtinfo_t mtinfo;
|
lfsr_mtinfo_t mtinfo;
|
||||||
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
|
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
|
||||||
assert(!err || err == LFS_ERR_NOENT);
|
assert(!err || err == LFS_ERR_NOENT);
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
break;
|
break;
|
||||||
@@ -3922,7 +3922,7 @@ code = '''
|
|||||||
assert(i < 2*BLOCK_COUNT);
|
assert(i < 2*BLOCK_COUNT);
|
||||||
|
|
||||||
lfsr_mtinfo_t mtinfo;
|
lfsr_mtinfo_t mtinfo;
|
||||||
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
|
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
|
||||||
assert(!err || err == LFS_ERR_NOENT);
|
assert(!err || err == LFS_ERR_NOENT);
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
break;
|
break;
|
||||||
@@ -4031,6 +4031,7 @@ 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_mdir_t mdir;
|
||||||
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
|
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
|
||||||
LFS_T_MTREEONLY
|
LFS_T_MTREEONLY
|
||||||
| ((CKMETA) ? LFS_T_CKMETA : 0));
|
| ((CKMETA) ? LFS_T_CKMETA : 0));
|
||||||
@@ -4039,7 +4040,7 @@ code = '''
|
|||||||
assert(i < 2*BLOCK_COUNT);
|
assert(i < 2*BLOCK_COUNT);
|
||||||
|
|
||||||
lfsr_mtinfo_t mtinfo;
|
lfsr_mtinfo_t mtinfo;
|
||||||
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
|
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
|
||||||
assert(!err || err == LFS_ERR_NOENT);
|
assert(!err || err == LFS_ERR_NOENT);
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
break;
|
break;
|
||||||
@@ -4087,7 +4088,6 @@ code = '''
|
|||||||
// and the tree should still work
|
// and the tree should still work
|
||||||
|
|
||||||
// try looking up each entry
|
// try looking up each entry
|
||||||
lfsr_mdir_t mdir;
|
|
||||||
lfsr_mtree_lookup(&lfs, 0, &mdir) => 0;
|
lfsr_mtree_lookup(&lfs, 0, &mdir) => 0;
|
||||||
lfsr_data_t data;
|
lfsr_data_t data;
|
||||||
uint8_t buffer[256];
|
uint8_t buffer[256];
|
||||||
@@ -4190,6 +4190,7 @@ 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_mdir_t mdir;
|
||||||
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
|
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
|
||||||
LFS_T_MTREEONLY
|
LFS_T_MTREEONLY
|
||||||
| ((CKMETA) ? LFS_T_CKMETA : 0));
|
| ((CKMETA) ? LFS_T_CKMETA : 0));
|
||||||
@@ -4198,7 +4199,7 @@ code = '''
|
|||||||
assert(i < 2*BLOCK_COUNT);
|
assert(i < 2*BLOCK_COUNT);
|
||||||
|
|
||||||
lfsr_mtinfo_t mtinfo;
|
lfsr_mtinfo_t mtinfo;
|
||||||
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
|
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
|
||||||
assert(!err || err == LFS_ERR_NOENT);
|
assert(!err || err == LFS_ERR_NOENT);
|
||||||
if (err == LFS_ERR_NOENT) {
|
if (err == LFS_ERR_NOENT) {
|
||||||
break;
|
break;
|
||||||
@@ -4246,7 +4247,6 @@ code = '''
|
|||||||
// and the tree should still work
|
// and the tree should still work
|
||||||
|
|
||||||
// try looking up each entry
|
// try looking up each entry
|
||||||
lfsr_mdir_t mdir;
|
|
||||||
lfsr_mtree_lookup(&lfs, 0, &mdir) => 0;
|
lfsr_mtree_lookup(&lfs, 0, &mdir) => 0;
|
||||||
lfsr_data_t data;
|
lfsr_data_t data;
|
||||||
uint8_t buffer[256];
|
uint8_t buffer[256];
|
||||||
@@ -4313,6 +4313,7 @@ code = '''
|
|||||||
LFSR_DATA_MPTR(&LFSR_MPTR_MROOTANCHOR())))) => 0;
|
LFSR_DATA_MPTR(&LFSR_MPTR_MROOTANCHOR())))) => 0;
|
||||||
|
|
||||||
// technically, cycle detection only needs to work when we're validating
|
// technically, cycle detection only needs to work when we're validating
|
||||||
|
lfsr_mdir_t mdir;
|
||||||
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
|
lfsr_mtraversal_t mt = LFSR_MTRAVERSAL(
|
||||||
LFS_T_MTREEONLY | LFS_T_CKMETA);
|
LFS_T_MTREEONLY | LFS_T_CKMETA);
|
||||||
for (lfs_block_t i = 0;; i++) {
|
for (lfs_block_t i = 0;; i++) {
|
||||||
@@ -4320,7 +4321,7 @@ code = '''
|
|||||||
assert(i < 2*BLOCK_COUNT);
|
assert(i < 2*BLOCK_COUNT);
|
||||||
|
|
||||||
lfsr_mtinfo_t mtinfo;
|
lfsr_mtinfo_t mtinfo;
|
||||||
int err = lfsr_mtree_traverse(&lfs, &mt, &mtinfo);
|
int err = lfsr_mtree_traverse(&lfs, &mdir, &mt, &mtinfo);
|
||||||
assert(!err || err == LFS_ERR_CORRUPT);
|
assert(!err || err == LFS_ERR_CORRUPT);
|
||||||
if (err == LFS_ERR_CORRUPT) {
|
if (err == LFS_ERR_CORRUPT) {
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user