From 1b3054db89484f1e4485f5005a8c612ceaad22c3 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Mon, 6 Jan 2025 20:34:40 -0600 Subject: [PATCH] gc: Moved incremental gc behind ifdef LFS_GC Incremental gc, being stateful and not gc-able (ironic), was always going to need to be conditionally compilable. This moves incremental gc behind the LFS_GC define, so that we can focus on the "default" costs. This cuts lfs_t in nearly half! lfs_t with LFS_GC: 308 lfs_t without LFS_C: 168 (-45.5%) This does save less code than one might expect though. We still need most of the internal traversal/gc logic for things like block allocation and orphan cleanup, so most of the savings is limited to the RAM storing the incremental state: code stack ctx before: 37916 2608 768 after with LFS_CFG: 37944 (+0.1%) 2608 (+0.0%) 768 (+0.0%) after without LFS_CFG: 37796 (-0.3%) 2608 (+0.0%) 620 (-19.3%) On the flip side, this does mean most of the incremental gc functionality is still availables in the lfsr_traversal_t APIs. Applications with more advanced gc use-cases may actually benefit from _not_ enabling the incremental gc APIs, and instead use the lfsr_traversal_t APIs directly. --- lfs.c | 247 ++++++++++++++++++++++------------------- lfs.h | 13 ++- lfs_util.h | 6 + runners/bench_runner.h | 11 +- runners/test_runner.h | 13 ++- tests/test_attrs.toml | 9 ++ tests/test_ck.toml | 18 ++- tests/test_gc.toml | 28 ++++- 8 files changed, 220 insertions(+), 125 deletions(-) diff --git a/lfs.c b/lfs.c index fc5e09d9..3ff06466 100644 --- a/lfs.c +++ b/lfs.c @@ -13155,6 +13155,7 @@ static int lfs_init(lfs_t *lfs, uint32_t flags, // // wear-leveling. // LFS_ASSERT(lfs->cfg->block_cycles != 0); + #ifdef LFS_GC // unknown gc flags? LFS_ASSERT((lfs->cfg->gc_flags & ~( LFS_GC_MTREEONLY @@ -13163,6 +13164,7 @@ static int lfs_init(lfs_t *lfs, uint32_t flags, | LFS_GC_COMPACT | LFS_GC_CKMETA | LFS_GC_CKDATA)) == 0); + #endif // check that gc_compact_thresh makes sense // @@ -13361,6 +13363,7 @@ static int lfs_init(lfs_t *lfs, uint32_t flags, lfs_memset(lfs->grm_p, 0, LFSR_GRM_DSIZE); lfs_memset(lfs->grm_d, 0, LFSR_GRM_DSIZE); + #ifdef LFS_GC // setup gc state, this can be mutated which is why we need a copy if (lfs->cfg->gc_flags) { lfs->gc.flags = lfs->cfg->gc_flags; @@ -13374,6 +13377,7 @@ static int lfs_init(lfs_t *lfs, uint32_t flags, } else { lfs->gc.steps = 1; } + #endif return 0; @@ -13921,7 +13925,8 @@ static int lfsr_mountinited(lfs_t *lfs) { } // needed in lfsr_mount -static int lfsr_gc_(lfs_t *lfs, uint32_t flags, lfs_soff_t steps); +static int lfsr_fs_gc(lfs_t *lfs, lfsr_traversal_t *t, + uint32_t flags, lfs_soff_t steps); int lfsr_mount(lfs_t *lfs, uint32_t flags, const struct lfs_config *cfg) { @@ -13977,7 +13982,8 @@ int lfsr_mount(lfs_t *lfs, uint32_t flags, | LFS_M_COMPACT | LFS_M_CKMETA | LFS_M_CKDATA)) { - err = lfsr_gc_(lfs, + lfsr_traversal_t t; + err = lfsr_fs_gc(lfs, &t, flags & ( LFS_M_MTREEONLY | LFS_M_MKCONSISTENT @@ -14018,8 +14024,10 @@ int lfsr_unmount(lfs_t *lfs) { // all files/dirs should be closed before lfsr_unmount LFS_ASSERT(lfs->omdirs == NULL // special case for our gc traversal handle - || (lfs->omdirs == &lfs->gc.t.o.o - && lfs->gc.t.o.o.next == NULL)); + || LFS_IFDEF_GC( + (lfs->omdirs == &lfs->gc.t.o.o + && lfs->gc.t.o.o.next == NULL), + false)); return lfs_deinit(lfs); } @@ -14153,7 +14161,8 @@ int lfsr_format(lfs_t *lfs, uint32_t flags, | LFS_F_COMPACT | LFS_F_CKMETA | LFS_F_CKDATA)) { - err = lfsr_gc_(lfs, + lfsr_traversal_t t; + err = lfsr_fs_gc(lfs, &t, flags & ( LFS_F_MTREEONLY | LFS_F_COMPACT @@ -14405,6 +14414,118 @@ int lfsr_fs_ckdata(lfs_t *lfs) { return lfsr_fs_ck(lfs, LFS_T_CKMETA | LFS_T_CKDATA); } +// low-level filesystem gc +// +// runs the traversal until all work is completed, which may take +// multiple passes +static int lfsr_fs_gc(lfs_t *lfs, lfsr_traversal_t *t, + uint32_t flags, lfs_soff_t steps) { + // unknown gc flags? + // + // we should have check these earlier, but it doesn't hurt to + // double check + LFS_ASSERT((flags & ~( + LFS_GC_MTREEONLY + | LFS_GC_MKCONSISTENT + | LFS_GC_LOOKAHEAD + | LFS_GC_COMPACT + | LFS_GC_CKMETA + | LFS_GC_CKDATA)) == 0); + // these flags require a writable filesystem + LFS_ASSERT(!lfsr_m_isrdonly(lfs->flags) || !lfsr_t_ismkconsistent(flags)); + LFS_ASSERT(!lfsr_m_isrdonly(lfs->flags) || !lfsr_t_islookahead(flags)); + LFS_ASSERT(!lfsr_m_isrdonly(lfs->flags) || !lfsr_t_iscompact(flags)); + // 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_isckdata(flags)); + + // fix pending grms if requested + if (lfsr_t_ismkconsistent(flags) + && lfsr_grm_count(lfs) > 0) { + int err = lfsr_fs_fixgrm(lfs); + if (err) { + return err; + } + } + + // do we have any pending work? + uint32_t pending = flags & ( + (lfs->flags & ( + LFS_I_UNTIDY + | LFS_I_UNCOMPACTED)) + | ((lfsr_fs_canlookahead(lfs)) ? LFS_GC_LOOKAHEAD : 0) + | LFS_GC_CKMETA + | LFS_GC_CKDATA); + + while (pending && (lfs_off_t)steps > 0) { + // checkpoint the allocator to maximize any lookahead scans + lfs_alloc_ckpoint(lfs); + + // start a new traversal? + if (!lfsr_omdir_isopen(lfs, &t->o.o)) { + lfsr_traversal_init(t, pending); + lfsr_omdir_open(lfs, &t->o.o); + } + + // don't bother with lookahead if we've mutated + if (lfsr_t_isdirty(t->o.o.flags) + || lfsr_t_ismutated(t->o.o.flags)) { + t->o.o.flags &= ~LFS_GC_LOOKAHEAD; + } + + // will this traversal still make progress? no? start over + if (!(t->o.o.flags & ( + LFS_GC_MKCONSISTENT + | LFS_GC_LOOKAHEAD + | LFS_GC_COMPACT + | LFS_GC_CKMETA + | LFS_GC_CKDATA))) { + lfsr_omdir_close(lfs, &t->o.o); + continue; + } + + // do we really need a full traversal? + if (!(t->o.o.flags & ( + LFS_GC_LOOKAHEAD + | LFS_GC_CKMETA + | LFS_GC_CKDATA))) { + t->o.o.flags |= LFS_T_MTREEONLY; + } + + // progress gc + int err = lfsr_mtree_gc(lfs, t, + NULL, NULL); + if (err && err != LFS_ERR_NOENT) { + return err; + } + + // end of traversal? + if (err == LFS_ERR_NOENT) { + lfsr_omdir_close(lfs, &t->o.o); + + // clear any pending flags we make progress on + pending &= ( + (lfs->flags & ( + LFS_I_UNTIDY + | LFS_I_UNCOMPACTED)) + | ((lfsr_fs_canlookahead(lfs)) ? LFS_GC_LOOKAHEAD : 0) + // only consider our filesystem checked if we + // weren't mutated + | ((lfsr_t_isdirty(t->o.o.flags) + || lfsr_t_ismutated(t->o.o.flags)) + ? LFS_GC_CKMETA | LFS_GC_CKDATA + : 0)); + } + + // decrement steps + if (steps > 0) { + steps -= 1; + } + } + + return 0; +} + // attempt to grow the filesystem int lfsr_fs_grow(lfs_t *lfs, lfs_size_t block_count_) { @@ -14638,6 +14759,7 @@ int lfsr_traversal_rewind(lfs_t *lfs, lfsr_traversal_t *t) { /// Incremental gc operations /// +#ifdef LFS_GC int lfsr_gc_setflags(lfs_t *lfs, uint32_t flags) { // unknown gc flags? LFS_ASSERT((flags & ~( @@ -14656,123 +14778,22 @@ int lfsr_gc_setflags(lfs_t *lfs, uint32_t flags) { lfs->gc.flags = flags; return 0; } +#endif +#ifdef LFS_GC int lfsr_gc_setsteps(lfs_t *lfs, lfs_soff_t steps) { lfs->gc.steps = steps; return 0; } +#endif +#ifdef LFS_GC // perform any pending janitorial work -static int lfsr_gc_(lfs_t *lfs, uint32_t flags, lfs_soff_t steps) { - // unknown gc flags? - // - // we should have check these earlier, but it doesn't hurt to - // double check - LFS_ASSERT((flags & ~( - LFS_GC_MTREEONLY - | LFS_GC_MKCONSISTENT - | LFS_GC_LOOKAHEAD - | LFS_GC_COMPACT - | LFS_GC_CKMETA - | LFS_GC_CKDATA)) == 0); - // these flags require a writable filesystem - LFS_ASSERT(!lfsr_m_isrdonly(lfs->flags) || !lfsr_t_ismkconsistent(flags)); - LFS_ASSERT(!lfsr_m_isrdonly(lfs->flags) || !lfsr_t_islookahead(flags)); - LFS_ASSERT(!lfsr_m_isrdonly(lfs->flags) || !lfsr_t_iscompact(flags)); - // 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_isckdata(flags)); - - // fix pending grms if requested - if (lfsr_t_ismkconsistent(flags) - && lfsr_grm_count(lfs) > 0) { - int err = lfsr_fs_fixgrm(lfs); - if (err) { - return err; - } - } - - // do we have any pending work? - uint32_t pending = flags & ( - (lfs->flags & ( - LFS_I_UNTIDY - | LFS_I_UNCOMPACTED)) - | ((lfsr_fs_canlookahead(lfs)) ? LFS_GC_LOOKAHEAD : 0) - | LFS_GC_CKMETA - | LFS_GC_CKDATA); - - while (pending && (lfs_off_t)steps > 0) { - // checkpoint the allocator to maximize any lookahead scans - lfs_alloc_ckpoint(lfs); - - // start a new traversal? - if (!lfsr_omdir_isopen(lfs, &lfs->gc.t.o.o)) { - lfsr_traversal_init(&lfs->gc.t, pending); - lfsr_omdir_open(lfs, &lfs->gc.t.o.o); - } - - // don't bother with lookahead if we've mutated - if (lfsr_t_isdirty(lfs->gc.t.o.o.flags) - || lfsr_t_ismutated(lfs->gc.t.o.o.flags)) { - lfs->gc.t.o.o.flags &= ~LFS_GC_LOOKAHEAD; - } - - // will this traversal still make progress? no? start over - if (!(lfs->gc.t.o.o.flags & ( - LFS_GC_MKCONSISTENT - | LFS_GC_LOOKAHEAD - | LFS_GC_COMPACT - | LFS_GC_CKMETA - | LFS_GC_CKDATA))) { - lfsr_omdir_close(lfs, &lfs->gc.t.o.o); - continue; - } - - // do we really need a full traversal? - if (!(lfs->gc.t.o.o.flags & ( - LFS_GC_LOOKAHEAD - | LFS_GC_CKMETA - | LFS_GC_CKDATA))) { - lfs->gc.t.o.o.flags |= LFS_T_MTREEONLY; - } - - // progress gc - int err = lfsr_mtree_gc(lfs, &lfs->gc.t, - NULL, NULL); - if (err && err != LFS_ERR_NOENT) { - return err; - } - - // end of traversal? - if (err == LFS_ERR_NOENT) { - lfsr_omdir_close(lfs, &lfs->gc.t.o.o); - - // clear any pending flags we make progress on - pending &= ( - (lfs->flags & ( - LFS_I_UNTIDY - | LFS_I_UNCOMPACTED)) - | ((lfsr_fs_canlookahead(lfs)) ? LFS_GC_LOOKAHEAD : 0) - // only consider our filesystem checked if we - // weren't mutated - | ((lfsr_t_isdirty(lfs->gc.t.o.o.flags) - || lfsr_t_ismutated(lfs->gc.t.o.o.flags)) - ? LFS_GC_CKMETA | LFS_GC_CKDATA - : 0)); - } - - // decrement steps - if (steps > 0) { - steps -= 1; - } - } - - return 0; -} - int lfsr_gc(lfs_t *lfs) { - return lfsr_gc_(lfs, lfs->gc.flags, lfs->gc.steps); + return lfsr_fs_gc(lfs, &lfs->gc.t, + lfs->gc.flags, lfs->gc.steps); } +#endif diff --git a/lfs.h b/lfs.h index f36c4ef3..8f0608c7 100644 --- a/lfs.h +++ b/lfs.h @@ -352,12 +352,15 @@ struct lfs_config { // can track 8 blocks. lfs_size_t lookahead_size; + #ifdef LFS_GC // Flags indicating what gc work to do during lfsr_gc calls. // // Defaults to LFS_GC_MKCONSISTENT + LFS_GC_LOOKAHEAD + // LFS_GC_COMPACT when zero. uint32_t gc_flags; + #endif + #ifdef LFS_GC // Number of gc steps to perform in each call to lfsr_gc, with each // step being ~1 block of work. // @@ -369,6 +372,7 @@ struct lfs_config { // // Defaults to steps=1 when zero. lfs_soff_t gc_steps; + #endif // Threshold for metadata compaction during gc in bytes. Metadata logs // that exceed this threshold will be compacted during gc operations. @@ -879,12 +883,13 @@ typedef struct lfs { uint8_t grm_p[LFSR_GRM_DSIZE]; uint8_t grm_d[LFSR_GRM_DSIZE]; - // TODO allow compile time opt-out to reclaim RAM + #ifdef LFS_GC struct { uint32_t flags; lfs_soff_t steps; lfsr_traversal_t t; } gc; + #endif } lfs_t; @@ -1253,7 +1258,7 @@ int lfsr_traversal_rewind(lfs_t *lfs, lfsr_traversal_t *t); /// Incremental gc operations /// -#ifndef LFS_READONLY +#ifdef LFS_GC // Perform any janitorial work that may be pending. // // The exact janitorial work depends on the configured flags and steps. @@ -1265,14 +1270,14 @@ int lfsr_traversal_rewind(lfs_t *lfs, lfsr_traversal_t *t); int lfsr_gc(lfs_t *lfs); #endif -#ifndef LFS_READONLY +#ifdef LFS_GC // Sets the gc flags. // // Returns a negative error code on failure. int lfsr_gc_setflags(lfs_t *lfs, uint32_t flags); #endif -#ifndef LFS_READONLY +#ifdef LFS_GC // Sets the number of gc steps per lfsr_gc call, with each step being // ~1 block of work. // diff --git a/lfs_util.h b/lfs_util.h index 45c48343..55c44da7 100644 --- a/lfs_util.h +++ b/lfs_util.h @@ -162,6 +162,12 @@ extern "C" #define LFS_IFDEF_CKDATACKSUMS(a, b) (b) #endif +#ifdef LFS_GC +#define LFS_IFDEF_GC(a, b) (a) +#else +#define LFS_IFDEF_GC(a, b) (b) +#endif + // Builtin functions, these may be replaced by more efficient // toolchain-specific implementations. LFS_NO_BUILTINS falls back to a more diff --git a/runners/bench_runner.h b/runners/bench_runner.h index 3b925b56..70abedcd 100644 --- a/runners/bench_runner.h +++ b/runners/bench_runner.h @@ -145,14 +145,21 @@ void bench_permutation(size_t i, uint32_t *buffer, size_t size); .pcache_size = PCACHE_SIZE, \ .file_buffer_size = FILE_BUFFER_SIZE, \ .lookahead_size = LOOKAHEAD_SIZE, \ - .gc_flags = GC_FLAGS, \ - .gc_steps = GC_STEPS, \ + BENCH_GC_CFG \ .gc_compact_thresh = GC_COMPACT_THRESH, \ .inline_size = INLINE_SIZE, \ .shrub_size = SHRUB_SIZE, \ .fragment_size = FRAGMENT_SIZE, \ .crystal_thresh = CRYSTAL_THRESH, +#ifdef LFS_GC +#define BENCH_GC_CFG \ + .gc_flags = GC_FLAGS, \ + .gc_steps = GC_STEPS, +#else +#define BENCH_GC_CFG +#endif + #define BENCH_BDCFG \ .erase_value = ERASE_VALUE, \ .erase_cycles = ERASE_CYCLES, \ diff --git a/runners/test_runner.h b/runners/test_runner.h index 97c5eef7..5ce87e10 100644 --- a/runners/test_runner.h +++ b/runners/test_runner.h @@ -136,13 +136,20 @@ void test_permutation(size_t i, uint32_t *buffer, size_t size); .pcache_size = PCACHE_SIZE, \ .file_buffer_size = FILE_BUFFER_SIZE, \ .lookahead_size = LOOKAHEAD_SIZE, \ - .gc_flags = GC_FLAGS, \ - .gc_steps = GC_STEPS, \ + TEST_GC_CFG \ .gc_compact_thresh = GC_COMPACT_THRESH, \ .inline_size = INLINE_SIZE, \ .shrub_size = SHRUB_SIZE, \ .fragment_size = FRAGMENT_SIZE, \ - .crystal_thresh = CRYSTAL_THRESH, + .crystal_thresh = CRYSTAL_THRESH + +#ifdef LFS_GC +#define TEST_GC_CFG \ + .gc_flags = GC_FLAGS, \ + .gc_steps = GC_STEPS, +#else +#define TEST_GC_CFG +#endif #define TEST_BDCFG \ .erase_value = ERASE_VALUE, \ diff --git a/tests/test_attrs.toml b/tests/test_attrs.toml index 382988b2..94517a13 100644 --- a/tests/test_attrs.toml +++ b/tests/test_attrs.toml @@ -493,6 +493,7 @@ defines.COMPACT = [false, true] defines.GC_FLAGS = 'LFS_GC_COMPACT' defines.GC_STEPS = -1 defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2' +if = 'LFS_IFDEF_GC(true, !COMPACT)' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -528,9 +529,11 @@ code = ''' } // try compacting? + #ifdef LFS_GC if (COMPACT) { lfsr_gc(&lfs) => 0; } + #endif for (int remount = 0; remount < 2; remount++) { // remount? @@ -572,6 +575,7 @@ defines.COMPACT = [false, true] defines.GC_FLAGS = 'LFS_GC_COMPACT' defines.GC_STEPS = -1 defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2' +if = 'LFS_IFDEF_GC(true, !COMPACT)' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -608,9 +612,11 @@ code = ''' } // try compacting? + #ifdef LFS_GC if (COMPACT) { lfsr_gc(&lfs) => 0; } + #endif for (int remount = 0; remount < 2; remount++) { // remount? @@ -4074,6 +4080,7 @@ defines.COMPACT = [false, true] defines.GC_FLAGS = 'LFS_GC_COMPACT' defines.GC_STEPS = -1 defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2' +if = 'LFS_IFDEF_GC(true, !COMPACT)' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -4110,9 +4117,11 @@ code = ''' } // try compacting? + #ifdef LFS_GC if (COMPACT) { lfsr_gc(&lfs) => 0; } + #endif for (int remount = 0; remount < 2; remount++) { // remount? diff --git a/tests/test_ck.toml b/tests/test_ck.toml index b1ed4d2c..5e5b9a0a 100644 --- a/tests/test_ck.toml +++ b/tests/test_ck.toml @@ -24,7 +24,10 @@ defines.SIZE = [ '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] -if = '(SIZE*N)/BLOCK_SIZE <= 32' +if = [ + '(SIZE*N)/BLOCK_SIZE <= 32', + 'LFS_IFDEF_GC(true, METHOD != 1)', +] code = ''' lfs_block_t i = 0; while (true) { @@ -98,7 +101,11 @@ code = ''' // find clobbered blocks with lfsr_gc } else if (METHOD == 1) { + #ifdef LFS_GC lfsr_gc(&lfs) => LFS_ERR_CORRUPT; + #else + LFS_UNREACHABLE(); + #endif // find clobbered blocks with lfsr_traversal_read } else if (METHOD == 2) { @@ -154,7 +161,10 @@ defines.SIZE = [ '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] -if = '(SIZE*N)/BLOCK_SIZE <= 32' +if = [ + '(SIZE*N)/BLOCK_SIZE <= 32', + 'LFS_IFDEF_GC(true, METHOD != 1)', +] code = ''' lfs_block_t i = 0; while (true) { @@ -229,7 +239,11 @@ code = ''' // find clobbered blocks with lfsr_gc } else if (METHOD == 1) { + #ifdef LFS_GC lfsr_gc(&lfs) => LFS_ERR_CORRUPT; + #else + LFS_UNREACHABLE(); + #endif // find clobbered blocks with lfsr_traversal_read } else if (METHOD == 2) { diff --git a/tests/test_gc.toml b/tests/test_gc.toml index 0353dd16..03866834 100644 --- a/tests/test_gc.toml +++ b/tests/test_gc.toml @@ -22,6 +22,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] +ifdef = 'LFS_GC' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -85,6 +86,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] +ifdef = 'LFS_GC' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -153,6 +155,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] +ifdef = 'LFS_GC' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -216,6 +219,7 @@ defines.SIZE = [ ] # we need something to keep the traversal running if = 'CKMETA || CKDATA' +ifdef = 'LFS_GC' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -290,6 +294,7 @@ defines.SIZE = [ ] # we need something to keep the traversal running if = 'CKMETA || CKDATA' +ifdef = 'LFS_GC' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -358,6 +363,7 @@ defines.SIZE = [ ] # we need something to keep the traversal running if = 'CKMETA || CKDATA' +ifdef = 'LFS_GC' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -430,6 +436,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] +ifdef = 'LFS_GC' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -518,6 +525,7 @@ defines.SIZE = [ ] # we need something to keep the traversal running if = 'CKMETA || CKDATA' +ifdef = 'LFS_GC' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -618,6 +626,7 @@ defines.SIZE = [ ] # we need something to keep the traversal running if = 'CKMETA || CKDATA' +ifdef = 'LFS_GC' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -713,6 +722,7 @@ defines.SIZE = [ ] # we need something to keep the traversal running if = 'CKMETA || CKDATA' +ifdef = 'LFS_GC' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -804,6 +814,7 @@ defines.SIZE = 'FILE_BUFFER_SIZE/2' # <=2 => grm-able # >2 => requires orphans defines.ORPHANS = [1, 2, 3, 100] +ifdef = 'LFS_GC' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -953,7 +964,9 @@ code = ''' struct lfs_fsinfo fsinfo; lfsr_fs_stat(&lfs, &fsinfo) => 0; assert(fsinfo.flags & LFS_I_INCONSISTENT); + #ifdef LFS_GC assert(lfs.omdirs != &lfs.gc.t.o.o); + #endif // call lfsr_fs_mkconsistent lfsr_fs_mkconsistent(&lfs) => 0; @@ -1008,6 +1021,7 @@ defines.SIZE = 'FILE_BUFFER_SIZE/2' defines.ORPHANS = [3, 100] # we need something to keep the traversal running if = 'CKMETA || CKDATA' +ifdef = 'LFS_GC' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -1123,7 +1137,7 @@ defines.SIZE = 'FILE_BUFFER_SIZE/2' defines.ORPHANS = [3, 100] # we need something to keep the traversal running if = 'CKMETA || CKDATA' -in = 'lfs.c' +ifdef = 'LFS_GC' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -1237,6 +1251,7 @@ defines.SIZE = 'FILE_BUFFER_SIZE/2' defines.ORPHANS = [3, 100] # we need something to keep the traversal running if = 'CKMETA || CKDATA' +ifdef = 'LFS_GC' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -1349,6 +1364,7 @@ defines.SIZE = [ '8*BLOCK_SIZE', ] if = '(SIZE*N)/BLOCK_SIZE <= 32' +ifdef = 'LFS_GC' code = ''' lfs_block_t i = 0; while (true) { @@ -1448,6 +1464,7 @@ defines.SIZE = [ '8*BLOCK_SIZE', ] if = '(SIZE*N)/BLOCK_SIZE <= 32' +ifdef = 'LFS_GC' code = ''' lfs_block_t i = 0; while (true) { @@ -1740,6 +1757,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] +ifdef = 'LFS_GC' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -1808,6 +1826,7 @@ defines.SIZE = [ '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] +ifdef = 'LFS_GC' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -1876,6 +1895,7 @@ defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] # set compact thresh to minimum defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2' defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256] +ifdef = 'LFS_GC' code = ''' // test creating directories lfs_t lfs; @@ -1976,6 +1996,7 @@ defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256] defines.OPS = '2*N' defines.SEED = 42 fuzz = 'SEED' +ifdef = 'LFS_GC' code = ''' // test fuzz with dirs lfs_t lfs; @@ -2151,6 +2172,7 @@ defines.SIZE = [ '4*BLOCK_SIZE', ] if = '(SIZE*N)/BLOCK_SIZE <= 32' +ifdef = 'LFS_GC' code = ''' // test creating files lfs_t lfs; @@ -2245,6 +2267,7 @@ defines.SIZE = [ defines.SEED = 42 fuzz = 'SEED' if = '(SIZE*N)/BLOCK_SIZE <= 16' +ifdef = 'LFS_GC' code = ''' // test fuzz with files lfs_t lfs; @@ -2484,6 +2507,7 @@ if = [ # this just saves testing time 'SIZE <= 4*1024*FRAGMENT_SIZE', ] +ifdef = 'LFS_GC' code = ''' // test with complex file writes lfs_t lfs; @@ -2625,6 +2649,7 @@ defines.SIZE = [ defines.SEED = 42 fuzz = 'SEED' if = '(SIZE*N)/BLOCK_SIZE <= 16' +ifdef = 'LFS_GC' code = ''' // test with uncreats, zombies, etc lfs_t lfs; @@ -2983,6 +3008,7 @@ defines.SIZE = [ defines.SEED = 42 fuzz = 'SEED' if = '(SIZE*N)/BLOCK_SIZE <= 16' +ifdef = 'LFS_GC' code = ''' // test with uncreats, zombies, dirs, etc lfs_t lfs;