Reworked lfsr_bshrub_t, renamed file.o -> file.b

This moves all of the shrub tracking logic from lfsr_obshrub_t into
lfsr_bshrub_t, completely drops the lfsr_obshrub_t type, and changes all
lfsr_bshrub_* functions to take lfsr_bshrub_t instead of the mdir+shrub
pair.

This makes the lfsr_bshrub_* functions <-> lfsr_bshrub_t relationship
more consistent with other APIs, such as lfsr_btree_t:

  - lfsr_bshrub_lookupnext(lfs, &file->o.o.mdir, &file->o.bshrub, ...)
  + lfsr_bshrub_lookupnext(lfs, &file->b, ...)

I think the reason why this design wasn't obvious before is because, at
least conceptually, having the lfsr_mdir_t live inside the lfsr_bshrub_t
is a bit weird. It's only thanks to lfsr_file_t invasively using the
internal lfsr_mdir_t that we can avoid duplicate lfsr_mdir_t objects.

This also reorganizes the structs in lfs.h a bit, and renames the
related file.o -> file.b fields (much needed because lfs->gc.t.o.o.mdir.
rbyd.blocks was starting to get _real_ confusing).

---

Unfortunately, reducing the number of arguments to lfsr_bshrub_*
functions did not save nearly as much code as I thought it would. It
even ended up with a net _increase_ of code, apparently due to needing
to recalculate the bshrub->shrub offset more often:

           code          stack          ctx
  before: 36476           2608          640
  after:  36484 (+0.0%)   2608 (+0.0%)  640 (+0.0%)

Strange, but this rework is still worthwhile if only for the code
readability.
This commit is contained in:
Christopher Haster
2025-02-03 03:07:30 -06:00
parent fd62ef9674
commit bc639b03f2
7 changed files with 487 additions and 506 deletions
+60 -63
View File
@@ -584,42 +584,6 @@ struct lfs_file_config {
// uint8_t *buffer;
//} lfs_cache_t;
// TODO do we get ram savings with a lfsr_rorbyd_t substruct? need to measure
typedef struct lfsr_rbyd {
// note this lines up with weight in lfsr_data_t
// sign(weight)=0 => rbyd
lfsr_rid_t weight;
lfs_block_t blocks[2];
// sign(trunk)=0 => normal rbyd
// sign(trunk)=1 => shrub rbyd
lfs_size_t trunk;
// sign(eoff) => perturb bit
// eoff=0, trunk=0 => not yet committed
// eoff=0, trunk>0 => not yet fetched
// eoff>=block_size => rbyd not erased/needs compaction
lfs_size_t eoff;
uint32_t cksum;
} lfsr_rbyd_t;
// a btree is just the root rbyd
typedef lfsr_rbyd_t lfsr_btree_t;
// a shrub is a secondary trunk in an mdir
typedef lfsr_rbyd_t lfsr_shrub_t;
typedef struct lfsr_mdir {
lfsr_smid_t mid;
lfsr_rbyd_t rbyd;
uint32_t gcksumdelta;
} lfsr_mdir_t;
typedef struct lfsr_omdir {
struct lfsr_omdir *next;
uint32_t flags;
lfsr_mdir_t mdir;
} lfsr_omdir_t;
//typedef struct lfs_mdir {
// lfs_block_t pair[2];
// uint32_t rev;
@@ -656,6 +620,62 @@ typedef struct lfsr_data {
} u;
} lfsr_data_t;
// a block pointer
typedef struct lfsr_bptr {
lfsr_data_t data;
#ifndef LFS_CKDATACKSUMS
lfs_size_t cksize;
uint32_t cksum;
#endif
} lfsr_bptr_t;
// littlefs's core metadata log type
typedef struct lfsr_rbyd {
lfsr_rid_t weight;
lfs_block_t blocks[2];
// sign(trunk)=0 => normal rbyd
// sign(trunk)=1 => shrub rbyd
lfs_size_t trunk;
// sign(eoff) => perturb bit
// eoff=0, trunk=0 => not yet committed
// eoff=0, trunk>0 => not yet fetched
// eoff>=block_size => rbyd not erased/needs compaction
lfs_size_t eoff;
uint32_t cksum;
} lfsr_rbyd_t;
// a btree is represented by the root rbyd
typedef lfsr_rbyd_t lfsr_btree_t;
// littlefs's atomic metadata log type
typedef struct lfsr_mdir {
lfsr_smid_t mid;
lfsr_rbyd_t rbyd;
uint32_t gcksumdelta;
} lfsr_mdir_t;
typedef struct lfsr_omdir {
struct lfsr_omdir *next;
uint32_t flags;
lfsr_mdir_t mdir;
} lfsr_omdir_t;
// a shrub is a secondary trunk in an mdir
typedef lfsr_rbyd_t lfsr_shrub_t;
// a bshrub is like a btree but with a shrub as a root
typedef struct lfsr_bshrub {
// bshrubs need to be tracked for commits to work
lfsr_omdir_t o;
// files contain both an active bshrub and staging bshrub, to allow
// staging during mdir compacts
// trunk=0 => no bshrub/btree
// sign(trunk)=1 => bshrub
// sign(trunk)=0 => btree
lfsr_shrub_t shrub;
lfsr_shrub_t shrub_;
} lfsr_bshrub_t;
// littlefs file type
//typedef struct lfs_file {
@@ -678,32 +698,8 @@ typedef struct lfsr_data {
// const struct lfs_file_config *cfg;
//} lfs_file_t;
typedef struct lfsr_bptr {
lfsr_data_t data;
#ifndef LFS_CKDATACKSUMS
lfs_size_t cksize;
uint32_t cksum;
#endif
} lfsr_bptr_t;
// the lfsr_bshrub_t struct represents the on-disk component of a file
//
// weight=0 => no bshrub/btree
// sign(weight)=1 => bshrub
// sign(weight)=0 => btree
typedef lfsr_rbyd_t lfsr_bshrub_t;
typedef struct lfsr_obshrub {
// bshrubs need to be tracked for commits to work
lfsr_omdir_t o;
// files contain both an active bshrub and staging bshrub, to allow
// staging during mdir compacts
lfsr_bshrub_t bshrub;
lfsr_bshrub_t bshrub_;
} lfsr_obshrub_t;
typedef struct lfsr_file {
lfsr_obshrub_t o;
lfsr_bshrub_t b;
const struct lfs_file_config *cfg;
lfs_off_t pos;
@@ -747,8 +743,9 @@ typedef struct lfsr_btraversal {
} lfsr_btraversal_t;
typedef struct lfsr_traversal {
// mdir/btree state, this also includes our traversal state machine
lfsr_obshrub_t o;
// mdir/bshrub/btree state, this also includes our traversal
// state machine
lfsr_bshrub_t b;
// opened file state
lfsr_omdir_t *ot;
union {