diff --git a/lfs.c b/lfs.c index 2e2c9eb1..fc5e09d9 100644 --- a/lfs.c +++ b/lfs.c @@ -8733,7 +8733,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, } // we may have touched any number of mdirs, so assume uncompacted - // until lfsr_fs_gc can prove otherwise + // until lfsr_gc can prove otherwise lfs->flags |= LFS_I_UNCOMPACTED; // update any gstate changes @@ -13155,6 +13155,15 @@ static int lfs_init(lfs_t *lfs, uint32_t flags, // // wear-leveling. // LFS_ASSERT(lfs->cfg->block_cycles != 0); + // unknown gc flags? + LFS_ASSERT((lfs->cfg->gc_flags & ~( + LFS_GC_MTREEONLY + | LFS_GC_MKCONSISTENT + | LFS_GC_LOOKAHEAD + | LFS_GC_COMPACT + | LFS_GC_CKMETA + | LFS_GC_CKDATA)) == 0); + // check that gc_compact_thresh makes sense // // metadata can't be compacted below block_size/2, and metadata can't @@ -13176,7 +13185,7 @@ static int lfs_init(lfs_t *lfs, uint32_t flags, // assume we may contain orphans until proven otherwise | LFS_I_UNTIDY // default to assuming we need compaction somewhere, worst case - // this just makes lfsr_fs_gc read more than is strictly needed + // this just makes lfsr_gc read more than is strictly needed | LFS_I_UNCOMPACTED; // copy block_count so we can mutate it @@ -13352,6 +13361,20 @@ 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); + // 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; + } else { + lfs->gc.flags = LFS_GC_MKCONSISTENT + | LFS_GC_LOOKAHEAD + | LFS_GC_COMPACT; + } + if (lfs->cfg->gc_steps) { + lfs->gc.steps = lfs->cfg->gc_steps; + } else { + lfs->gc.steps = 1; + } + return 0; failed:; @@ -13897,6 +13920,9 @@ static int lfsr_mountinited(lfs_t *lfs) { return 0; } +// needed in lfsr_mount +static int lfsr_gc_(lfs_t *lfs, uint32_t flags, lfs_soff_t steps); + int lfsr_mount(lfs_t *lfs, uint32_t flags, const struct lfs_config *cfg) { // unknown flags? @@ -13951,14 +13977,15 @@ int lfsr_mount(lfs_t *lfs, uint32_t flags, | LFS_M_COMPACT | LFS_M_CKMETA | LFS_M_CKDATA)) { - err = lfsr_fs_gc(lfs, -1, + err = lfsr_gc_(lfs, flags & ( LFS_M_MTREEONLY | LFS_M_MKCONSISTENT | LFS_M_LOOKAHEAD | LFS_M_COMPACT | LFS_M_CKMETA - | LFS_M_CKDATA)); + | LFS_M_CKDATA), + -1); if (err) { goto failed; } @@ -13990,8 +14017,9 @@ failed:; int lfsr_unmount(lfs_t *lfs) { // all files/dirs should be closed before lfsr_unmount LFS_ASSERT(lfs->omdirs == NULL - || (lfs->omdirs == &lfs->gc.o.o - && lfs->gc.o.o.next == NULL)); + // special case for our gc traversal handle + || (lfs->omdirs == &lfs->gc.t.o.o + && lfs->gc.t.o.o.next == NULL)); return lfs_deinit(lfs); } @@ -14125,12 +14153,13 @@ int lfsr_format(lfs_t *lfs, uint32_t flags, | LFS_F_COMPACT | LFS_F_CKMETA | LFS_F_CKDATA)) { - err = lfsr_fs_gc(lfs, -1, + err = lfsr_gc_(lfs, flags & ( LFS_F_MTREEONLY | LFS_F_COMPACT | LFS_F_CKMETA - | LFS_F_CKDATA)); + | LFS_F_CKDATA), + -1); if (err) { goto failed; } @@ -14209,6 +14238,18 @@ lfs_ssize_t lfsr_fs_size(lfs_t *lfs) { // consistency stuff static int lfsr_fs_fixgrm(lfs_t *lfs) { + if (lfsr_grm_count(lfs) == 2) { + LFS_DEBUG("Fixing grm %"PRId32".%"PRId32" %"PRId32".%"PRId32, + lfsr_mid_bid(lfs, lfs->grm.mids[0]) >> lfs->mdir_bits, + lfsr_mid_rid(lfs, lfs->grm.mids[0]), + lfsr_mid_bid(lfs, lfs->grm.mids[1]) >> lfs->mdir_bits, + lfsr_mid_rid(lfs, lfs->grm.mids[1])); + } else if (lfsr_grm_count(lfs) == 1) { + LFS_DEBUG("Fixing grm %"PRId32".%"PRId32, + lfsr_mid_bid(lfs, lfs->grm.mids[0]) >> lfs->mdir_bits, + lfsr_mid_rid(lfs, lfs->grm.mids[0])); + } + while (lfsr_grm_count(lfs) > 0) { LFS_ASSERT(lfs->grm.mids[0] != -1); @@ -14316,18 +14357,6 @@ int lfsr_fs_mkconsistent(lfs_t *lfs) { // fix pending grms if (lfsr_grm_count(lfs) > 0) { - if (lfsr_grm_count(lfs) == 2) { - LFS_DEBUG("Fixing grm %"PRId32".%"PRId32" %"PRId32".%"PRId32, - lfsr_mid_bid(lfs, lfs->grm.mids[0]) >> lfs->mdir_bits, - lfsr_mid_rid(lfs, lfs->grm.mids[0]), - lfsr_mid_bid(lfs, lfs->grm.mids[1]) >> lfs->mdir_bits, - lfsr_mid_rid(lfs, lfs->grm.mids[1])); - } else if (lfsr_grm_count(lfs) == 1) { - LFS_DEBUG("Fixing grm %"PRId32".%"PRId32, - lfsr_mid_bid(lfs, lfs->grm.mids[0]) >> lfs->mdir_bits, - lfsr_mid_rid(lfs, lfs->grm.mids[0])); - } - int err = lfsr_fs_fixgrm(lfs); if (err) { return err; @@ -14376,134 +14405,8 @@ int lfsr_fs_ckdata(lfs_t *lfs) { return lfsr_fs_ck(lfs, LFS_T_CKMETA | LFS_T_CKDATA); } -// perform any pending janitorial work -int lfsr_fs_gc(lfs_t *lfs, lfs_soff_t steps, uint32_t flags) { - // unknown flags? - 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) { - if (lfsr_grm_count(lfs) == 2) { - LFS_DEBUG("Fixing grm %"PRId32".%"PRId32" %"PRId32".%"PRId32, - lfsr_mid_bid(lfs, lfs->grm.mids[0]) >> lfs->mdir_bits, - lfsr_mid_rid(lfs, lfs->grm.mids[0]), - lfsr_mid_bid(lfs, lfs->grm.mids[1]) >> lfs->mdir_bits, - lfsr_mid_rid(lfs, lfs->grm.mids[1])); - } else if (lfsr_grm_count(lfs) == 1) { - LFS_DEBUG("Fixing grm %"PRId32".%"PRId32, - lfsr_mid_bid(lfs, lfs->grm.mids[0]) >> lfs->mdir_bits, - lfsr_mid_rid(lfs, lfs->grm.mids[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.o.o)) { - lfsr_traversal_init(&lfs->gc, pending); - lfsr_omdir_open(lfs, &lfs->gc.o.o); - } - - // mask flags, we can't trust existing traversals to make - // progress if flags change - lfs->gc.o.o.flags &= ( - pending | ~( - LFS_GC_MKCONSISTENT - | LFS_GC_LOOKAHEAD - | LFS_GC_COMPACT - | LFS_GC_CKMETA - | LFS_GC_CKDATA)); - - // don't bother with lookahead if we've mutated - if (lfsr_t_isdirty(lfs->gc.o.o.flags) - || lfsr_t_ismutated(lfs->gc.o.o.flags)) { - lfs->gc.o.o.flags &= ~LFS_GC_LOOKAHEAD; - } - - // will this traversal still make progress? no? start over - if (!(lfs->gc.o.o.flags & ( - LFS_GC_MKCONSISTENT - | LFS_GC_LOOKAHEAD - | LFS_GC_COMPACT - | LFS_GC_CKMETA - | LFS_GC_CKDATA))) { - lfsr_omdir_close(lfs, &lfs->gc.o.o); - continue; - } - - // do we really need a full traversal? - if (!(lfs->gc.o.o.flags & ( - LFS_GC_LOOKAHEAD - | LFS_GC_CKMETA - | LFS_GC_CKDATA))) { - lfs->gc.o.o.flags |= LFS_T_MTREEONLY; - } - - // progress gc - int err = lfsr_mtree_gc(lfs, &lfs->gc, - NULL, NULL); - if (err && err != LFS_ERR_NOENT) { - return err; - } - - // end of traversal? - if (err == LFS_ERR_NOENT) { - lfsr_omdir_close(lfs, &lfs->gc.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.o.o.flags) - || lfsr_t_ismutated(lfs->gc.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_) { // filesystem must be writeable LFS_ASSERT(!lfsr_m_isrdonly(lfs->flags)); @@ -14564,7 +14467,6 @@ failed:; } - /// High-level filesystem traversal /// // needed in lfsr_traversal_open @@ -14619,18 +14521,6 @@ int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *t, // operation introduced new grms if (lfsr_t_ismkconsistent(t->o.o.flags) && lfsr_grm_count(lfs) > 0) { - if (lfsr_grm_count(lfs) == 2) { - LFS_DEBUG("Fixing grm %"PRId32".%"PRId32" %"PRId32".%"PRId32, - lfsr_mid_bid(lfs, lfs->grm.mids[0]) >> lfs->mdir_bits, - lfsr_mid_rid(lfs, lfs->grm.mids[0]), - lfsr_mid_bid(lfs, lfs->grm.mids[1]) >> lfs->mdir_bits, - lfsr_mid_rid(lfs, lfs->grm.mids[1])); - } else if (lfsr_grm_count(lfs) == 1) { - LFS_DEBUG("Fixing grm %"PRId32".%"PRId32, - lfsr_mid_bid(lfs, lfs->grm.mids[0]) >> lfs->mdir_bits, - lfsr_mid_rid(lfs, lfs->grm.mids[0])); - } - // swap dirty/mutated flags while mutating t->o.o.flags = lfsr_t_swapdirty(t->o.o.flags); @@ -14746,6 +14636,143 @@ int lfsr_traversal_rewind(lfs_t *lfs, lfsr_traversal_t *t) { +/// Incremental gc operations /// + +int lfsr_gc_setflags(lfs_t *lfs, uint32_t flags) { + // unknown gc flags? + LFS_ASSERT((flags & ~( + LFS_GC_MTREEONLY + | LFS_GC_MKCONSISTENT + | LFS_GC_LOOKAHEAD + | LFS_GC_COMPACT + | LFS_GC_CKMETA + | LFS_GC_CKDATA)) == 0); + + // clobber any existing traversals + if (lfsr_omdir_isopen(lfs, &lfs->gc.t.o.o)) { + lfsr_omdir_close(lfs, &lfs->gc.t.o.o); + } + + lfs->gc.flags = flags; + return 0; +} + +int lfsr_gc_setsteps(lfs_t *lfs, lfs_soff_t steps) { + lfs->gc.steps = steps; + return 0; +} + +// 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); +} diff --git a/lfs.h b/lfs.h index 6afdae24..f36c4ef3 100644 --- a/lfs.h +++ b/lfs.h @@ -352,6 +352,24 @@ struct lfs_config { // can track 8 blocks. lfs_size_t lookahead_size; + // 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; + + // Number of gc steps to perform in each call to lfsr_gc, with each + // step being ~1 block of work. + // + // More steps per call will make more progress if interleaved with + // other filesystem operations, but may also introduce more latency. + // steps=1 will do the minimum amount of work to make progress, and + // steps=-1 will not return until all pending janitorial work has + // been completed. + // + // Defaults to steps=1 when zero. + lfs_soff_t gc_steps; + // Threshold for metadata compaction during gc in bytes. Metadata logs // that exceed this threshold will be compacted during gc operations. // Defaults to ~88% block_size when zero, though this default may change @@ -862,7 +880,11 @@ typedef struct lfs { uint8_t grm_d[LFSR_GRM_DSIZE]; // TODO allow compile time opt-out to reclaim RAM - lfsr_traversal_t gc; + struct { + uint32_t flags; + lfs_soff_t steps; + lfsr_traversal_t t; + } gc; } lfs_t; @@ -1229,6 +1251,42 @@ int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *t, int lfsr_traversal_rewind(lfs_t *lfs, lfsr_traversal_t *t); +/// Incremental gc operations /// + +#ifndef LFS_READONLY +// Perform any janitorial work that may be pending. +// +// The exact janitorial work depends on the configured flags and steps. +// +// Calling this function is not required, but may allow the offloading of +// expensive janitorial work to a less time-critical code path. +// +// Returns a negative error code on failure. +int lfsr_gc(lfs_t *lfs); +#endif + +#ifndef LFS_READONLY +// 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 +// Sets the number of gc steps per lfsr_gc call, with each step being +// ~1 block of work. +// +// More steps per call will make more progress if interleaved with +// other filesystem operations, but may also introduce more latency. +// steps=1 will do the minimum amount of work to make progress, and +// steps=-1 will not return until all pending janitorial work has +// been completed. +// +// Returns a negative error code on failure. +int lfsr_gc_setsteps(lfs_t *lfs, lfs_soff_t steps); +#endif + + /// Filesystem-level filesystem operations // Find on-disk info about the filesystem @@ -1283,25 +1341,6 @@ int lfsr_fs_ckmeta(lfs_t *lfs); int lfsr_fs_ckdata(lfs_t *lfs); #endif -#ifndef LFS_READONLY -// Perform any janitorial work that may be pending. -// -// The exact janitorial work depends on the provided flags. -// -// The steps parameter controls how many gc steps to progress before -// returning, with each gc step being ~1 block of work. More steps per call -// will make more progress if interleaved with other filesystem writes, but -// may also introduce more latency. steps=1 will do the minimum amount of -// work to make progress, and steps=-1 will not return until all pending -// janitorial work has been completed. -// -// Calling this function is not required, but may allow the offloading of -// expensive janitorial work to a less time-critical code path. -// -// Returns a negative error code on failure. -int lfsr_fs_gc(lfs_t *lfs, lfs_soff_t steps, uint32_t flags); -#endif - #ifndef LFS_READONLY // Change the number of blocks used by the filesystem // diff --git a/runners/bench_runner.h b/runners/bench_runner.h index b34864a2..3b925b56 100644 --- a/runners/bench_runner.h +++ b/runners/bench_runner.h @@ -114,6 +114,8 @@ void bench_permutation(size_t i, uint32_t *buffer, size_t size); BENCH_DEFINE(PCACHE_SIZE, LFS_MAX(16, PROG_SIZE) ) \ BENCH_DEFINE(FILE_BUFFER_SIZE, 16 ) \ BENCH_DEFINE(LOOKAHEAD_SIZE, 16 ) \ + BENCH_DEFINE(GC_FLAGS, 0 ) \ + BENCH_DEFINE(GC_STEPS, 0 ) \ BENCH_DEFINE(GC_COMPACT_THRESH, 0 ) \ BENCH_DEFINE(INLINE_SIZE, BLOCK_SIZE/4 ) \ BENCH_DEFINE(SHRUB_SIZE, INLINE_SIZE ) \ @@ -143,6 +145,8 @@ 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, \ .gc_compact_thresh = GC_COMPACT_THRESH, \ .inline_size = INLINE_SIZE, \ .shrub_size = SHRUB_SIZE, \ diff --git a/runners/test_runner.h b/runners/test_runner.h index 4835d2ea..97c5eef7 100644 --- a/runners/test_runner.h +++ b/runners/test_runner.h @@ -105,6 +105,8 @@ void test_permutation(size_t i, uint32_t *buffer, size_t size); TEST_DEFINE(PCACHE_SIZE, LFS_MAX(16, PROG_SIZE) ) \ TEST_DEFINE(FILE_BUFFER_SIZE, 16 ) \ TEST_DEFINE(LOOKAHEAD_SIZE, 16 ) \ + TEST_DEFINE(GC_FLAGS, 0 ) \ + TEST_DEFINE(GC_STEPS, 0 ) \ TEST_DEFINE(GC_COMPACT_THRESH, 0 ) \ TEST_DEFINE(INLINE_SIZE, BLOCK_SIZE/4 ) \ TEST_DEFINE(SHRUB_SIZE, INLINE_SIZE ) \ @@ -134,6 +136,8 @@ 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, \ .gc_compact_thresh = GC_COMPACT_THRESH, \ .inline_size = INLINE_SIZE, \ .shrub_size = SHRUB_SIZE, \ diff --git a/tests/test_attrs.toml b/tests/test_attrs.toml index c0d51e48..382988b2 100644 --- a/tests/test_attrs.toml +++ b/tests/test_attrs.toml @@ -490,6 +490,8 @@ defines.FILETYPE = [0, 1, 2] defines.M = 40 defines.SIZE = 4 defines.COMPACT = [false, true] +defines.GC_FLAGS = 'LFS_GC_COMPACT' +defines.GC_STEPS = -1 defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2' code = ''' lfs_t lfs; @@ -527,7 +529,7 @@ code = ''' // try compacting? if (COMPACT) { - lfsr_fs_gc(&lfs, -1, LFS_GC_COMPACT) => 0; + lfsr_gc(&lfs) => 0; } for (int remount = 0; remount < 2; remount++) { @@ -567,6 +569,8 @@ defines.N = 64 defines.M = 4 defines.SIZE = 4 defines.COMPACT = [false, true] +defines.GC_FLAGS = 'LFS_GC_COMPACT' +defines.GC_STEPS = -1 defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2' code = ''' lfs_t lfs; @@ -605,7 +609,7 @@ code = ''' // try compacting? if (COMPACT) { - lfsr_fs_gc(&lfs, -1, LFS_GC_COMPACT) => 0; + lfsr_gc(&lfs) => 0; } for (int remount = 0; remount < 2; remount++) { @@ -4067,6 +4071,8 @@ defines.N = 64 defines.M = 4 defines.SIZE = 4 defines.COMPACT = [false, true] +defines.GC_FLAGS = 'LFS_GC_COMPACT' +defines.GC_STEPS = -1 defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2' code = ''' lfs_t lfs; @@ -4105,7 +4111,7 @@ code = ''' // try compacting? if (COMPACT) { - lfsr_fs_gc(&lfs, -1, LFS_GC_COMPACT) => 0; + lfsr_gc(&lfs) => 0; } for (int remount = 0; remount < 2; remount++) { diff --git a/tests/test_ck.toml b/tests/test_ck.toml index c319f439..b1ed4d2c 100644 --- a/tests/test_ck.toml +++ b/tests/test_ck.toml @@ -8,10 +8,12 @@ after = ['test_traversal', 'test_gc', 'test_mount'] # test we can detect at least fully clobbered blocks [cases.test_ck_ckmeta_easy] # METHOD=0 => lfsr_fs_ckmeta -# METHOD=1 => lfsr_fs_gc +# METHOD=1 => lfsr_gc # METHOD=2 => lfsr_traversal_read # METHOD=3 => lfsr_mount defines.METHOD = [0, 1, 2, 3] +defines.GC_FLAGS = 'LFS_GC_CKMETA' +defines.GC_STEPS = -1 defines.N = [1, 2, 4, 8, 16, 32, 64] defines.SIZE = [ '0', @@ -94,9 +96,9 @@ code = ''' if (METHOD == 0) { lfsr_fs_ckmeta(&lfs) => LFS_ERR_CORRUPT; - // find clobbered blocks with lfsr_fs_gc + // find clobbered blocks with lfsr_gc } else if (METHOD == 1) { - lfsr_fs_gc(&lfs, -1, LFS_GC_CKMETA) => LFS_ERR_CORRUPT; + lfsr_gc(&lfs) => LFS_ERR_CORRUPT; // find clobbered blocks with lfsr_traversal_read } else if (METHOD == 2) { @@ -136,10 +138,12 @@ done:; [cases.test_ck_ckdata_easy] # METHOD=0 => lfsr_fs_ckdata -# METHOD=1 => lfsr_fs_gc +# METHOD=1 => lfsr_gc # METHOD=2 => lfsr_traversal_read # METHOD=3 => lfsr_mount defines.METHOD = [0, 1, 2, 3] +defines.GC_FLAGS = 'LFS_GC_CKDATA' +defines.GC_STEPS = -1 defines.N = [1, 2, 4, 8, 16, 32, 64] defines.SIZE = [ '0', @@ -223,9 +227,9 @@ code = ''' if (METHOD == 0) { lfsr_fs_ckdata(&lfs) => LFS_ERR_CORRUPT; - // find clobbered blocks with lfsr_fs_gc + // find clobbered blocks with lfsr_gc } else if (METHOD == 1) { - lfsr_fs_gc(&lfs, -1, LFS_GC_CKDATA) => LFS_ERR_CORRUPT; + lfsr_gc(&lfs) => LFS_ERR_CORRUPT; // find clobbered blocks with lfsr_traversal_read } else if (METHOD == 2) { diff --git a/tests/test_gc.toml b/tests/test_gc.toml index b5147b48..0353dd16 100644 --- a/tests/test_gc.toml +++ b/tests/test_gc.toml @@ -1,14 +1,19 @@ # Test GC things -# most of the GC logic is tested in test_traversal, we just test a few -# GC-specific things here +# most of the GC logic is tested in test_traversal, we just test +# GC-API specific things here after = ['test_traversal'] # test that lookahead can make progress in isolation [cases.test_gc_lookahead_progress] -defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + LFS_GC_LOOKAHEAD + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' +defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] defines.SIZE = [ 'FILE_BUFFER_SIZE/2', '2*FILE_BUFFER_SIZE', @@ -39,17 +44,14 @@ code = ''' struct lfs_fsinfo fsinfo; lfsr_fs_stat(&lfs, &fsinfo) => 0; assert(fsinfo.flags & LFS_I_CANLOOKAHEAD); - assert(lfs.omdirs != &lfs.gc.o.o); + assert(lfs.omdirs != &lfs.gc.t.o.o); // run GC until we make progress for (lfs_block_t i = 0;; i++) { // a bit hacky, but this catches infinite loops LFS_ASSERT(i < 2*BLOCK_COUNT); - lfsr_fs_gc(&lfs, GC_STEPS, - LFS_GC_LOOKAHEAD - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc(&lfs) => 0; lfsr_fs_stat(&lfs, &fsinfo) => 0; if (!(fsinfo.flags & LFS_I_CANLOOKAHEAD)) { @@ -67,11 +69,143 @@ code = ''' lfsr_unmount(&lfs) => 0; ''' -# test that lookahead dirtying still works with the GC API -[cases.test_gc_lookahead_mutation] -defines.GC_STEPS = 1 +# test that we can change flags after mount +[cases.test_gc_setflags] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' +defines.SIZE = [ + 'FILE_BUFFER_SIZE/2', + '2*FILE_BUFFER_SIZE', + 'BLOCK_SIZE/2', + 'BLOCK_SIZE', + '2*BLOCK_SIZE', + '8*BLOCK_SIZE', +] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + + uint32_t prng = 42; + + // create a file + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "spider", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + uint8_t wbuf[SIZE]; + for (lfs_size_t j = 0; j < SIZE; j++) { + wbuf[j] = 'a' + (TEST_PRNG(&prng) % 26); + } + lfsr_file_write(&lfs, &file, wbuf, SIZE) => SIZE; + lfsr_file_close(&lfs, &file) => 0; + + // expect dirty initial state or else our test doesn't work + struct lfs_fsinfo fsinfo; + lfsr_fs_stat(&lfs, &fsinfo) => 0; + assert(fsinfo.flags & LFS_I_CANLOOKAHEAD); + assert(lfs.omdirs != &lfs.gc.t.o.o); + + // change flags + lfsr_gc_setflags(&lfs, GC_FLAGS | LFS_GC_LOOKAHEAD) => 0; + + // run GC until we make progress + for (lfs_block_t i = 0;; i++) { + // a bit hacky, but this catches infinite loops + LFS_ASSERT(i < 2*BLOCK_COUNT); + + lfsr_gc(&lfs) => 0; + + lfsr_fs_stat(&lfs, &fsinfo) => 0; + if (!(fsinfo.flags & LFS_I_CANLOOKAHEAD)) { + break; + } + } + + // check the file contents + lfsr_file_open(&lfs, &file, "spider", LFS_O_RDONLY) => 0; + uint8_t rbuf[SIZE]; + lfsr_file_read(&lfs, &file, rbuf, SIZE) => SIZE; + assert(memcmp(rbuf, wbuf, SIZE) == 0); + lfsr_file_close(&lfs, &file) => 0; + + lfsr_unmount(&lfs) => 0; +''' + +# test that we can change steps after mount +[cases.test_gc_setsteps] +defines.CKMETA = [false, true] +defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + LFS_GC_LOOKAHEAD + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' +defines.GC_STEPS = 1 +defines.SIZE = [ + 'FILE_BUFFER_SIZE/2', + '2*FILE_BUFFER_SIZE', + 'BLOCK_SIZE/2', + 'BLOCK_SIZE', + '2*BLOCK_SIZE', + '8*BLOCK_SIZE', +] +code = ''' + lfs_t lfs; + lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; + lfsr_mount(&lfs, LFS_M_RDWR, CFG) => 0; + + uint32_t prng = 42; + + // create a file + lfsr_file_t file; + lfsr_file_open(&lfs, &file, "spider", + LFS_O_WRONLY | LFS_O_CREAT | LFS_O_EXCL) => 0; + uint8_t wbuf[SIZE]; + for (lfs_size_t j = 0; j < SIZE; j++) { + wbuf[j] = 'a' + (TEST_PRNG(&prng) % 26); + } + lfsr_file_write(&lfs, &file, wbuf, SIZE) => SIZE; + lfsr_file_close(&lfs, &file) => 0; + + // expect dirty initial state or else our test doesn't work + struct lfs_fsinfo fsinfo; + lfsr_fs_stat(&lfs, &fsinfo) => 0; + assert(fsinfo.flags & LFS_I_CANLOOKAHEAD); + assert(lfs.omdirs != &lfs.gc.t.o.o); + + // change steps + lfsr_gc_setsteps(&lfs, -1) => 0; + + // run GC + lfsr_gc(&lfs) => 0; + + // we should have made progress + lfsr_fs_stat(&lfs, &fsinfo) => 0; + assert(!(fsinfo.flags & LFS_I_CANLOOKAHEAD)); + + // check the file contents + lfsr_file_open(&lfs, &file, "spider", LFS_O_RDONLY) => 0; + uint8_t rbuf[SIZE]; + lfsr_file_read(&lfs, &file, rbuf, SIZE) => SIZE; + assert(memcmp(rbuf, wbuf, SIZE) == 0); + lfsr_file_close(&lfs, &file) => 0; + + lfsr_unmount(&lfs) => 0; +''' + +# test that lookahead dirtying still works with the GC API +[cases.test_gc_lookahead_mutation] +defines.CKMETA = [false, true] +defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + LFS_GC_LOOKAHEAD + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' defines.SIZE = [ 'FILE_BUFFER_SIZE/2', '2*FILE_BUFFER_SIZE', @@ -104,14 +238,11 @@ code = ''' struct lfs_fsinfo fsinfo; lfsr_fs_stat(&lfs, &fsinfo) => 0; assert(fsinfo.flags & LFS_I_CANLOOKAHEAD); - assert(lfs.omdirs != &lfs.gc.o.o); + assert(lfs.omdirs != &lfs.gc.t.o.o); // run GC one step - lfsr_fs_gc(&lfs, GC_STEPS, - LFS_GC_LOOKAHEAD - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; - assert(lfs.omdirs == &lfs.gc.o.o); + lfsr_gc(&lfs) => 0; + assert(lfs.omdirs == &lfs.gc.t.o.o); // mutate the filesystem lfsr_file_open(&lfs, &file, "spider", @@ -123,11 +254,8 @@ code = ''' lfsr_file_close(&lfs, &file) => 0; // run GC until our traversal is done - while (lfs.omdirs == &lfs.gc.o.o) { - lfsr_fs_gc(&lfs, GC_STEPS, - LFS_GC_LOOKAHEAD - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + while (lfs.omdirs == &lfs.gc.t.o.o) { + lfsr_gc(&lfs) => 0; } // we should _not_ make progress @@ -146,9 +274,12 @@ code = ''' # test that adding flags doesn't break lookahead [cases.test_gc_lookahead_add_flags] -defines.GC_STEPS = 1 defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' defines.SIZE = [ 'FILE_BUFFER_SIZE/2', '2*FILE_BUFFER_SIZE', @@ -181,20 +312,17 @@ code = ''' struct lfs_fsinfo fsinfo; lfsr_fs_stat(&lfs, &fsinfo) => 0; assert(fsinfo.flags & LFS_I_CANLOOKAHEAD); - assert(lfs.omdirs != &lfs.gc.o.o); + assert(lfs.omdirs != &lfs.gc.t.o.o); // run GC one step - lfsr_fs_gc(&lfs, GC_STEPS, - ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; - assert(lfs.omdirs == &lfs.gc.o.o); + lfsr_gc(&lfs) => 0; + assert(lfs.omdirs == &lfs.gc.t.o.o); // change flags and run GC until our traversal is done - while (lfs.omdirs == &lfs.gc.o.o) { - lfsr_fs_gc(&lfs, GC_STEPS, - LFS_GC_LOOKAHEAD - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc_setflags(&lfs, GC_FLAGS | LFS_GC_LOOKAHEAD) => 0; + + while (lfs.omdirs == &lfs.gc.t.o.o) { + lfsr_gc(&lfs) => 0; } // we should _not_ make progress @@ -213,9 +341,13 @@ code = ''' # test that removing flags invalidates lookahead [cases.test_gc_lookahead_remove_flags] -defines.GC_STEPS = 1 defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + LFS_GC_LOOKAHEAD + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' defines.SIZE = [ 'FILE_BUFFER_SIZE/2', '2*FILE_BUFFER_SIZE', @@ -248,20 +380,17 @@ code = ''' struct lfs_fsinfo fsinfo; lfsr_fs_stat(&lfs, &fsinfo) => 0; assert(fsinfo.flags & LFS_I_CANLOOKAHEAD); - assert(lfs.omdirs != &lfs.gc.o.o); + assert(lfs.omdirs != &lfs.gc.t.o.o); // run GC one step - lfsr_fs_gc(&lfs, GC_STEPS, - LFS_GC_LOOKAHEAD - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; - assert(lfs.omdirs == &lfs.gc.o.o); + lfsr_gc(&lfs) => 0; + assert(lfs.omdirs == &lfs.gc.t.o.o); // change flags and run GC until our traversal is done - while (lfs.omdirs == &lfs.gc.o.o) { - lfsr_fs_gc(&lfs, GC_STEPS, - ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc_setflags(&lfs, GC_FLAGS & ~LFS_GC_LOOKAHEAD) => 0; + + while (lfs.omdirs == &lfs.gc.t.o.o) { + lfsr_gc(&lfs) => 0; } // we should _not_ make progress @@ -281,10 +410,18 @@ code = ''' # test that compact can make progress in isolation [cases.test_gc_compact_progress] -defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] defines.LOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + LFS_GC_COMPACT + | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' +defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] +# set compact thresh to minimum +defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2' defines.SIZE = [ 'FILE_BUFFER_SIZE/2', '2*FILE_BUFFER_SIZE', @@ -293,8 +430,6 @@ defines.SIZE = [ '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] -# set compact thresh to minimum -defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2' code = ''' lfs_t lfs; lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0; @@ -322,18 +457,14 @@ code = ''' struct lfs_fsinfo fsinfo; lfsr_fs_stat(&lfs, &fsinfo) => 0; assert(fsinfo.flags & LFS_I_UNCOMPACTED); - assert(lfs.omdirs != &lfs.gc.o.o); + assert(lfs.omdirs != &lfs.gc.t.o.o); // run GC until we make progress for (lfs_block_t i = 0;; i++) { // a bit hacky, but this catches infinite loops LFS_ASSERT(i < 2*BLOCK_COUNT); - lfsr_fs_gc(&lfs, GC_STEPS, - LFS_GC_COMPACT - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc(&lfs) => 0; lfsr_fs_stat(&lfs, &fsinfo) => 0; if (!(fsinfo.flags & LFS_I_UNCOMPACTED)) { @@ -366,10 +497,17 @@ code = ''' # test that compact dirtying still works with the GC API [cases.test_gc_compact_mutation] -defines.GC_STEPS = 1 defines.LOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + LFS_GC_COMPACT + | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' +# set compact thresh to minimum +defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2' defines.SIZE = [ 'FILE_BUFFER_SIZE/2', '2*FILE_BUFFER_SIZE', @@ -378,8 +516,6 @@ defines.SIZE = [ '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] -# set compact thresh to minimum -defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2' # we need something to keep the traversal running if = 'CKMETA || CKDATA' code = ''' @@ -409,27 +545,19 @@ code = ''' struct lfs_fsinfo fsinfo; lfsr_fs_stat(&lfs, &fsinfo) => 0; assert(fsinfo.flags & LFS_I_UNCOMPACTED); - assert(lfs.omdirs != &lfs.gc.o.o); + assert(lfs.omdirs != &lfs.gc.t.o.o); // run GC one traversal + one step while (true) { - lfsr_fs_gc(&lfs, GC_STEPS, - LFS_GC_COMPACT - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc(&lfs) => 0; // internal traversal done? - if (lfs.omdirs != &lfs.gc.o.o) { + if (lfs.omdirs != &lfs.gc.t.o.o) { break; } } - lfsr_fs_gc(&lfs, GC_STEPS, - LFS_GC_COMPACT - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; - assert(lfs.omdirs == &lfs.gc.o.o); + lfsr_gc(&lfs) => 0; + assert(lfs.omdirs == &lfs.gc.t.o.o); // mutate the filesystem lfsr_file_rewind(&lfs, &file) => 0; @@ -440,12 +568,8 @@ code = ''' lfsr_file_sync(&lfs, &file) => 0; // run GC until our traversal is done (twice for compact) - while (lfs.omdirs == &lfs.gc.o.o) { - lfsr_fs_gc(&lfs, GC_STEPS, - LFS_GC_COMPACT - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + while (lfs.omdirs == &lfs.gc.t.o.o) { + lfsr_gc(&lfs) => 0; } // we should _not_ make progress @@ -474,10 +598,16 @@ code = ''' # test that adding flags doesn't break compact [cases.test_gc_compact_add_flags] -defines.GC_STEPS = 1 defines.LOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' +# set compact thresh to minimum +defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2' defines.SIZE = [ 'FILE_BUFFER_SIZE/2', '2*FILE_BUFFER_SIZE', @@ -486,8 +616,6 @@ defines.SIZE = [ '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] -# set compact thresh to minimum -defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2' # we need something to keep the traversal running if = 'CKMETA || CKDATA' code = ''' @@ -517,33 +645,25 @@ code = ''' struct lfs_fsinfo fsinfo; lfsr_fs_stat(&lfs, &fsinfo) => 0; assert(fsinfo.flags & LFS_I_UNCOMPACTED); - assert(lfs.omdirs != &lfs.gc.o.o); + assert(lfs.omdirs != &lfs.gc.t.o.o); // run GC one traversal + one step while (true) { - lfsr_fs_gc(&lfs, GC_STEPS, - ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc(&lfs) => 0; // internal traversal done? - if (lfs.omdirs != &lfs.gc.o.o) { + if (lfs.omdirs != &lfs.gc.t.o.o) { break; } } - lfsr_fs_gc(&lfs, GC_STEPS, - ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; - assert(lfs.omdirs == &lfs.gc.o.o); + lfsr_gc(&lfs) => 0; + assert(lfs.omdirs == &lfs.gc.t.o.o); // change flags and run GC until our traversal is done (twice for compact) - while (lfs.omdirs == &lfs.gc.o.o) { - lfsr_fs_gc(&lfs, GC_STEPS, - LFS_GC_COMPACT - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc_setflags(&lfs, GC_FLAGS | LFS_GC_COMPACT) => 0; + + while (lfs.omdirs == &lfs.gc.t.o.o) { + lfsr_gc(&lfs) => 0; } // we should _not_ make progress @@ -572,10 +692,17 @@ code = ''' # test that removing flags invalidates compact [cases.test_gc_compact_remove_flags] -defines.GC_STEPS = 1 defines.LOOKAHEAD = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + LFS_GC_COMPACT + | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' +# set compact thresh to minimum +defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2' defines.SIZE = [ 'FILE_BUFFER_SIZE/2', '2*FILE_BUFFER_SIZE', @@ -584,8 +711,6 @@ defines.SIZE = [ '2*BLOCK_SIZE', '8*BLOCK_SIZE', ] -# set compact thresh to minimum -defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2' # we need something to keep the traversal running if = 'CKMETA || CKDATA' code = ''' @@ -615,34 +740,25 @@ code = ''' struct lfs_fsinfo fsinfo; lfsr_fs_stat(&lfs, &fsinfo) => 0; assert(fsinfo.flags & LFS_I_UNCOMPACTED); - assert(lfs.omdirs != &lfs.gc.o.o); + assert(lfs.omdirs != &lfs.gc.t.o.o); // run GC one traversal + one step while (true) { - lfsr_fs_gc(&lfs, GC_STEPS, - LFS_GC_COMPACT - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc(&lfs) => 0; // internal traversal done? - if (lfs.omdirs != &lfs.gc.o.o) { + if (lfs.omdirs != &lfs.gc.t.o.o) { break; } } - lfsr_fs_gc(&lfs, GC_STEPS, - LFS_GC_COMPACT - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; - assert(lfs.omdirs == &lfs.gc.o.o); + lfsr_gc(&lfs) => 0; + assert(lfs.omdirs == &lfs.gc.t.o.o); // change flags and run GC until our traversal is done (twice for compact) - while (lfs.omdirs == &lfs.gc.o.o) { - lfsr_fs_gc(&lfs, GC_STEPS, - ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc_setflags(&lfs, GC_FLAGS & ~LFS_GC_COMPACT) => 0; + + while (lfs.omdirs == &lfs.gc.t.o.o) { + lfsr_gc(&lfs) => 0; } // we should _not_ make progress @@ -672,11 +788,18 @@ code = ''' # test that mkconsistent can make progress in isolation [cases.test_gc_mkconsistent_progress] -defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] defines.LOOKAHEAD = [false, true] defines.COMPACT = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + LFS_GC_MKCONSISTENT + | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) + | ((COMPACT) ? LFS_GC_COMPACT : 0) + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' +defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] defines.SIZE = 'FILE_BUFFER_SIZE/2' # <=2 => grm-able # >2 => requires orphans @@ -731,19 +854,14 @@ code = ''' struct lfs_fsinfo fsinfo; lfsr_fs_stat(&lfs, &fsinfo) => 0; assert(fsinfo.flags & LFS_I_INCONSISTENT); - assert(lfs.omdirs != &lfs.gc.o.o); + assert(lfs.omdirs != &lfs.gc.t.o.o); // run GC until we make progress for (lfs_block_t i = 0;; i++) { // a bit hacky, but this catches infinite loops LFS_ASSERT(i < 2*BLOCK_COUNT); - lfsr_fs_gc(&lfs, GC_STEPS, - LFS_GC_MKCONSISTENT - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((COMPACT) ? LFS_GC_COMPACT : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc(&lfs) => 0; lfsr_fs_stat(&lfs, &fsinfo) => 0; if (!(fsinfo.flags & LFS_I_INCONSISTENT)) { @@ -835,7 +953,7 @@ code = ''' struct lfs_fsinfo fsinfo; lfsr_fs_stat(&lfs, &fsinfo) => 0; assert(fsinfo.flags & LFS_I_INCONSISTENT); - assert(lfs.omdirs != &lfs.gc.o.o); + assert(lfs.omdirs != &lfs.gc.t.o.o); // call lfsr_fs_mkconsistent lfsr_fs_mkconsistent(&lfs) => 0; @@ -873,11 +991,17 @@ code = ''' # test that mkconsistent dirtying still works with the GC API [cases.test_gc_mkconsistent_mutation] -defines.GC_STEPS = 1 defines.LOOKAHEAD = [false, true] defines.COMPACT = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + LFS_GC_MKCONSISTENT + | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) + | ((COMPACT) ? LFS_GC_COMPACT : 0) + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' defines.SIZE = 'FILE_BUFFER_SIZE/2' # <=2 => grm-able # >2 => requires orphans @@ -925,14 +1049,9 @@ code = ''' } // run GC one step - assert(lfs.omdirs != &lfs.gc.o.o); - lfsr_fs_gc(&lfs, GC_STEPS, - LFS_GC_MKCONSISTENT - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((COMPACT) ? LFS_GC_COMPACT : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; - assert(lfs.omdirs == &lfs.gc.o.o); + assert(lfs.omdirs != &lfs.gc.t.o.o); + lfsr_gc(&lfs) => 0; + assert(lfs.omdirs == &lfs.gc.t.o.o); // create the rest of the orphans after GC has started for (lfs_size_t i = 0; i < ORPHANS; i++) { @@ -951,13 +1070,8 @@ code = ''' assert(fsinfo.flags & LFS_I_INCONSISTENT); // run GC until our traversal is done - while (lfs.omdirs == &lfs.gc.o.o) { - lfsr_fs_gc(&lfs, GC_STEPS, - LFS_GC_MKCONSISTENT - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((COMPACT) ? LFS_GC_COMPACT : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + while (lfs.omdirs == &lfs.gc.t.o.o) { + lfsr_gc(&lfs) => 0; } // we should _not_ make progress @@ -993,11 +1107,16 @@ code = ''' # test that adding flags doesn't break mkconsistent [cases.test_gc_mkconsistent_add_flags] -defines.GC_STEPS = 1 defines.LOOKAHEAD = [false, true] defines.COMPACT = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) + | ((COMPACT) ? LFS_GC_COMPACT : 0) + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' defines.SIZE = 'FILE_BUFFER_SIZE/2' # <=2 => grm-able # >2 => requires orphans @@ -1055,24 +1174,17 @@ code = ''' struct lfs_fsinfo fsinfo; lfsr_fs_stat(&lfs, &fsinfo) => 0; assert(fsinfo.flags & LFS_I_INCONSISTENT); - assert(lfs.omdirs != &lfs.gc.o.o); + assert(lfs.omdirs != &lfs.gc.t.o.o); // run GC one step - lfsr_fs_gc(&lfs, GC_STEPS, - ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((COMPACT) ? LFS_GC_COMPACT : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; - assert(lfs.omdirs == &lfs.gc.o.o); + lfsr_gc(&lfs) => 0; + assert(lfs.omdirs == &lfs.gc.t.o.o); // change flags and run GC until our traversal is done - while (lfs.omdirs == &lfs.gc.o.o) { - lfsr_fs_gc(&lfs, GC_STEPS, - LFS_GC_MKCONSISTENT - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((COMPACT) ? LFS_GC_COMPACT : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc_setflags(&lfs, GC_FLAGS | LFS_GC_MKCONSISTENT) => 0; + + while (lfs.omdirs == &lfs.gc.t.o.o) { + lfsr_gc(&lfs) => 0; } // we should _not_ make progress @@ -1108,11 +1220,17 @@ code = ''' # test that removing flags invalidates mkconsistent [cases.test_gc_mkconsistent_remove_flags] -defines.GC_STEPS = 1 defines.LOOKAHEAD = [false, true] defines.COMPACT = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + LFS_GC_MKCONSISTENT + | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) + | ((COMPACT) ? LFS_GC_COMPACT : 0) + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' defines.SIZE = 'FILE_BUFFER_SIZE/2' # <=2 => grm-able # >2 => requires orphans @@ -1169,24 +1287,17 @@ code = ''' struct lfs_fsinfo fsinfo; lfsr_fs_stat(&lfs, &fsinfo) => 0; assert(fsinfo.flags & LFS_I_INCONSISTENT); - assert(lfs.omdirs != &lfs.gc.o.o); + assert(lfs.omdirs != &lfs.gc.t.o.o); // run GC one step - lfsr_fs_gc(&lfs, GC_STEPS, - LFS_GC_MKCONSISTENT - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((COMPACT) ? LFS_GC_COMPACT : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; - assert(lfs.omdirs == &lfs.gc.o.o); + lfsr_gc(&lfs) => 0; + assert(lfs.omdirs == &lfs.gc.t.o.o); // change flags and run GC until our traversal is done - while (lfs.omdirs == &lfs.gc.o.o) { - lfsr_fs_gc(&lfs, GC_STEPS, - ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((COMPACT) ? LFS_GC_COMPACT : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc_setflags(&lfs, GC_FLAGS & ~LFS_GC_MKCONSISTENT) => 0; + + while (lfs.omdirs == &lfs.gc.t.o.o) { + lfsr_gc(&lfs) => 0; } // we should _not_ make progress @@ -1225,6 +1336,7 @@ code = ''' # # these are tested more thoroughly in test_ck [cases.test_gc_ckmeta] +defines.GC_FLAGS = 'LFS_GC_CKMETA' defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] defines.N = [1, 2, 4, 8, 16, 32, 64] defines.SIZE = [ @@ -1304,12 +1416,12 @@ code = ''' } clobbered:; - // running lfsr_fs_gc should eventually find the clobbered block + // running lfsr_gc should eventually find the clobbered block for (lfs_block_t i = 0;; i++) { // a bit hacky, but this catches infinite loops LFS_ASSERT(i < 2*BLOCK_COUNT); - int err = lfsr_fs_gc(&lfs, GC_STEPS, LFS_GC_CKMETA); + int err = lfsr_gc(&lfs); assert(!err || err == LFS_ERR_CORRUPT); // found it if (err == LFS_ERR_CORRUPT) { @@ -1323,6 +1435,7 @@ done:; ''' [cases.test_gc_ckdata] +defines.GC_FLAGS = 'LFS_GC_CKDATA' defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] defines.N = [1, 2, 4, 8, 16, 32, 64] defines.SIZE = [ @@ -1403,14 +1516,14 @@ code = ''' } clobbered:; - // running lfsr_fs_gc should eventually find the clobbered block + // running lfsr_gc should eventually find the clobbered block // // note LFS_GC_CKDATA implies LFS_GC_CKMETA for (lfs_block_t i = 0;; i++) { // a bit hacky, but this catches infinite loops LFS_ASSERT(i < 2*BLOCK_COUNT); - int err = lfsr_fs_gc(&lfs, GC_STEPS, LFS_GC_CKDATA); + int err = lfsr_gc(&lfs); assert(!err || err == LFS_ERR_CORRUPT); // found it if (err == LFS_ERR_CORRUPT) { @@ -1603,13 +1716,20 @@ done:; # pseudo-fuzz test that dirtying still works with the GC API [cases.test_gc_mutation] -defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] defines.N = 100 defines.MKCONSISTENT = [false, true] defines.LOOKAHEAD = [false, true] defines.COMPACT = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + ((MKCONSISTENT) ? LFS_GC_MKCONSISTENT : 0) + | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) + | ((COMPACT) ? LFS_GC_COMPACT : 0) + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' +defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] # set compact thresh to minimum defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2' defines.SIZE = [ @@ -1649,12 +1769,7 @@ code = ''' lfsr_file_close(&lfs, &file) => 0; // gc! - lfsr_fs_gc(&lfs, GC_STEPS, - ((MKCONSISTENT) ? LFS_GC_MKCONSISTENT : 0) - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((COMPACT) ? LFS_GC_COMPACT : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc(&lfs) => 0; } // check the file contents @@ -1669,13 +1784,20 @@ code = ''' # pseudo-fuzz test that adding/removing flags doesn't break anything [cases.test_gc_changing_flags] -defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] defines.N = 100 defines.MKCONSISTENT = [false, true] defines.LOOKAHEAD = [false, true] defines.COMPACT = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + ((MKCONSISTENT) ? LFS_GC_MKCONSISTENT : 0) + | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) + | ((COMPACT) ? LFS_GC_COMPACT : 0) + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' +defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] # set compact thresh to minimum defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2' defines.SIZE = [ @@ -1715,16 +1837,11 @@ code = ''' lfsr_file_close(&lfs, &file) => 0; // choose a new subset of flags every cycle - uint32_t flags = ( - ((MKCONSISTENT) ? LFS_GC_MKCONSISTENT : 0) - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((COMPACT) ? LFS_GC_COMPACT : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0) - ) & TEST_PRNG(&prng); + uint32_t flags = GC_FLAGS & TEST_PRNG(&prng); + lfsr_gc_setflags(&lfs, flags) => 0; // gc! - lfsr_fs_gc(&lfs, GC_STEPS, flags) => 0; + lfsr_gc(&lfs) => 0; } // check the file contents @@ -1743,12 +1860,19 @@ code = ''' # [cases.test_gc_spam_dir_many] -defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] defines.MKCONSISTENT = [false, true] defines.LOOKAHEAD = [false, true] defines.COMPACT = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + ((MKCONSISTENT) ? LFS_GC_MKCONSISTENT : 0) + | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) + | ((COMPACT) ? LFS_GC_COMPACT : 0) + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' +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] @@ -1766,12 +1890,7 @@ code = ''' assert(!err || (TEST_PLS && err == LFS_ERR_EXIST)); // gc! - lfsr_fs_gc(&lfs, GC_STEPS, - ((MKCONSISTENT) ? LFS_GC_MKCONSISTENT : 0) - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((COMPACT) ? LFS_GC_COMPACT : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc(&lfs) => 0; } for (int remount = 0; remount < 2; remount++) { @@ -1838,12 +1957,19 @@ code = ''' ''' [cases.test_gc_spam_dir_fuzz] -defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] defines.MKCONSISTENT = [false, true] defines.LOOKAHEAD = [false, true] defines.COMPACT = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + ((MKCONSISTENT) ? LFS_GC_MKCONSISTENT : 0) + | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) + | ((COMPACT) ? LFS_GC_COMPACT : 0) + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' +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] @@ -1944,12 +2070,7 @@ code = ''' } // gc! - lfsr_fs_gc(&lfs, GC_STEPS, - ((MKCONSISTENT) ? LFS_GC_MKCONSISTENT : 0) - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((COMPACT) ? LFS_GC_COMPACT : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc(&lfs) => 0; } for (int remount = 0; remount < 2; remount++) { @@ -2004,12 +2125,19 @@ code = ''' ''' [cases.test_gc_spam_file_many] -defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] defines.MKCONSISTENT = [false, true] defines.LOOKAHEAD = [false, true] defines.COMPACT = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + ((MKCONSISTENT) ? LFS_GC_MKCONSISTENT : 0) + | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) + | ((COMPACT) ? LFS_GC_COMPACT : 0) + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' +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] @@ -2047,12 +2175,7 @@ code = ''' lfsr_file_close(&lfs, &file) => 0; // gc! - lfsr_fs_gc(&lfs, GC_STEPS, - ((MKCONSISTENT) ? LFS_GC_MKCONSISTENT : 0) - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((COMPACT) ? LFS_GC_COMPACT : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc(&lfs) => 0; } for (int remount = 0; remount < 2; remount++) { @@ -2093,12 +2216,19 @@ code = ''' ''' [cases.test_gc_spam_file_fuzz] -defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] defines.MKCONSISTENT = [false, true] defines.LOOKAHEAD = [false, true] defines.COMPACT = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + ((MKCONSISTENT) ? LFS_GC_MKCONSISTENT : 0) + | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) + | ((COMPACT) ? LFS_GC_COMPACT : 0) + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' +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] @@ -2246,12 +2376,7 @@ code = ''' } // gc! - lfsr_fs_gc(&lfs, GC_STEPS, - ((MKCONSISTENT) ? LFS_GC_MKCONSISTENT : 0) - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((COMPACT) ? LFS_GC_COMPACT : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc(&lfs) => 0; } for (int remount = 0; remount < 2; remount++) { @@ -2321,12 +2446,19 @@ code = ''' ''' [cases.test_gc_spam_fwrite_fuzz] -defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] defines.MKCONSISTENT = [false, true] defines.LOOKAHEAD = [false, true] defines.COMPACT = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + ((MKCONSISTENT) ? LFS_GC_MKCONSISTENT : 0) + | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) + | ((COMPACT) ? LFS_GC_COMPACT : 0) + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' +defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] # set compact thresh to minimum defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2' defines.OPS = 20 @@ -2410,12 +2542,7 @@ code = ''' } // gc! - lfsr_fs_gc(&lfs, GC_STEPS, - ((MKCONSISTENT) ? LFS_GC_MKCONSISTENT : 0) - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((COMPACT) ? LFS_GC_COMPACT : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc(&lfs) => 0; } lfsr_file_close(&lfs, &file) => 0; @@ -2469,12 +2596,19 @@ code = ''' ''' [cases.test_gc_spam_uz_fuzz] -defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] defines.MKCONSISTENT = [false, true] defines.LOOKAHEAD = [false, true] defines.COMPACT = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + ((MKCONSISTENT) ? LFS_GC_MKCONSISTENT : 0) + | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) + | ((COMPACT) ? LFS_GC_COMPACT : 0) + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' +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] @@ -2740,12 +2874,7 @@ code = ''' } // gc! - lfsr_fs_gc(&lfs, GC_STEPS, - ((MKCONSISTENT) ? LFS_GC_MKCONSISTENT : 0) - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((COMPACT) ? LFS_GC_COMPACT : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc(&lfs) => 0; } // check that disk matches our simulation @@ -2825,12 +2954,19 @@ code = ''' ''' [cases.test_gc_spam_uzd_fuzz] -defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] defines.MKCONSISTENT = [false, true] defines.LOOKAHEAD = [false, true] defines.COMPACT = [false, true] defines.CKMETA = [false, true] defines.CKDATA = [false, true] +defines.GC_FLAGS = ''' + ((MKCONSISTENT) ? LFS_GC_MKCONSISTENT : 0) + | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) + | ((COMPACT) ? LFS_GC_COMPACT : 0) + | ((CKMETA) ? LFS_GC_CKMETA : 0) + | ((CKDATA) ? LFS_GC_CKDATA : 0) +''' +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] @@ -3158,12 +3294,7 @@ code = ''' } // gc! - lfsr_fs_gc(&lfs, GC_STEPS, - ((MKCONSISTENT) ? LFS_GC_MKCONSISTENT : 0) - | ((LOOKAHEAD) ? LFS_GC_LOOKAHEAD : 0) - | ((COMPACT) ? LFS_GC_COMPACT : 0) - | ((CKMETA) ? LFS_GC_CKMETA : 0) - | ((CKDATA) ? LFS_GC_CKDATA : 0)) => 0; + lfsr_gc(&lfs) => 0; } // check that disk matches our simulation