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.
This commit is contained in:
@@ -13155,6 +13155,7 @@ static int lfs_init(lfs_t *lfs, uint32_t flags,
|
|||||||
// // wear-leveling.
|
// // wear-leveling.
|
||||||
// LFS_ASSERT(lfs->cfg->block_cycles != 0);
|
// LFS_ASSERT(lfs->cfg->block_cycles != 0);
|
||||||
|
|
||||||
|
#ifdef LFS_GC
|
||||||
// unknown gc flags?
|
// unknown gc flags?
|
||||||
LFS_ASSERT((lfs->cfg->gc_flags & ~(
|
LFS_ASSERT((lfs->cfg->gc_flags & ~(
|
||||||
LFS_GC_MTREEONLY
|
LFS_GC_MTREEONLY
|
||||||
@@ -13163,6 +13164,7 @@ static int lfs_init(lfs_t *lfs, uint32_t flags,
|
|||||||
| LFS_GC_COMPACT
|
| LFS_GC_COMPACT
|
||||||
| LFS_GC_CKMETA
|
| LFS_GC_CKMETA
|
||||||
| LFS_GC_CKDATA)) == 0);
|
| LFS_GC_CKDATA)) == 0);
|
||||||
|
#endif
|
||||||
|
|
||||||
// check that gc_compact_thresh makes sense
|
// 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_p, 0, LFSR_GRM_DSIZE);
|
||||||
lfs_memset(lfs->grm_d, 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
|
// setup gc state, this can be mutated which is why we need a copy
|
||||||
if (lfs->cfg->gc_flags) {
|
if (lfs->cfg->gc_flags) {
|
||||||
lfs->gc.flags = 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 {
|
} else {
|
||||||
lfs->gc.steps = 1;
|
lfs->gc.steps = 1;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -13921,7 +13925,8 @@ static int lfsr_mountinited(lfs_t *lfs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// needed in lfsr_mount
|
// 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,
|
int lfsr_mount(lfs_t *lfs, uint32_t flags,
|
||||||
const struct lfs_config *cfg) {
|
const struct lfs_config *cfg) {
|
||||||
@@ -13977,7 +13982,8 @@ int lfsr_mount(lfs_t *lfs, uint32_t flags,
|
|||||||
| LFS_M_COMPACT
|
| LFS_M_COMPACT
|
||||||
| LFS_M_CKMETA
|
| LFS_M_CKMETA
|
||||||
| LFS_M_CKDATA)) {
|
| LFS_M_CKDATA)) {
|
||||||
err = lfsr_gc_(lfs,
|
lfsr_traversal_t t;
|
||||||
|
err = lfsr_fs_gc(lfs, &t,
|
||||||
flags & (
|
flags & (
|
||||||
LFS_M_MTREEONLY
|
LFS_M_MTREEONLY
|
||||||
| LFS_M_MKCONSISTENT
|
| LFS_M_MKCONSISTENT
|
||||||
@@ -14018,8 +14024,10 @@ int lfsr_unmount(lfs_t *lfs) {
|
|||||||
// all files/dirs should be closed before lfsr_unmount
|
// all files/dirs should be closed before lfsr_unmount
|
||||||
LFS_ASSERT(lfs->omdirs == NULL
|
LFS_ASSERT(lfs->omdirs == NULL
|
||||||
// special case for our gc traversal handle
|
// special case for our gc traversal handle
|
||||||
|| (lfs->omdirs == &lfs->gc.t.o.o
|
|| LFS_IFDEF_GC(
|
||||||
&& lfs->gc.t.o.o.next == NULL));
|
(lfs->omdirs == &lfs->gc.t.o.o
|
||||||
|
&& lfs->gc.t.o.o.next == NULL),
|
||||||
|
false));
|
||||||
|
|
||||||
return lfs_deinit(lfs);
|
return lfs_deinit(lfs);
|
||||||
}
|
}
|
||||||
@@ -14153,7 +14161,8 @@ int lfsr_format(lfs_t *lfs, uint32_t flags,
|
|||||||
| LFS_F_COMPACT
|
| LFS_F_COMPACT
|
||||||
| LFS_F_CKMETA
|
| LFS_F_CKMETA
|
||||||
| LFS_F_CKDATA)) {
|
| LFS_F_CKDATA)) {
|
||||||
err = lfsr_gc_(lfs,
|
lfsr_traversal_t t;
|
||||||
|
err = lfsr_fs_gc(lfs, &t,
|
||||||
flags & (
|
flags & (
|
||||||
LFS_F_MTREEONLY
|
LFS_F_MTREEONLY
|
||||||
| LFS_F_COMPACT
|
| 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);
|
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
|
// attempt to grow the filesystem
|
||||||
int lfsr_fs_grow(lfs_t *lfs, lfs_size_t block_count_) {
|
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 ///
|
/// Incremental gc operations ///
|
||||||
|
|
||||||
|
#ifdef LFS_GC
|
||||||
int lfsr_gc_setflags(lfs_t *lfs, uint32_t flags) {
|
int lfsr_gc_setflags(lfs_t *lfs, uint32_t flags) {
|
||||||
// unknown gc flags?
|
// unknown gc flags?
|
||||||
LFS_ASSERT((flags & ~(
|
LFS_ASSERT((flags & ~(
|
||||||
@@ -14656,123 +14778,22 @@ int lfsr_gc_setflags(lfs_t *lfs, uint32_t flags) {
|
|||||||
lfs->gc.flags = flags;
|
lfs->gc.flags = flags;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LFS_GC
|
||||||
int lfsr_gc_setsteps(lfs_t *lfs, lfs_soff_t steps) {
|
int lfsr_gc_setsteps(lfs_t *lfs, lfs_soff_t steps) {
|
||||||
lfs->gc.steps = steps;
|
lfs->gc.steps = steps;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LFS_GC
|
||||||
// perform any pending janitorial work
|
// 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) {
|
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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -352,12 +352,15 @@ struct lfs_config {
|
|||||||
// can track 8 blocks.
|
// can track 8 blocks.
|
||||||
lfs_size_t lookahead_size;
|
lfs_size_t lookahead_size;
|
||||||
|
|
||||||
|
#ifdef LFS_GC
|
||||||
// Flags indicating what gc work to do during lfsr_gc calls.
|
// Flags indicating what gc work to do during lfsr_gc calls.
|
||||||
//
|
//
|
||||||
// Defaults to LFS_GC_MKCONSISTENT + LFS_GC_LOOKAHEAD +
|
// Defaults to LFS_GC_MKCONSISTENT + LFS_GC_LOOKAHEAD +
|
||||||
// LFS_GC_COMPACT when zero.
|
// LFS_GC_COMPACT when zero.
|
||||||
uint32_t gc_flags;
|
uint32_t gc_flags;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef LFS_GC
|
||||||
// Number of gc steps to perform in each call to lfsr_gc, with each
|
// Number of gc steps to perform in each call to lfsr_gc, with each
|
||||||
// step being ~1 block of work.
|
// step being ~1 block of work.
|
||||||
//
|
//
|
||||||
@@ -369,6 +372,7 @@ struct lfs_config {
|
|||||||
//
|
//
|
||||||
// Defaults to steps=1 when zero.
|
// Defaults to steps=1 when zero.
|
||||||
lfs_soff_t gc_steps;
|
lfs_soff_t gc_steps;
|
||||||
|
#endif
|
||||||
|
|
||||||
// Threshold for metadata compaction during gc in bytes. Metadata logs
|
// Threshold for metadata compaction during gc in bytes. Metadata logs
|
||||||
// that exceed this threshold will be compacted during gc operations.
|
// 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_p[LFSR_GRM_DSIZE];
|
||||||
uint8_t grm_d[LFSR_GRM_DSIZE];
|
uint8_t grm_d[LFSR_GRM_DSIZE];
|
||||||
|
|
||||||
// TODO allow compile time opt-out to reclaim RAM
|
#ifdef LFS_GC
|
||||||
struct {
|
struct {
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
lfs_soff_t steps;
|
lfs_soff_t steps;
|
||||||
lfsr_traversal_t t;
|
lfsr_traversal_t t;
|
||||||
} gc;
|
} gc;
|
||||||
|
#endif
|
||||||
} lfs_t;
|
} lfs_t;
|
||||||
|
|
||||||
|
|
||||||
@@ -1253,7 +1258,7 @@ int lfsr_traversal_rewind(lfs_t *lfs, lfsr_traversal_t *t);
|
|||||||
|
|
||||||
/// Incremental gc operations ///
|
/// Incremental gc operations ///
|
||||||
|
|
||||||
#ifndef LFS_READONLY
|
#ifdef LFS_GC
|
||||||
// Perform any janitorial work that may be pending.
|
// Perform any janitorial work that may be pending.
|
||||||
//
|
//
|
||||||
// The exact janitorial work depends on the configured flags and steps.
|
// 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);
|
int lfsr_gc(lfs_t *lfs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef LFS_READONLY
|
#ifdef LFS_GC
|
||||||
// Sets the gc flags.
|
// Sets the gc flags.
|
||||||
//
|
//
|
||||||
// Returns a negative error code on failure.
|
// Returns a negative error code on failure.
|
||||||
int lfsr_gc_setflags(lfs_t *lfs, uint32_t flags);
|
int lfsr_gc_setflags(lfs_t *lfs, uint32_t flags);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef LFS_READONLY
|
#ifdef LFS_GC
|
||||||
// Sets the number of gc steps per lfsr_gc call, with each step being
|
// Sets the number of gc steps per lfsr_gc call, with each step being
|
||||||
// ~1 block of work.
|
// ~1 block of work.
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -162,6 +162,12 @@ extern "C"
|
|||||||
#define LFS_IFDEF_CKDATACKSUMS(a, b) (b)
|
#define LFS_IFDEF_CKDATACKSUMS(a, b) (b)
|
||||||
#endif
|
#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
|
// Builtin functions, these may be replaced by more efficient
|
||||||
// toolchain-specific implementations. LFS_NO_BUILTINS falls back to a more
|
// toolchain-specific implementations. LFS_NO_BUILTINS falls back to a more
|
||||||
|
|||||||
@@ -145,14 +145,21 @@ void bench_permutation(size_t i, uint32_t *buffer, size_t size);
|
|||||||
.pcache_size = PCACHE_SIZE, \
|
.pcache_size = PCACHE_SIZE, \
|
||||||
.file_buffer_size = FILE_BUFFER_SIZE, \
|
.file_buffer_size = FILE_BUFFER_SIZE, \
|
||||||
.lookahead_size = LOOKAHEAD_SIZE, \
|
.lookahead_size = LOOKAHEAD_SIZE, \
|
||||||
.gc_flags = GC_FLAGS, \
|
BENCH_GC_CFG \
|
||||||
.gc_steps = GC_STEPS, \
|
|
||||||
.gc_compact_thresh = GC_COMPACT_THRESH, \
|
.gc_compact_thresh = GC_COMPACT_THRESH, \
|
||||||
.inline_size = INLINE_SIZE, \
|
.inline_size = INLINE_SIZE, \
|
||||||
.shrub_size = SHRUB_SIZE, \
|
.shrub_size = SHRUB_SIZE, \
|
||||||
.fragment_size = FRAGMENT_SIZE, \
|
.fragment_size = FRAGMENT_SIZE, \
|
||||||
.crystal_thresh = CRYSTAL_THRESH,
|
.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 \
|
#define BENCH_BDCFG \
|
||||||
.erase_value = ERASE_VALUE, \
|
.erase_value = ERASE_VALUE, \
|
||||||
.erase_cycles = ERASE_CYCLES, \
|
.erase_cycles = ERASE_CYCLES, \
|
||||||
|
|||||||
+10
-3
@@ -136,13 +136,20 @@ void test_permutation(size_t i, uint32_t *buffer, size_t size);
|
|||||||
.pcache_size = PCACHE_SIZE, \
|
.pcache_size = PCACHE_SIZE, \
|
||||||
.file_buffer_size = FILE_BUFFER_SIZE, \
|
.file_buffer_size = FILE_BUFFER_SIZE, \
|
||||||
.lookahead_size = LOOKAHEAD_SIZE, \
|
.lookahead_size = LOOKAHEAD_SIZE, \
|
||||||
.gc_flags = GC_FLAGS, \
|
TEST_GC_CFG \
|
||||||
.gc_steps = GC_STEPS, \
|
|
||||||
.gc_compact_thresh = GC_COMPACT_THRESH, \
|
.gc_compact_thresh = GC_COMPACT_THRESH, \
|
||||||
.inline_size = INLINE_SIZE, \
|
.inline_size = INLINE_SIZE, \
|
||||||
.shrub_size = SHRUB_SIZE, \
|
.shrub_size = SHRUB_SIZE, \
|
||||||
.fragment_size = FRAGMENT_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 \
|
#define TEST_BDCFG \
|
||||||
.erase_value = ERASE_VALUE, \
|
.erase_value = ERASE_VALUE, \
|
||||||
|
|||||||
@@ -493,6 +493,7 @@ defines.COMPACT = [false, true]
|
|||||||
defines.GC_FLAGS = 'LFS_GC_COMPACT'
|
defines.GC_FLAGS = 'LFS_GC_COMPACT'
|
||||||
defines.GC_STEPS = -1
|
defines.GC_STEPS = -1
|
||||||
defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2'
|
defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2'
|
||||||
|
if = 'LFS_IFDEF_GC(true, !COMPACT)'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
@@ -528,9 +529,11 @@ code = '''
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try compacting?
|
// try compacting?
|
||||||
|
#ifdef LFS_GC
|
||||||
if (COMPACT) {
|
if (COMPACT) {
|
||||||
lfsr_gc(&lfs) => 0;
|
lfsr_gc(&lfs) => 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
for (int remount = 0; remount < 2; remount++) {
|
for (int remount = 0; remount < 2; remount++) {
|
||||||
// remount?
|
// remount?
|
||||||
@@ -572,6 +575,7 @@ defines.COMPACT = [false, true]
|
|||||||
defines.GC_FLAGS = 'LFS_GC_COMPACT'
|
defines.GC_FLAGS = 'LFS_GC_COMPACT'
|
||||||
defines.GC_STEPS = -1
|
defines.GC_STEPS = -1
|
||||||
defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2'
|
defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2'
|
||||||
|
if = 'LFS_IFDEF_GC(true, !COMPACT)'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
@@ -608,9 +612,11 @@ code = '''
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try compacting?
|
// try compacting?
|
||||||
|
#ifdef LFS_GC
|
||||||
if (COMPACT) {
|
if (COMPACT) {
|
||||||
lfsr_gc(&lfs) => 0;
|
lfsr_gc(&lfs) => 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
for (int remount = 0; remount < 2; remount++) {
|
for (int remount = 0; remount < 2; remount++) {
|
||||||
// remount?
|
// remount?
|
||||||
@@ -4074,6 +4080,7 @@ defines.COMPACT = [false, true]
|
|||||||
defines.GC_FLAGS = 'LFS_GC_COMPACT'
|
defines.GC_FLAGS = 'LFS_GC_COMPACT'
|
||||||
defines.GC_STEPS = -1
|
defines.GC_STEPS = -1
|
||||||
defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2'
|
defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2'
|
||||||
|
if = 'LFS_IFDEF_GC(true, !COMPACT)'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
@@ -4110,9 +4117,11 @@ code = '''
|
|||||||
}
|
}
|
||||||
|
|
||||||
// try compacting?
|
// try compacting?
|
||||||
|
#ifdef LFS_GC
|
||||||
if (COMPACT) {
|
if (COMPACT) {
|
||||||
lfsr_gc(&lfs) => 0;
|
lfsr_gc(&lfs) => 0;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
for (int remount = 0; remount < 2; remount++) {
|
for (int remount = 0; remount < 2; remount++) {
|
||||||
// remount?
|
// remount?
|
||||||
|
|||||||
+16
-2
@@ -24,7 +24,10 @@ defines.SIZE = [
|
|||||||
'2*BLOCK_SIZE',
|
'2*BLOCK_SIZE',
|
||||||
'8*BLOCK_SIZE',
|
'8*BLOCK_SIZE',
|
||||||
]
|
]
|
||||||
if = '(SIZE*N)/BLOCK_SIZE <= 32'
|
if = [
|
||||||
|
'(SIZE*N)/BLOCK_SIZE <= 32',
|
||||||
|
'LFS_IFDEF_GC(true, METHOD != 1)',
|
||||||
|
]
|
||||||
code = '''
|
code = '''
|
||||||
lfs_block_t i = 0;
|
lfs_block_t i = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -98,7 +101,11 @@ code = '''
|
|||||||
|
|
||||||
// find clobbered blocks with lfsr_gc
|
// find clobbered blocks with lfsr_gc
|
||||||
} else if (METHOD == 1) {
|
} else if (METHOD == 1) {
|
||||||
|
#ifdef LFS_GC
|
||||||
lfsr_gc(&lfs) => LFS_ERR_CORRUPT;
|
lfsr_gc(&lfs) => LFS_ERR_CORRUPT;
|
||||||
|
#else
|
||||||
|
LFS_UNREACHABLE();
|
||||||
|
#endif
|
||||||
|
|
||||||
// find clobbered blocks with lfsr_traversal_read
|
// find clobbered blocks with lfsr_traversal_read
|
||||||
} else if (METHOD == 2) {
|
} else if (METHOD == 2) {
|
||||||
@@ -154,7 +161,10 @@ defines.SIZE = [
|
|||||||
'2*BLOCK_SIZE',
|
'2*BLOCK_SIZE',
|
||||||
'8*BLOCK_SIZE',
|
'8*BLOCK_SIZE',
|
||||||
]
|
]
|
||||||
if = '(SIZE*N)/BLOCK_SIZE <= 32'
|
if = [
|
||||||
|
'(SIZE*N)/BLOCK_SIZE <= 32',
|
||||||
|
'LFS_IFDEF_GC(true, METHOD != 1)',
|
||||||
|
]
|
||||||
code = '''
|
code = '''
|
||||||
lfs_block_t i = 0;
|
lfs_block_t i = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -229,7 +239,11 @@ code = '''
|
|||||||
|
|
||||||
// find clobbered blocks with lfsr_gc
|
// find clobbered blocks with lfsr_gc
|
||||||
} else if (METHOD == 1) {
|
} else if (METHOD == 1) {
|
||||||
|
#ifdef LFS_GC
|
||||||
lfsr_gc(&lfs) => LFS_ERR_CORRUPT;
|
lfsr_gc(&lfs) => LFS_ERR_CORRUPT;
|
||||||
|
#else
|
||||||
|
LFS_UNREACHABLE();
|
||||||
|
#endif
|
||||||
|
|
||||||
// find clobbered blocks with lfsr_traversal_read
|
// find clobbered blocks with lfsr_traversal_read
|
||||||
} else if (METHOD == 2) {
|
} else if (METHOD == 2) {
|
||||||
|
|||||||
+27
-1
@@ -22,6 +22,7 @@ defines.SIZE = [
|
|||||||
'2*BLOCK_SIZE',
|
'2*BLOCK_SIZE',
|
||||||
'8*BLOCK_SIZE',
|
'8*BLOCK_SIZE',
|
||||||
]
|
]
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
@@ -85,6 +86,7 @@ defines.SIZE = [
|
|||||||
'2*BLOCK_SIZE',
|
'2*BLOCK_SIZE',
|
||||||
'8*BLOCK_SIZE',
|
'8*BLOCK_SIZE',
|
||||||
]
|
]
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
@@ -153,6 +155,7 @@ defines.SIZE = [
|
|||||||
'2*BLOCK_SIZE',
|
'2*BLOCK_SIZE',
|
||||||
'8*BLOCK_SIZE',
|
'8*BLOCK_SIZE',
|
||||||
]
|
]
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
@@ -216,6 +219,7 @@ defines.SIZE = [
|
|||||||
]
|
]
|
||||||
# we need something to keep the traversal running
|
# we need something to keep the traversal running
|
||||||
if = 'CKMETA || CKDATA'
|
if = 'CKMETA || CKDATA'
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
@@ -290,6 +294,7 @@ defines.SIZE = [
|
|||||||
]
|
]
|
||||||
# we need something to keep the traversal running
|
# we need something to keep the traversal running
|
||||||
if = 'CKMETA || CKDATA'
|
if = 'CKMETA || CKDATA'
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
@@ -358,6 +363,7 @@ defines.SIZE = [
|
|||||||
]
|
]
|
||||||
# we need something to keep the traversal running
|
# we need something to keep the traversal running
|
||||||
if = 'CKMETA || CKDATA'
|
if = 'CKMETA || CKDATA'
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
@@ -430,6 +436,7 @@ defines.SIZE = [
|
|||||||
'2*BLOCK_SIZE',
|
'2*BLOCK_SIZE',
|
||||||
'8*BLOCK_SIZE',
|
'8*BLOCK_SIZE',
|
||||||
]
|
]
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
@@ -518,6 +525,7 @@ defines.SIZE = [
|
|||||||
]
|
]
|
||||||
# we need something to keep the traversal running
|
# we need something to keep the traversal running
|
||||||
if = 'CKMETA || CKDATA'
|
if = 'CKMETA || CKDATA'
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
@@ -618,6 +626,7 @@ defines.SIZE = [
|
|||||||
]
|
]
|
||||||
# we need something to keep the traversal running
|
# we need something to keep the traversal running
|
||||||
if = 'CKMETA || CKDATA'
|
if = 'CKMETA || CKDATA'
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
@@ -713,6 +722,7 @@ defines.SIZE = [
|
|||||||
]
|
]
|
||||||
# we need something to keep the traversal running
|
# we need something to keep the traversal running
|
||||||
if = 'CKMETA || CKDATA'
|
if = 'CKMETA || CKDATA'
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
@@ -804,6 +814,7 @@ defines.SIZE = 'FILE_BUFFER_SIZE/2'
|
|||||||
# <=2 => grm-able
|
# <=2 => grm-able
|
||||||
# >2 => requires orphans
|
# >2 => requires orphans
|
||||||
defines.ORPHANS = [1, 2, 3, 100]
|
defines.ORPHANS = [1, 2, 3, 100]
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
@@ -953,7 +964,9 @@ code = '''
|
|||||||
struct lfs_fsinfo fsinfo;
|
struct lfs_fsinfo fsinfo;
|
||||||
lfsr_fs_stat(&lfs, &fsinfo) => 0;
|
lfsr_fs_stat(&lfs, &fsinfo) => 0;
|
||||||
assert(fsinfo.flags & LFS_I_INCONSISTENT);
|
assert(fsinfo.flags & LFS_I_INCONSISTENT);
|
||||||
|
#ifdef LFS_GC
|
||||||
assert(lfs.omdirs != &lfs.gc.t.o.o);
|
assert(lfs.omdirs != &lfs.gc.t.o.o);
|
||||||
|
#endif
|
||||||
|
|
||||||
// call lfsr_fs_mkconsistent
|
// call lfsr_fs_mkconsistent
|
||||||
lfsr_fs_mkconsistent(&lfs) => 0;
|
lfsr_fs_mkconsistent(&lfs) => 0;
|
||||||
@@ -1008,6 +1021,7 @@ defines.SIZE = 'FILE_BUFFER_SIZE/2'
|
|||||||
defines.ORPHANS = [3, 100]
|
defines.ORPHANS = [3, 100]
|
||||||
# we need something to keep the traversal running
|
# we need something to keep the traversal running
|
||||||
if = 'CKMETA || CKDATA'
|
if = 'CKMETA || CKDATA'
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
@@ -1123,7 +1137,7 @@ defines.SIZE = 'FILE_BUFFER_SIZE/2'
|
|||||||
defines.ORPHANS = [3, 100]
|
defines.ORPHANS = [3, 100]
|
||||||
# we need something to keep the traversal running
|
# we need something to keep the traversal running
|
||||||
if = 'CKMETA || CKDATA'
|
if = 'CKMETA || CKDATA'
|
||||||
in = 'lfs.c'
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
@@ -1237,6 +1251,7 @@ defines.SIZE = 'FILE_BUFFER_SIZE/2'
|
|||||||
defines.ORPHANS = [3, 100]
|
defines.ORPHANS = [3, 100]
|
||||||
# we need something to keep the traversal running
|
# we need something to keep the traversal running
|
||||||
if = 'CKMETA || CKDATA'
|
if = 'CKMETA || CKDATA'
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
@@ -1349,6 +1364,7 @@ defines.SIZE = [
|
|||||||
'8*BLOCK_SIZE',
|
'8*BLOCK_SIZE',
|
||||||
]
|
]
|
||||||
if = '(SIZE*N)/BLOCK_SIZE <= 32'
|
if = '(SIZE*N)/BLOCK_SIZE <= 32'
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_block_t i = 0;
|
lfs_block_t i = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -1448,6 +1464,7 @@ defines.SIZE = [
|
|||||||
'8*BLOCK_SIZE',
|
'8*BLOCK_SIZE',
|
||||||
]
|
]
|
||||||
if = '(SIZE*N)/BLOCK_SIZE <= 32'
|
if = '(SIZE*N)/BLOCK_SIZE <= 32'
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_block_t i = 0;
|
lfs_block_t i = 0;
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -1740,6 +1757,7 @@ defines.SIZE = [
|
|||||||
'2*BLOCK_SIZE',
|
'2*BLOCK_SIZE',
|
||||||
'8*BLOCK_SIZE',
|
'8*BLOCK_SIZE',
|
||||||
]
|
]
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
||||||
@@ -1808,6 +1826,7 @@ defines.SIZE = [
|
|||||||
'2*BLOCK_SIZE',
|
'2*BLOCK_SIZE',
|
||||||
'8*BLOCK_SIZE',
|
'8*BLOCK_SIZE',
|
||||||
]
|
]
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
lfsr_format(&lfs, LFS_F_RDWR, CFG) => 0;
|
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
|
# set compact thresh to minimum
|
||||||
defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2'
|
defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2'
|
||||||
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256]
|
defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256]
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
// test creating directories
|
// test creating directories
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
@@ -1976,6 +1996,7 @@ defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256]
|
|||||||
defines.OPS = '2*N'
|
defines.OPS = '2*N'
|
||||||
defines.SEED = 42
|
defines.SEED = 42
|
||||||
fuzz = 'SEED'
|
fuzz = 'SEED'
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
// test fuzz with dirs
|
// test fuzz with dirs
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
@@ -2151,6 +2172,7 @@ defines.SIZE = [
|
|||||||
'4*BLOCK_SIZE',
|
'4*BLOCK_SIZE',
|
||||||
]
|
]
|
||||||
if = '(SIZE*N)/BLOCK_SIZE <= 32'
|
if = '(SIZE*N)/BLOCK_SIZE <= 32'
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
// test creating files
|
// test creating files
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
@@ -2245,6 +2267,7 @@ defines.SIZE = [
|
|||||||
defines.SEED = 42
|
defines.SEED = 42
|
||||||
fuzz = 'SEED'
|
fuzz = 'SEED'
|
||||||
if = '(SIZE*N)/BLOCK_SIZE <= 16'
|
if = '(SIZE*N)/BLOCK_SIZE <= 16'
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
// test fuzz with files
|
// test fuzz with files
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
@@ -2484,6 +2507,7 @@ if = [
|
|||||||
# this just saves testing time
|
# this just saves testing time
|
||||||
'SIZE <= 4*1024*FRAGMENT_SIZE',
|
'SIZE <= 4*1024*FRAGMENT_SIZE',
|
||||||
]
|
]
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
// test with complex file writes
|
// test with complex file writes
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
@@ -2625,6 +2649,7 @@ defines.SIZE = [
|
|||||||
defines.SEED = 42
|
defines.SEED = 42
|
||||||
fuzz = 'SEED'
|
fuzz = 'SEED'
|
||||||
if = '(SIZE*N)/BLOCK_SIZE <= 16'
|
if = '(SIZE*N)/BLOCK_SIZE <= 16'
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
// test with uncreats, zombies, etc
|
// test with uncreats, zombies, etc
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
@@ -2983,6 +3008,7 @@ defines.SIZE = [
|
|||||||
defines.SEED = 42
|
defines.SEED = 42
|
||||||
fuzz = 'SEED'
|
fuzz = 'SEED'
|
||||||
if = '(SIZE*N)/BLOCK_SIZE <= 16'
|
if = '(SIZE*N)/BLOCK_SIZE <= 16'
|
||||||
|
ifdef = 'LFS_GC'
|
||||||
code = '''
|
code = '''
|
||||||
// test with uncreats, zombies, dirs, etc
|
// test with uncreats, zombies, dirs, etc
|
||||||
lfs_t lfs;
|
lfs_t lfs;
|
||||||
|
|||||||
Reference in New Issue
Block a user