bmap: Taught littlefs how to traverse the gbmap

Fortunately the btree traversal logic is pretty reusable, so this just
required an additional tstate (LFS3_TSTATE_BMAP).

This raises an interesting question: _when_ do we traverse the bmap? We
need to wait until at least mtree traversal completes for gstate to be
reconstructed during lfs3_mount, but I think traversing before file
btrees makes sense.
This commit is contained in:
Christopher Haster
2025-07-24 00:16:14 -05:00
parent 1537f6a430
commit 59a4ae6f61
2 changed files with 37 additions and 15 deletions
+30 -9
View File
@@ -9955,13 +9955,14 @@ enum lfs3_tstate {
#ifndef LFS3_2BONLY #ifndef LFS3_2BONLY
LFS3_TSTATE_MROOTCHAIN = 1, LFS3_TSTATE_MROOTCHAIN = 1,
LFS3_TSTATE_MTREE = 2, LFS3_TSTATE_MTREE = 2,
LFS3_TSTATE_MDIRS = 3, LFS3_TSTATE_BMAP = 3,
LFS3_TSTATE_MDIR = 4, LFS3_TSTATE_MDIRS = 4,
LFS3_TSTATE_BTREE = 5, LFS3_TSTATE_MDIR = 5,
LFS3_TSTATE_HANDLES = 6, LFS3_TSTATE_BTREE = 6,
LFS3_TSTATE_HBTREE = 7, LFS3_TSTATE_HANDLES = 7,
LFS3_TSTATE_HBTREE = 8,
#endif #endif
LFS3_TSTATE_DONE = 8, LFS3_TSTATE_DONE = 9,
}; };
static void lfs3_trv_init(lfs3_trv_t *trv, uint32_t flags) { static void lfs3_trv_init(lfs3_trv_t *trv, uint32_t flags) {
@@ -10193,6 +10194,7 @@ static lfs3_stag_t lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_trv_t *trv,
// and any file btrees/bshrubs // and any file btrees/bshrubs
#ifndef LFS3_2BONLY #ifndef LFS3_2BONLY
case LFS3_TSTATE_MTREE:; case LFS3_TSTATE_MTREE:;
case LFS3_TSTATE_BMAP:;
case LFS3_TSTATE_BTREE:; case LFS3_TSTATE_BTREE:;
case LFS3_TSTATE_HBTREE:; case LFS3_TSTATE_HBTREE:;
// traverse through our bshrub/btree // traverse through our bshrub/btree
@@ -10202,9 +10204,26 @@ static lfs3_stag_t lfs3_mtree_traverse_(lfs3_t *lfs3, lfs3_trv_t *trv,
if (tag == LFS3_ERR_NOENT) { if (tag == LFS3_ERR_NOENT) {
// clear the bshrub state // clear the bshrub state
lfs3_bshrub_init(&trv->b); lfs3_bshrub_init(&trv->b);
// end of mtree? start iterating over mdirs // end of mtree? have a bmap? not mtreeonly? start
if (lfs3_t_tstate(trv->b.h.flags) // iterating over bmap
== LFS3_TSTATE_MTREE) { if (LFS3_IFDEF_BMAP(
lfs3_t_tstate(trv->b.h.flags)
== LFS3_TSTATE_MTREE
&& !lfs3_t_ismtreeonly(trv->b.h.flags),
false)) {
#ifdef LFS3_BMAP
trv->b.shrub = lfs3->gbmap.b;
trv->bid = -2;
lfs3_t_settstate(&trv->b.h.flags, LFS3_TSTATE_BMAP);
continue;
#endif
// end of mtree and bmap? start iterating over mdirs
} else if (lfs3_t_tstate(trv->b.h.flags)
== LFS3_TSTATE_MTREE
|| LFS3_IFDEF_BMAP(
lfs3_t_tstate(trv->b.h.flags)
== LFS3_TSTATE_BMAP,
false)) {
trv->b.h.mdir.mid = 0; trv->b.h.mdir.mid = 0;
lfs3_t_settstate(&trv->b.h.flags, LFS3_TSTATE_MDIRS); lfs3_t_settstate(&trv->b.h.flags, LFS3_TSTATE_MDIRS);
continue; continue;
@@ -15430,12 +15449,14 @@ static int lfs3_mountinited(lfs3_t *lfs3) {
// decode the global block-map // decode the global block-map
// //
// this one is a bit less exciting // this one is a bit less exciting
#ifdef LFS3_BMAP
err = lfs3_data_readgbmap(lfs3, err = lfs3_data_readgbmap(lfs3,
&LFS3_DATA_BUF(lfs3->gbmap_d, LFS3_GBMAP_DSIZE)); &LFS3_DATA_BUF(lfs3->gbmap_d, LFS3_GBMAP_DSIZE));
if (err) { if (err) {
// TODO switch to read-only? // TODO switch to read-only?
return err; return err;
} }
#endif
return 0; return 0;
} }
+7 -6
View File
@@ -162,12 +162,13 @@ FLAGS = [
0x00000000, "Tstate = mroot-anchor" ), 0x00000000, "Tstate = mroot-anchor" ),
('^_MROOTCHAIN', 0x00010000, "Tstate = mroot-chain" ), ('^_MROOTCHAIN', 0x00010000, "Tstate = mroot-chain" ),
('^_MTREE', 0x00020000, "Tstate = mtree" ), ('^_MTREE', 0x00020000, "Tstate = mtree" ),
('^_MDIRS', 0x00030000, "Tstate = mtree-mdirs" ), ('^_BMAP', 0x00030000, "Tstate = bmap" ),
('^_MDIR', 0x00040000, "Tstate = mdir" ), ('^_MDIRS', 0x00040000, "Tstate = mtree-mdirs" ),
('^_BTREE', 0x00050000, "Tstate = btree" ), ('^_MDIR', 0x00050000, "Tstate = mdir" ),
('^_HANDLES', 0x00060000, "Tstate = open-mdirs" ), ('^_BTREE', 0x00060000, "Tstate = btree" ),
('^_HBTREE', 0x00070000, "Tstate = open-btree" ), ('^_HANDLES', 0x00070000, "Tstate = open-mdirs" ),
('^_DONE', 0x00080000, "Tstate = done" ), ('^_HBTREE', 0x00080000, "Tstate = open-btree" ),
('^_DONE', 0x00090000, "Tstate = done" ),
('t_BTYPE', 0x00f00000, "The current block type" ), ('t_BTYPE', 0x00f00000, "The current block type" ),
('^_MDIR', 0x00100000, "Btype = mdir" ), ('^_MDIR', 0x00100000, "Btype = mdir" ),
('^_BTREE', 0x00200000, "Btype = btree" ), ('^_BTREE', 0x00200000, "Btype = btree" ),