From 9e45249b29a870366ca6ccee459895c11e0dfc2a Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Fri, 10 Oct 2025 13:44:40 -0500 Subject: [PATCH] gbmap: Added support for gbmap in lfs3_fs_grow In lfs3_fs_grow, we need to update any gbmaps to match the new disk size. The actual patch to the gbmap is easy, but it does get a bit delicate since we need to feed the gbmap with an allocator in the new disk size. Fortunately, the opportunistism of the gbmap allocator avoids any catch-22 issues, as long as we make sure to not trigger any gbmap rebuilds. Adds a bit of code, but not much: code stack ctx before: 37168 2352 684 after: 37168 (+0.0%) 2352 (+0.0%) 684 (+0.0%) code stack ctx gbmap before: 39000 2456 800 gbmap after: 39116 (+0.3%) 2456 (+0.0%) 800 (+0.0%) --- lfs3.c | 79 +++++++++++++++++----- scripts/dbgbmap.py | 4 +- scripts/dbgbmapsvg.py | 4 +- scripts/dbglfs3.py | 4 +- tests/test_alloc.toml | 11 ++-- tests/test_badblocks.toml | 72 ++++++++++---------- tests/test_grow.toml | 134 ++++++++++++++++++++++++-------------- 7 files changed, 196 insertions(+), 112 deletions(-) diff --git a/lfs3.c b/lfs3.c index 63f93c30..f189ee7b 100644 --- a/lfs3.c +++ b/lfs3.c @@ -7875,7 +7875,7 @@ static int lfs3_rbyd_appendgdelta(lfs3_t *lfs3, lfs3_rbyd_t *rbyd) { // TODO is this the right place? // try to update to most recent lookahead window lfs3->gbmap.window = (lfs3->lookahead.window + lfs3->lookahead.off) - % lfs3->cfg->block_count; + % lfs3->block_count; lfs3->gbmap.known = lfs3->lookahead.gbmapped; uint8_t gbmapdelta_[LFS3_GBMAP_DSIZE]; @@ -10981,6 +10981,13 @@ static int lfs3_gbmap_setbptr(lfs3_t *lfs3, lfs3_btree_t *gbmap, /// Block allocator /// +// checkpoint only the lookahead buffer +#ifndef LFS3_RDONLY +static inline void lfs3_alloc_ckpoint_(lfs3_t *lfs3) { + lfs3->lookahead.ckpoint = lfs3->block_count; +} +#endif + // needed in lfs3_alloc_ckpoint static int lfs3_alloc_rebuildgbmap(lfs3_t *lfs3); @@ -10995,7 +11002,7 @@ static int lfs3_alloc_rebuildgbmap(lfs3_t *lfs3); static inline int lfs3_alloc_ckpoint(lfs3_t *lfs3) { #ifndef LFS3_2BONLY // checkpoint the allocator - lfs3->lookahead.ckpoint = lfs3->block_count; + lfs3_alloc_ckpoint_(lfs3); #ifdef LFS3_GBMAP // do we need to rebuild the gbmap? @@ -11009,7 +11016,7 @@ static inline int lfs3_alloc_ckpoint(lfs3_t *lfs3) { } // checkpoint the allocator again - lfs3->lookahead.ckpoint = lfs3->block_count; + lfs3_alloc_ckpoint_(lfs3); } #endif @@ -11021,11 +11028,17 @@ static inline int lfs3_alloc_ckpoint(lfs3_t *lfs3) { } #endif -// discard any lookahead state, this is necessary if block_count changes +// discard any lookahead/gbmap windows, this is necessary if block_count +// changes #if !defined(LFS3_RDONLY) && !defined(LFS3_2BONLY) static inline void lfs3_alloc_discard(lfs3_t *lfs3) { + // discard lookahead state lfs3->lookahead.known = 0; lfs3_memset(lfs3->lookahead.buffer, 0, lfs3->cfg->lookahead_size); + // discard gbmap window + #ifdef LFS3_GBMAP + lfs3->lookahead.gbmapped = 0; + #endif } #endif @@ -11218,7 +11231,7 @@ static lfs3_sblock_t lfs3_alloc(lfs3_t *lfs3, uint32_t flags) { "lookahead %"PRId32"/%"PRId32, block, lfs3->lookahead.known, - lfs3->cfg->block_count); + lfs3->block_count); #endif return block; } @@ -11234,7 +11247,7 @@ static lfs3_sblock_t lfs3_alloc(lfs3_t *lfs3, uint32_t flags) { LFS3_ERROR("No more free space " "(lookahead %"PRId32"/%"PRId32")", lfs3->lookahead.known, - lfs3->cfg->block_count); + lfs3->block_count); return LFS3_ERR_NOSPC; } @@ -11298,11 +11311,11 @@ static lfs3_sblock_t lfs3_alloc(lfs3_t *lfs3, uint32_t flags) { #if !defined(LFS3_RDONLY) && defined(LFS3_GBMAP) static int lfs3_alloc_rebuildgbmap(lfs3_t *lfs3) { // we should ckpoint before calling this - LFS3_ASSERT(lfs3->lookahead.ckpoint == lfs3->cfg->block_count); + LFS3_ASSERT(lfs3->lookahead.ckpoint == lfs3->block_count); LFS3_INFO("Rebuilding gbmap " "(gbmap %"PRId32"/%"PRId32")", lfs3->lookahead.gbmapped, - lfs3->cfg->block_count); + lfs3->block_count); // create a copy of the gbmap lfs3_btree_t gbmap_ = lfs3->gbmap.b; @@ -11378,7 +11391,7 @@ failed:; LFS3_INFO("Not enough space for gbmap " "(lookahead %"PRId32"/%"PRId32")", lfs3->lookahead.known, - lfs3->cfg->block_count); + lfs3->block_count); return 0; } return err; @@ -15391,9 +15404,6 @@ static int lfs3_init(lfs3_t *lfs3, uint32_t flags, lfs3->lookahead.off = 0; lfs3->lookahead.known = 0; lfs3->lookahead.ckpoint = 0; - #ifdef LFS3_GBMAP - lfs3->lookahead.gbmapped = 0; - #endif lfs3_alloc_discard(lfs3); #endif @@ -16322,7 +16332,7 @@ static int lfs3_formatgbmap(lfs3_t *lfs3) { // // assume we can write gbmap to block 2 lfs3->gbmap.window = 3; - lfs3->gbmap.known = lfs3->cfg->block_count; + lfs3->gbmap.known = lfs3->block_count; lfs3->gbmap.b.r.blocks[0] = 2; lfs3->gbmap.b.r.trunk = 0; lfs3->gbmap.b.r.weight = 0; @@ -16346,7 +16356,9 @@ static int lfs3_formatgbmap(lfs3_t *lfs3) { // blocks 0..3 - in-use LFS3_RATTR(LFS3_TAG_BMINUSE, +3), // blocks 3..block_count - free - LFS3_RATTR(LFS3_TAG_BMFREE, +(lfs3->cfg->block_count - 3)))); + (lfs3->block_count > 3) + ? LFS3_RATTR(LFS3_TAG_BMFREE, +(lfs3->block_count - 3)) + : LFS3_RATTR_NOOP())); if (err) { goto failed; } @@ -17039,9 +17051,46 @@ int lfs3_fs_grow(lfs3_t *lfs3, lfs3_size_t block_count_) { lfs3->block_count = block_count_; // discard stale lookahead buffer lfs3_alloc_discard(lfs3); + int err; + + // grow the gbmap if we have one + // + // note this won't actually be committed to disk until mdir commit + #ifdef LFS3_GBMAP + if (lfs3_f_isgbmap(lfs3->flags)) { + // if the last range is free, we can extend it, otherwise we + // need a new range + lfs3_stag_t tag = lfs3_gbmap_lookupnext(lfs3, &lfs3->gbmap.b, + block_count-1, + NULL, NULL); + if (tag < 0) { + LFS3_ASSERT(tag != LFS3_ERR_NOENT); + err = tag; + goto failed; + } + + // checkpoint the lookahead buffer, but _not_ the gbmap, we + // cann't rebuild the gbmap until we've resized it + lfs3_alloc_ckpoint_(lfs3); + + // we don't need a copy because this is atomic, and mdir commit + // reverts to the on-disk state if it fails + err = lfs3_gbmap_commit(lfs3, &lfs3->gbmap.b, + (tag == LFS3_TAG_BMFREE) ? block_count-1 : block_count, + LFS3_RATTRS( + LFS3_RATTR( + (tag == LFS3_TAG_BMFREE) + ? LFS3_TAG_GROW + : LFS3_TAG_BMFREE, + +(block_count_ - block_count)))); + if (err) { + goto failed; + } + } + #endif // update our on-disk config - int err = lfs3_mdir_commit(lfs3, &lfs3->mroot, LFS3_RATTRS( + err = lfs3_mdir_commit(lfs3, &lfs3->mroot, LFS3_RATTRS( LFS3_RATTR_GEOMETRY( LFS3_TAG_GEOMETRY, 0, (&(lfs3_geometry_t){ diff --git a/scripts/dbgbmap.py b/scripts/dbgbmap.py index e6c3388a..2a60c17c 100755 --- a/scripts/dbgbmap.py +++ b/scripts/dbgbmap.py @@ -2803,7 +2803,7 @@ class Gstate: def __init__(self, mtree, config, tag, gdeltas): super().__init__(mtree, config, tag, gdeltas) d = 0 - self.cursor, d_ = fromleb128(self.data, d); d += d_ + self.window, d_ = fromleb128(self.data, d); d += d_ self.known, d_ = fromleb128(self.data, d); d += d_ block, trunk, cksum, d_ = frombranch(self.data, d); d += d_ self.btree = Btree.fetchck( @@ -2815,7 +2815,7 @@ class Gstate: def repr(self): return 'gbmap %s 0x%x %d' % ( self.btree.addr(), - self.cursor, self.known) + self.window, self.known) # keep track of known gstate _known = [g for g in Gstate.__subclasses__() if g.tag is not None] diff --git a/scripts/dbgbmapsvg.py b/scripts/dbgbmapsvg.py index 83b9a45e..0b61085a 100755 --- a/scripts/dbgbmapsvg.py +++ b/scripts/dbgbmapsvg.py @@ -2833,7 +2833,7 @@ class Gstate: def __init__(self, mtree, config, tag, gdeltas): super().__init__(mtree, config, tag, gdeltas) d = 0 - self.cursor, d_ = fromleb128(self.data, d); d += d_ + self.window, d_ = fromleb128(self.data, d); d += d_ self.known, d_ = fromleb128(self.data, d); d += d_ block, trunk, cksum, d_ = frombranch(self.data, d); d += d_ self.btree = Btree.fetchck( @@ -2845,7 +2845,7 @@ class Gstate: def repr(self): return 'gbmap %s 0x%x %d' % ( self.btree.addr(), - self.cursor, self.known) + self.window, self.known) # keep track of known gstate _known = [g for g in Gstate.__subclasses__() if g.tag is not None] diff --git a/scripts/dbglfs3.py b/scripts/dbglfs3.py index d702def6..75f3d4d7 100755 --- a/scripts/dbglfs3.py +++ b/scripts/dbglfs3.py @@ -2728,7 +2728,7 @@ class Gstate: def __init__(self, mtree, config, tag, gdeltas): super().__init__(mtree, config, tag, gdeltas) d = 0 - self.cursor, d_ = fromleb128(self.data, d); d += d_ + self.window, d_ = fromleb128(self.data, d); d += d_ self.known, d_ = fromleb128(self.data, d); d += d_ block, trunk, cksum, d_ = frombranch(self.data, d); d += d_ self.btree = Btree.fetchck( @@ -2740,7 +2740,7 @@ class Gstate: def repr(self): return 'gbmap %s 0x%x %d' % ( self.btree.addr(), - self.cursor, self.known) + self.window, self.known) # keep track of known gstate _known = [g for g in Gstate.__subclasses__() if g.tag is not None] diff --git a/tests/test_alloc.toml b/tests/test_alloc.toml index fc7f7a5c..20ed2b55 100644 --- a/tests/test_alloc.toml +++ b/tests/test_alloc.toml @@ -9,7 +9,8 @@ # after = ['test_mtree', 'test_gbmap', 'test_dirs', 'test_files'] -defines.INIT_BLOCKS = 'LFS3_IFDEF_GBMAP(3, 2)' +defines.FORMAT_BLOCK_COUNT = 'LFS3_IFDEF_YES_GBMAP(3, 2)' + # test that we can alloc [cases.test_alloc_alloc] @@ -22,7 +23,7 @@ defines.COUNT = [ '2', ] defines.ERASE = [false, true] -if = 'COUNT >= INIT_BLOCKS' +if = 'COUNT >= FORMAT_BLOCK_COUNT' in = 'lfs3.c' code = ''' // test various block counts @@ -69,7 +70,7 @@ defines.COUNT = [ '2', ] defines.ERASE = [false, true] -if = 'COUNT >= INIT_BLOCKS' +if = 'COUNT >= FORMAT_BLOCK_COUNT' in = 'lfs3.c' code = ''' // test various block counts @@ -655,7 +656,7 @@ defines.COUNT = [ '5', '2', ] -if = 'COUNT >= INIT_BLOCKS' +if = 'COUNT >= FORMAT_BLOCK_COUNT' code = ''' // test various block counts struct lfs3_cfg cfg = *CFG; @@ -738,7 +739,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] -if = 'COUNT >= INIT_BLOCKS' +if = 'COUNT >= FORMAT_BLOCK_COUNT' code = ''' // test various block counts struct lfs3_cfg cfg = *CFG; diff --git a/tests/test_badblocks.toml b/tests/test_badblocks.toml index 2d78731f..29766647 100644 --- a/tests/test_badblocks.toml +++ b/tests/test_badblocks.toml @@ -11,7 +11,7 @@ after = [ 'test_compat', ] -defines.INIT_BLOCKS = 'LFS3_IFDEF_GBMAP(3, 2)' +defines.FORMAT_BLOCK_COUNT = 'LFS3_IFDEF_YES_GBMAP(3, 2)' ## Single-block badblock tests @@ -149,7 +149,7 @@ defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] if = 'LFS3_IFDEF_CKPROGS(true, !CKPROGS)' code = ''' // test all possible bad blocks - for (lfs3_size_t i = INIT_BLOCKS; + for (lfs3_size_t i = FORMAT_BLOCK_COUNT; i < ((BADBLOCK == -1) ? BLOCK_COUNT : 1); i++) { lfs3_size_t badblock = (BADBLOCK == -1) ? i : BADBLOCK; @@ -267,7 +267,7 @@ fuzz = 'SEED' if = 'LFS3_IFDEF_CKPROGS(true, !CKPROGS)' code = ''' // test all possible bad blocks - for (lfs3_size_t i = INIT_BLOCKS; + for (lfs3_size_t i = FORMAT_BLOCK_COUNT; i < ((BADBLOCK == -1) ? BLOCK_COUNT : 1); i++) { lfs3_size_t badblock = (BADBLOCK == -1) ? i : BADBLOCK; @@ -462,7 +462,7 @@ if = [ ] code = ''' // test all possible bad blocks - for (lfs3_size_t i = INIT_BLOCKS; + for (lfs3_size_t i = FORMAT_BLOCK_COUNT; i < ((BADBLOCK == -1) ? BLOCK_COUNT : 1); i++) { lfs3_size_t badblock = (BADBLOCK == -1) ? i : BADBLOCK; @@ -576,7 +576,7 @@ if = [ ] code = ''' // test all possible bad blocks - for (lfs3_size_t i = INIT_BLOCKS; + for (lfs3_size_t i = FORMAT_BLOCK_COUNT; i < ((BADBLOCK == -1) ? BLOCK_COUNT : 1); i++) { lfs3_size_t badblock = (BADBLOCK == -1) ? i : BADBLOCK; @@ -833,7 +833,7 @@ if = [ ] code = ''' // test all possible bad blocks - for (lfs3_size_t i = INIT_BLOCKS; + for (lfs3_size_t i = FORMAT_BLOCK_COUNT; i < ((BADBLOCK == -1) ? BLOCK_COUNT : 1); i++) { lfs3_size_t badblock = (BADBLOCK == -1) ? i : BADBLOCK; @@ -996,7 +996,7 @@ if = [ ] code = ''' // test all possible bad blocks - for (lfs3_size_t i = INIT_BLOCKS; + for (lfs3_size_t i = FORMAT_BLOCK_COUNT; i < ((BADBLOCK == -1) ? BLOCK_COUNT : 1); i++) { lfs3_size_t badblock = (BADBLOCK == -1) ? i : BADBLOCK; @@ -1448,7 +1448,7 @@ if = [ ] code = ''' // test all possible bad blocks - for (lfs3_size_t i = INIT_BLOCKS; + for (lfs3_size_t i = FORMAT_BLOCK_COUNT; i < ((BADBLOCK == -1) ? BLOCK_COUNT : 1); i++) { lfs3_size_t badblock = (BADBLOCK == -1) ? i : BADBLOCK; @@ -2103,11 +2103,11 @@ code = ''' for (lfs3_size_t i = 0; i < BLOCK_COUNT/2; i++) { // mark our badblock as bad if (!MIRROR) { - if (i >= INIT_BLOCKS) { + if (i >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, i) => 0; } } else { - if (i+BLOCK_COUNT/2 >= INIT_BLOCKS) { + if (i+BLOCK_COUNT/2 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, i+BLOCK_COUNT/2) => 0; } } @@ -2222,11 +2222,11 @@ code = ''' for (lfs3_size_t i = 0; i < BLOCK_COUNT/2; i++) { // mark our badblock as bad if (!MIRROR) { - if (i >= INIT_BLOCKS) { + if (i >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, i) => 0; } } else { - if (i+BLOCK_COUNT/2 >= INIT_BLOCKS) { + if (i+BLOCK_COUNT/2 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, i+BLOCK_COUNT/2) => 0; } } @@ -2418,11 +2418,11 @@ code = ''' for (lfs3_size_t i = 0; i < BLOCK_COUNT/2; i++) { // mark our badblock as bad if (!MIRROR) { - if (i >= INIT_BLOCKS) { + if (i >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, i) => 0; } } else { - if (i+BLOCK_COUNT/2 >= INIT_BLOCKS) { + if (i+BLOCK_COUNT/2 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, i+BLOCK_COUNT/2) => 0; } } @@ -2533,11 +2533,11 @@ code = ''' for (lfs3_size_t i = 0; i < BLOCK_COUNT/2; i++) { // mark our badblock as bad if (!MIRROR) { - if (i >= INIT_BLOCKS) { + if (i >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, i) => 0; } } else { - if (i+BLOCK_COUNT/2 >= INIT_BLOCKS) { + if (i+BLOCK_COUNT/2 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, i+BLOCK_COUNT/2) => 0; } } @@ -2791,11 +2791,11 @@ code = ''' for (lfs3_size_t i = 0; i < BLOCK_COUNT/2; i++) { // mark our badblock as bad if (!MIRROR) { - if (i >= INIT_BLOCKS) { + if (i >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, i) => 0; } } else { - if (i+BLOCK_COUNT/2 >= INIT_BLOCKS) { + if (i+BLOCK_COUNT/2 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, i+BLOCK_COUNT/2) => 0; } } @@ -2955,11 +2955,11 @@ code = ''' for (lfs3_size_t i = 0; i < BLOCK_COUNT/2; i++) { // mark our badblock as bad if (!MIRROR) { - if (i >= INIT_BLOCKS) { + if (i >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, i) => 0; } } else { - if (i+BLOCK_COUNT/2 >= INIT_BLOCKS) { + if (i+BLOCK_COUNT/2 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, i+BLOCK_COUNT/2) => 0; } } @@ -3408,11 +3408,11 @@ code = ''' for (lfs3_size_t i = 0; i < BLOCK_COUNT/2; i++) { // mark our badblock as bad if (!MIRROR) { - if (i >= INIT_BLOCKS) { + if (i >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, i) => 0; } } else { - if (i+BLOCK_COUNT/2 >= INIT_BLOCKS) { + if (i+BLOCK_COUNT/2 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, i+BLOCK_COUNT/2) => 0; } } @@ -4060,11 +4060,11 @@ code = ''' for (lfs3_size_t i = 0; i < BLOCK_COUNT/2; i++) { // mark our badblock as bad if (!MIRROR) { - if (2*i+0 >= INIT_BLOCKS) { + if (2*i+0 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, 2*i+0) => 0; } } else { - if (2*i+1 >= INIT_BLOCKS) { + if (2*i+1 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, 2*i+1) => 0; } } @@ -4179,11 +4179,11 @@ code = ''' for (lfs3_size_t i = 0; i < BLOCK_COUNT/2; i++) { // mark our badblock as bad if (!MIRROR) { - if (2*i+0 >= INIT_BLOCKS) { + if (2*i+0 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, 2*i+0) => 0; } } else { - if (2*i+1 >= INIT_BLOCKS) { + if (2*i+1 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, 2*i+1) => 0; } } @@ -4375,11 +4375,11 @@ code = ''' for (lfs3_size_t i = 0; i < BLOCK_COUNT/2; i++) { // mark our badblock as bad if (!MIRROR) { - if (2*i+0 >= INIT_BLOCKS) { + if (2*i+0 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, 2*i+0) => 0; } } else { - if (2*i+1 >= INIT_BLOCKS) { + if (2*i+1 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, 2*i+1) => 0; } } @@ -4490,11 +4490,11 @@ code = ''' for (lfs3_size_t i = 0; i < BLOCK_COUNT/2; i++) { // mark our badblock as bad if (!MIRROR) { - if (2*i+0 >= INIT_BLOCKS) { + if (2*i+0 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, 2*i+0) => 0; } } else { - if (2*i+1 >= INIT_BLOCKS) { + if (2*i+1 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, 2*i+1) => 0; } } @@ -4748,11 +4748,11 @@ code = ''' for (lfs3_size_t i = 0; i < BLOCK_COUNT/2; i++) { // mark our badblock as bad if (!MIRROR) { - if (2*i+0 >= INIT_BLOCKS) { + if (2*i+0 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, 2*i+0) => 0; } } else { - if (2*i+1 >= INIT_BLOCKS) { + if (2*i+1 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, 2*i+1) => 0; } } @@ -4910,11 +4910,11 @@ code = ''' for (lfs3_size_t i = 0; i < BLOCK_COUNT/2; i++) { // mark our badblock as bad if (!MIRROR) { - if (2*i+0 >= INIT_BLOCKS) { + if (2*i+0 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, 2*i+0) => 0; } } else { - if (2*i+1 >= INIT_BLOCKS) { + if (2*i+1 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, 2*i+1) => 0; } } @@ -5363,11 +5363,11 @@ code = ''' for (lfs3_size_t i = 0; i < BLOCK_COUNT/2; i++) { // mark our badblock as bad if (!MIRROR) { - if (2*i+0 >= INIT_BLOCKS) { + if (2*i+0 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, 2*i+0) => 0; } } else { - if (2*i+1 >= INIT_BLOCKS) { + if (2*i+1 >= FORMAT_BLOCK_COUNT) { lfs3_emubd_markbad(CFG, 2*i+1) => 0; } } diff --git a/tests/test_grow.toml b/tests/test_grow.toml index 5a829a4c..90b6a210 100644 --- a/tests/test_grow.toml +++ b/tests/test_grow.toml @@ -8,8 +8,14 @@ after = [ 'test_mount', ] -# TODO!! lfs3_fs_grow needs to be able to adjust an on-disk bmaps -ifndef = 'LFS3_GBMAP' +# Test both with and without the gbmap if available +defines.GBMAP = [false, true] +if = ''' + LFS3_IFDEF_YES_GBMAP( + GBMAP, + LFS3_IFDEF_GBMAP(true, !GBMAP)) +''' +defines.FORMAT_BLOCK_COUNT = '(GBMAP) ? 3 : 2' # test we can mount a filesystem with fewer blocks @@ -18,7 +24,7 @@ defines.SMALLER_BLOCK_COUNT = [ 'BLOCK_COUNT-1', 'BLOCK_COUNT/2', 'BLOCK_COUNT/4', - '2', + 'FORMAT_BLOCK_COUNT', ] defines.BIGGER_BLOCK_COUNT = [ 'BLOCK_COUNT', @@ -32,7 +38,10 @@ code = ''' struct lfs3_cfg cfg = *CFG; cfg.block_count = SMALLER_BLOCK_COUNT; lfs3_t lfs3; - lfs3_format(&lfs3, LFS3_F_RDWR, &cfg) => 0; + lfs3_format(&lfs3, + LFS3_F_RDWR + | ((GBMAP) ? LFS3_IFDEF_GBMAP(LFS3_F_GBMAP, -1) : 0), + &cfg) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; // fsstat up to date? @@ -137,7 +146,7 @@ defines.SMALLER_BLOCK_COUNT = [ 'BLOCK_COUNT-1', 'BLOCK_COUNT/2', 'BLOCK_COUNT/4', - '2', + 'FORMAT_BLOCK_COUNT', ] defines.BIGGER_BLOCK_COUNT = [ 'BLOCK_COUNT', @@ -151,7 +160,10 @@ code = ''' struct lfs3_cfg cfg = *CFG; cfg.block_count = BIGGER_BLOCK_COUNT; lfs3_t lfs3; - lfs3_format(&lfs3, LFS3_F_RDWR, &cfg) => 0; + lfs3_format(&lfs3, + LFS3_F_RDWR + | ((GBMAP) ? LFS3_IFDEF_GBMAP(LFS3_F_GBMAP, -1) : 0), + &cfg) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; // fsstat up to date? @@ -198,7 +210,7 @@ defines.SMALLER_BLOCK_COUNT = [ 'BLOCK_COUNT-1', 'BLOCK_COUNT/2', 'BLOCK_COUNT/4', - '2', + 'FORMAT_BLOCK_COUNT', ] defines.BIGGER_BLOCK_COUNT = [ 'BLOCK_COUNT', @@ -212,7 +224,10 @@ code = ''' struct lfs3_cfg cfg = *CFG; cfg.block_count = SMALLER_BLOCK_COUNT; lfs3_t lfs3; - lfs3_format(&lfs3, LFS3_F_RDWR, &cfg) => 0; + lfs3_format(&lfs3, + LFS3_F_RDWR + | ((GBMAP) ? LFS3_IFDEF_GBMAP(LFS3_F_GBMAP, -1) : 0), + &cfg) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; // fsstat up to date? @@ -320,14 +335,17 @@ defines.SMALLER_BLOCK_COUNT = [ 'BLOCK_COUNT-1', 'BLOCK_COUNT/2', 'BLOCK_COUNT/4', - '2', + 'FORMAT_BLOCK_COUNT', ] code = ''' // create a smaller fs struct lfs3_cfg cfg = *CFG; cfg.block_count = SMALLER_BLOCK_COUNT; lfs3_t lfs3; - lfs3_format(&lfs3, LFS3_F_RDWR, &cfg) => 0; + lfs3_format(&lfs3, + LFS3_F_RDWR + | ((GBMAP) ? LFS3_IFDEF_GBMAP(LFS3_F_GBMAP, -1) : 0), + &cfg) => 0; lfs3_mount(&lfs3, LFS3_M_RDWR, &cfg) => 0; // fsstat up to date? @@ -436,15 +454,17 @@ code = ''' # [cases.test_grow_incr_spam_dir_many] -defines.INIT_BLOCK_COUNT = 2 defines.REMOUNT = [false, true] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] code = ''' // start with a small number of blocks struct lfs3_cfg cfg = *CFG; - cfg.block_count = INIT_BLOCK_COUNT; + cfg.block_count = FORMAT_BLOCK_COUNT; lfs3_t lfs3; - lfs3_format(&lfs3, LFS3_F_RDWR, &cfg) => 0; + lfs3_format(&lfs3, + LFS3_F_RDWR + | ((GBMAP) ? LFS3_IFDEF_GBMAP(LFS3_F_GBMAP, -1) : 0), + &cfg) => 0; // mount with maximum block count lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; @@ -452,7 +472,7 @@ code = ''' struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(fsinfo.block_size == BLOCK_SIZE); - assert(fsinfo.block_count == INIT_BLOCK_COUNT); + assert(fsinfo.block_count == FORMAT_BLOCK_COUNT); assert(fsinfo.name_limit == LFS3_NAME_MAX); assert(fsinfo.file_limit == LFS3_FILE_MAX); @@ -473,7 +493,7 @@ code = ''' // try growing the filesystem struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; - assert(fsinfo.block_count >= INIT_BLOCK_COUNT); + assert(fsinfo.block_count >= FORMAT_BLOCK_COUNT); assert(fsinfo.block_count <= BLOCK_COUNT); lfs3_ssize_t used = lfs3_fs_usage(&lfs3); assert(used >= 0); @@ -576,7 +596,6 @@ code = ''' ''' [cases.test_grow_incr_spam_dir_fuzz] -defines.INIT_BLOCK_COUNT = 2 defines.REMOUNT = [false, true] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256] defines.OPS = 1024 @@ -585,9 +604,12 @@ fuzz = 'SEED' code = ''' // start with a small number of blocks struct lfs3_cfg cfg = *CFG; - cfg.block_count = INIT_BLOCK_COUNT; + cfg.block_count = FORMAT_BLOCK_COUNT; lfs3_t lfs3; - lfs3_format(&lfs3, LFS3_F_RDWR, &cfg) => 0; + lfs3_format(&lfs3, + LFS3_F_RDWR + | ((GBMAP) ? LFS3_IFDEF_GBMAP(LFS3_F_GBMAP, -1) : 0), + &cfg) => 0; // mount with maximum block count lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; @@ -595,7 +617,7 @@ code = ''' struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(fsinfo.block_size == BLOCK_SIZE); - assert(fsinfo.block_count == INIT_BLOCK_COUNT); + assert(fsinfo.block_count == FORMAT_BLOCK_COUNT); assert(fsinfo.name_limit == LFS3_NAME_MAX); assert(fsinfo.file_limit == LFS3_FILE_MAX); @@ -709,7 +731,7 @@ code = ''' // try growing the filesystem struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; - assert(fsinfo.block_count >= INIT_BLOCK_COUNT); + assert(fsinfo.block_count >= FORMAT_BLOCK_COUNT); assert(fsinfo.block_count <= BLOCK_COUNT); lfs3_ssize_t used = lfs3_fs_usage(&lfs3); assert(used >= 0); @@ -800,7 +822,6 @@ code = ''' ''' [cases.test_grow_incr_spam_file_many] -defines.INIT_BLOCK_COUNT = 2 defines.REMOUNT = [false, true] defines.N = [1, 2, 4, 8, 16, 32, 64] defines.SIZE = [ @@ -816,9 +837,12 @@ if = '(SIZE*N)/BLOCK_SIZE <= 32' code = ''' // start with a small number of blocks struct lfs3_cfg cfg = *CFG; - cfg.block_count = INIT_BLOCK_COUNT; + cfg.block_count = FORMAT_BLOCK_COUNT; lfs3_t lfs3; - lfs3_format(&lfs3, LFS3_F_RDWR, &cfg) => 0; + lfs3_format(&lfs3, + LFS3_F_RDWR + | ((GBMAP) ? LFS3_IFDEF_GBMAP(LFS3_F_GBMAP, -1) : 0), + &cfg) => 0; // mount with maximum block count lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; @@ -826,7 +850,7 @@ code = ''' struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(fsinfo.block_size == BLOCK_SIZE); - assert(fsinfo.block_count == INIT_BLOCK_COUNT); + assert(fsinfo.block_count == FORMAT_BLOCK_COUNT); assert(fsinfo.name_limit == LFS3_NAME_MAX); assert(fsinfo.file_limit == LFS3_FILE_MAX); @@ -869,7 +893,7 @@ code = ''' // try growing the filesystem struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; - assert(fsinfo.block_count >= INIT_BLOCK_COUNT); + assert(fsinfo.block_count >= FORMAT_BLOCK_COUNT); assert(fsinfo.block_count <= BLOCK_COUNT); lfs3_ssize_t used = lfs3_fs_usage(&lfs3); assert(used >= 0); @@ -946,7 +970,6 @@ code = ''' ''' [cases.test_grow_incr_spam_file_fuzz] -defines.INIT_BLOCK_COUNT = 2 defines.REMOUNT = [false, true] defines.N = [1, 2, 4, 8, 16, 32, 64] defines.OPS = 1024 @@ -965,9 +988,12 @@ if = '(SIZE*N)/BLOCK_SIZE <= 16' code = ''' // start with a small number of blocks struct lfs3_cfg cfg = *CFG; - cfg.block_count = INIT_BLOCK_COUNT; + cfg.block_count = FORMAT_BLOCK_COUNT; lfs3_t lfs3; - lfs3_format(&lfs3, LFS3_F_RDWR, &cfg) => 0; + lfs3_format(&lfs3, + LFS3_F_RDWR + | ((GBMAP) ? LFS3_IFDEF_GBMAP(LFS3_F_GBMAP, -1) : 0), + &cfg) => 0; // mount with maximum block count lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; @@ -975,7 +1001,7 @@ code = ''' struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(fsinfo.block_size == BLOCK_SIZE); - assert(fsinfo.block_count == INIT_BLOCK_COUNT); + assert(fsinfo.block_count == FORMAT_BLOCK_COUNT); assert(fsinfo.name_limit == LFS3_NAME_MAX); assert(fsinfo.file_limit == LFS3_FILE_MAX); @@ -1135,7 +1161,7 @@ code = ''' // try growing the filesystem struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; - assert(fsinfo.block_count >= INIT_BLOCK_COUNT); + assert(fsinfo.block_count >= FORMAT_BLOCK_COUNT); assert(fsinfo.block_count <= BLOCK_COUNT); lfs3_ssize_t used = lfs3_fs_usage(&lfs3); assert(used >= 0); @@ -1241,7 +1267,6 @@ code = ''' ''' [cases.test_grow_incr_spam_uz_fuzz] -defines.INIT_BLOCK_COUNT = 2 defines.N = [1, 2, 4, 8, 16, 32, 64] defines.OPS = 1024 defines.SIZE = [ @@ -1259,9 +1284,12 @@ if = '(SIZE*N)/BLOCK_SIZE <= 16' code = ''' // start with a small number of blocks struct lfs3_cfg cfg = *CFG; - cfg.block_count = INIT_BLOCK_COUNT; + cfg.block_count = FORMAT_BLOCK_COUNT; lfs3_t lfs3; - lfs3_format(&lfs3, LFS3_F_RDWR, &cfg) => 0; + lfs3_format(&lfs3, + LFS3_F_RDWR + | ((GBMAP) ? LFS3_IFDEF_GBMAP(LFS3_F_GBMAP, -1) : 0), + &cfg) => 0; // mount with maximum block count lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; @@ -1269,7 +1297,7 @@ code = ''' struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(fsinfo.block_size == BLOCK_SIZE); - assert(fsinfo.block_count == INIT_BLOCK_COUNT); + assert(fsinfo.block_count == FORMAT_BLOCK_COUNT); assert(fsinfo.name_limit == LFS3_NAME_MAX); assert(fsinfo.file_limit == LFS3_FILE_MAX); @@ -1616,7 +1644,7 @@ code = ''' // try growing the filesystem struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; - assert(fsinfo.block_count >= INIT_BLOCK_COUNT); + assert(fsinfo.block_count >= FORMAT_BLOCK_COUNT); assert(fsinfo.block_count <= BLOCK_COUNT); lfs3_ssize_t used = lfs3_fs_usage(&lfs3); assert(used >= 0); @@ -1741,7 +1769,6 @@ code = ''' ''' [cases.test_grow_incr_spam_uzd_fuzz] -defines.INIT_BLOCK_COUNT = 2 defines.N = [1, 2, 4, 8, 16, 32, 64] defines.OPS = 1024 defines.SIZE = [ @@ -1759,9 +1786,12 @@ if = '(SIZE*N)/BLOCK_SIZE <= 16' code = ''' // start with a small number of blocks struct lfs3_cfg cfg = *CFG; - cfg.block_count = INIT_BLOCK_COUNT; + cfg.block_count = FORMAT_BLOCK_COUNT; lfs3_t lfs3; - lfs3_format(&lfs3, LFS3_F_RDWR, &cfg) => 0; + lfs3_format(&lfs3, + LFS3_F_RDWR + | ((GBMAP) ? LFS3_IFDEF_GBMAP(LFS3_F_GBMAP, -1) : 0), + &cfg) => 0; // mount with maximum block count lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; @@ -1769,7 +1799,7 @@ code = ''' struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(fsinfo.block_size == BLOCK_SIZE); - assert(fsinfo.block_count == INIT_BLOCK_COUNT); + assert(fsinfo.block_count == FORMAT_BLOCK_COUNT); assert(fsinfo.name_limit == LFS3_NAME_MAX); assert(fsinfo.file_limit == LFS3_FILE_MAX); @@ -2200,7 +2230,7 @@ code = ''' // try growing the filesystem struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; - assert(fsinfo.block_count >= INIT_BLOCK_COUNT); + assert(fsinfo.block_count >= FORMAT_BLOCK_COUNT); assert(fsinfo.block_count <= BLOCK_COUNT); lfs3_ssize_t used = lfs3_fs_usage(&lfs3); assert(used >= 0); @@ -2350,7 +2380,6 @@ code = ''' # wrong. # [cases.test_grow_incr_spam_f_pl_fuzz] -defines.INIT_BLOCK_COUNT = 2 defines.N = [1, 2, 4, 8, 16, 32, 64] defines.OPS = 256 defines.SIZE = [ @@ -2373,8 +2402,11 @@ code = ''' if (err) { // start with a small number of blocks struct lfs3_cfg cfg = *CFG; - cfg.block_count = INIT_BLOCK_COUNT; - lfs3_format(&lfs3, LFS3_F_RDWR, &cfg) => 0; + cfg.block_count = FORMAT_BLOCK_COUNT; + lfs3_format(&lfs3, + LFS3_F_RDWR + | ((GBMAP) ? LFS3_IFDEF_GBMAP(LFS3_F_GBMAP, -1) : 0), + &cfg) => 0; // mount with maximum block count lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; @@ -2382,7 +2414,7 @@ code = ''' struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(fsinfo.block_size == BLOCK_SIZE); - assert(fsinfo.block_count == INIT_BLOCK_COUNT); + assert(fsinfo.block_count == FORMAT_BLOCK_COUNT); assert(fsinfo.name_limit == LFS3_NAME_MAX); assert(fsinfo.file_limit == LFS3_FILE_MAX); } @@ -2563,7 +2595,7 @@ code = ''' // try growing the filesystem struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; - assert(fsinfo.block_count >= INIT_BLOCK_COUNT); + assert(fsinfo.block_count >= FORMAT_BLOCK_COUNT); assert(fsinfo.block_count <= BLOCK_COUNT); lfs3_ssize_t used = lfs3_fs_usage(&lfs3); assert(used >= 0); @@ -2661,7 +2693,6 @@ code = ''' # wrong. # [cases.test_grow_incr_spam_fd_pl_fuzz] -defines.INIT_BLOCK_COUNT = 2 # note dirs x files grows O(n^2) defines.N = [1, 2, 4, 8] defines.M = 'N' @@ -2686,8 +2717,11 @@ code = ''' if (err) { // start with a small number of blocks struct lfs3_cfg cfg = *CFG; - cfg.block_count = INIT_BLOCK_COUNT; - lfs3_format(&lfs3, LFS3_F_RDWR, &cfg) => 0; + cfg.block_count = FORMAT_BLOCK_COUNT; + lfs3_format(&lfs3, + LFS3_F_RDWR + | ((GBMAP) ? LFS3_IFDEF_GBMAP(LFS3_F_GBMAP, -1) : 0), + &cfg) => 0; // mount with maximum block count lfs3_mount(&lfs3, LFS3_M_RDWR, CFG) => 0; @@ -2695,7 +2729,7 @@ code = ''' struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; assert(fsinfo.block_size == BLOCK_SIZE); - assert(fsinfo.block_count == INIT_BLOCK_COUNT); + assert(fsinfo.block_count == FORMAT_BLOCK_COUNT); assert(fsinfo.name_limit == LFS3_NAME_MAX); assert(fsinfo.file_limit == LFS3_FILE_MAX); } @@ -3003,7 +3037,7 @@ code = ''' // try growing the filesystem struct lfs3_fsinfo fsinfo; lfs3_fs_stat(&lfs3, &fsinfo) => 0; - assert(fsinfo.block_count >= INIT_BLOCK_COUNT); + assert(fsinfo.block_count >= FORMAT_BLOCK_COUNT); assert(fsinfo.block_count <= BLOCK_COUNT); lfs3_ssize_t used = lfs3_fs_usage(&lfs3); assert(used >= 0);