trv: Reverted LFS3_t_NOSPC, forward gbmap repop errors

Note: This affects the blocking lfs3_alloc_repopgbmap as well as
incremental gc/traversal repopulations. Now all repop attempts return
LFS3_ERR_NOSPC when we don't have space for the gbmap, motivation below.

This reverts the previous LFS3_t_NOSPC soft error, in which traversals
were allowed to continue some gc/traversal work when encountering
LFS3_ERR_NOSPC. This results in a simpler implementation and fewer error
cases to worry about.

Observation/motivation:

- The main motivation is noticing that when we're in low-space
  conditions, we just start spamming gbmap repops even if they all fail.

  That's really not great! We might as well just mark the flash as dead
  if we're going to start spamming erases!

  At least with an error the user can call rmgbmap to try to make
  progress.

- If we're in a low-space condition, something else will probably return
  LFS3_ERR_NOSPC anyways. Might as well report this early and simplify
  our system.

- It's a simpler model, and littlefs3 is already much more complicated
  than littlefs2. Maybe we should lean more towards a simpler system
  at the cost of some niche optimizations.

---

This had the side-effect of causing more lfs3_alloc_ckpoints to return
errors during testing, which revealed a bug in our uz/uzd_fuzz tests:

- We weren't flushing after writes to the opened RDWR files, which could
  cause delayed errors to occur during the later read checks in the
  test.

  Fortunately LFS3_O_FLUSH provides a quick and easy fix!

  Note we _don't_ adopt this in all uz/uzd_fuzz tests, only those that
  error. It's good to test both with and without LFS3_O_FLUSH to test
  that read-flushing also works under stress.

Saves a bit of code:

                 code          stack          ctx
  before:       37260           2352          688
  after:        37220 (-0.1%)   2352 (+0.0%)  688 (+0.0%)

                 code          stack          ctx
  gbmap before: 40220           2368          856
  gbmap after:  40184 (-0.1%)   2368 (+0.0%)  856 (+0.0%)
This commit is contained in:
Christopher Haster
2025-10-20 13:55:58 -05:00
parent 9e4bbdf0ad
commit 5d70e47708
11 changed files with 120 additions and 93 deletions
+13 -66
View File
@@ -7461,7 +7461,7 @@ static inline void lfs3_t_settstate(uint32_t *flags, uint8_t tstate) {
} }
static inline uint8_t lfs3_t_btype(uint32_t flags) { static inline uint8_t lfs3_t_btype(uint32_t flags) {
return (flags >> 20) & 0x7; return (flags >> 20) & 0xf;
} }
static inline uint32_t lfs3_t_btypeflags(uint8_t btype) { static inline uint32_t lfs3_t_btypeflags(uint8_t btype) {
@@ -7484,10 +7484,6 @@ static inline bool lfs3_t_isckpointed(uint32_t flags) {
return flags & LFS3_t_CKPOINTED; return flags & LFS3_t_CKPOINTED;
} }
static inline bool lfs3_t_isnospc(uint32_t flags) {
return flags & LFS3_t_NOSPC;
}
// mount flags // mount flags
static inline bool lfs3_m_isrdonly(uint32_t flags) { static inline bool lfs3_m_isrdonly(uint32_t flags) {
(void)flags; (void)flags;
@@ -9827,6 +9823,8 @@ static int lfs3_mdir_commit(lfs3_t *lfs3, lfs3_mdir_t *mdir,
// checkpoint the allocator // checkpoint the allocator
int err = lfs3_alloc_ckpoint(lfs3); int err = lfs3_alloc_ckpoint(lfs3);
if (err) { if (err) {
// revert gstate to on-disk state
lfs3_fs_revertgdelta(lfs3);
return err; return err;
} }
@@ -10684,19 +10682,10 @@ static lfs3_stag_t lfs3_mtree_gc(lfs3_t *lfs3, lfs3_mgc_t *mgc,
// erased/bad info and (2) try to best use any available // erased/bad info and (2) try to best use any available
// erased-state // erased-state
int err = lfs3_alloc_zerogbmap(lfs3, &mgc->gbmap_); int err = lfs3_alloc_zerogbmap(lfs3, &mgc->gbmap_);
if (err && err != LFS3_ERR_NOSPC) { if (err) {
return err; return err;
} }
// not having enough space isn't really an error
if (err == LFS3_ERR_NOSPC) {
LFS3_WARN("Not enough space for gbmap "
"(lookahead %"PRId32"/%"PRId32")",
lfs3->lookahead.known,
lfs3->block_count);
mgc->t.b.h.flags |= LFS3_t_NOSPC;
}
// keep our own ckpointed flag clear // keep our own ckpointed flag clear
mgc->t.b.h.flags &= ~LFS3_t_CKPOINTED; mgc->t.b.h.flags &= ~LFS3_t_CKPOINTED;
} }
@@ -10733,19 +10722,10 @@ dropped:;
&& !lfs3_t_isckpointed(mgc->t.b.h.flags)) { && !lfs3_t_isckpointed(mgc->t.b.h.flags)) {
int err = lfs3_gbmap_markbptr(lfs3, &mgc->gbmap_, tag, bptr_, int err = lfs3_gbmap_markbptr(lfs3, &mgc->gbmap_, tag, bptr_,
LFS3_TAG_BMINUSE); LFS3_TAG_BMINUSE);
if (err && err != LFS3_ERR_NOSPC) { if (err) {
return err; return err;
} }
// not having enough space isn't really an error
if (err == LFS3_ERR_NOSPC) {
LFS3_WARN("Not enough space for gbmap "
"(lookahead %"PRId32"/%"PRId32")",
lfs3->lookahead.known,
lfs3->block_count);
mgc->t.b.h.flags |= LFS3_t_NOSPC;
}
// keep our own ckpointed flag clear // keep our own ckpointed flag clear
mgc->t.b.h.flags &= ~LFS3_t_CKPOINTED; mgc->t.b.h.flags &= ~LFS3_t_CKPOINTED;
} }
@@ -10758,19 +10738,10 @@ dropped:;
lfs3_mdir_t *mdir = (lfs3_mdir_t*)bptr_->d.u.buffer; lfs3_mdir_t *mdir = (lfs3_mdir_t*)bptr_->d.u.buffer;
uint32_t dirty = mgc->t.b.h.flags; uint32_t dirty = mgc->t.b.h.flags;
int err = lfs3_mdir_mkconsistent(lfs3, mdir); int err = lfs3_mdir_mkconsistent(lfs3, mdir);
if (err && err != LFS3_ERR_NOSPC) { if (err) {
return err; return err;
} }
// not having enough space isn't really an error
if (err == LFS3_ERR_NOSPC) {
LFS3_WARN("Not enough space for mkconsistent "
"(lookahead %"PRId32"/%"PRId32")",
lfs3->lookahead.known,
lfs3->block_count);
mgc->t.b.h.flags |= LFS3_t_NOSPC;
}
// reset dirty flag // reset dirty flag
mgc->t.b.h.flags &= ~LFS3_t_DIRTY | dirty; mgc->t.b.h.flags &= ~LFS3_t_DIRTY | dirty;
// make sure we clear any zombie flags // make sure we clear any zombie flags
@@ -10807,19 +10778,10 @@ dropped:;
// compact the mdir // compact the mdir
uint32_t dirty = mgc->t.b.h.flags; uint32_t dirty = mgc->t.b.h.flags;
int err = lfs3_mdir_compact(lfs3, mdir); int err = lfs3_mdir_compact(lfs3, mdir);
if (err && err != LFS3_ERR_NOSPC) { if (err) {
return err; return err;
} }
// not having enough space isn't really an error
if (err == LFS3_ERR_NOSPC) {
LFS3_WARN("Not enough space for compactmeta "
"(lookahead %"PRId32"/%"PRId32")",
lfs3->lookahead.known,
lfs3->block_count);
mgc->t.b.h.flags |= LFS3_t_NOSPC;
}
// reset dirty flag // reset dirty flag
mgc->t.b.h.flags &= ~LFS3_t_DIRTY | dirty; mgc->t.b.h.flags &= ~LFS3_t_DIRTY | dirty;
} }
@@ -10841,8 +10803,7 @@ eot:;
&& lfs3_f_isgbmap(lfs3->flags) && lfs3_f_isgbmap(lfs3->flags)
&& lfs3_t_isrepopgbmap(lfs3->flags) && lfs3_t_isrepopgbmap(lfs3->flags)
&& !lfs3_t_ismtreeonly(mgc->t.b.h.flags) && !lfs3_t_ismtreeonly(mgc->t.b.h.flags)
&& !lfs3_t_isckpointed(mgc->t.b.h.flags) && !lfs3_t_isckpointed(mgc->t.b.h.flags),
&& !lfs3_t_isnospc(mgc->t.b.h.flags),
false)) { false)) {
#ifdef LFS3_GBMAP #ifdef LFS3_GBMAP
lfs3_alloc_adoptgbmap(lfs3, &mgc->gbmap_, lfs3->lookahead.ckpoint); lfs3_alloc_adoptgbmap(lfs3, &mgc->gbmap_, lfs3->lookahead.ckpoint);
@@ -10857,16 +10818,14 @@ eot:;
// was mkconsistent successful? // was mkconsistent successful?
if (lfs3_t_ismkconsistent(mgc->t.b.h.flags) if (lfs3_t_ismkconsistent(mgc->t.b.h.flags)
&& !lfs3_t_isdirty(mgc->t.b.h.flags) && !lfs3_t_isdirty(mgc->t.b.h.flags)) {
&& !lfs3_t_isnospc(mgc->t.b.h.flags)) {
lfs3->flags &= ~LFS3_I_MKCONSISTENT; lfs3->flags &= ~LFS3_I_MKCONSISTENT;
} }
// was compaction successful? note we may need multiple passes if // was compaction successful? note we may need multiple passes if
// we want to be sure everything is compacted // we want to be sure everything is compacted
if (lfs3_t_compactmeta(mgc->t.b.h.flags) if (lfs3_t_compactmeta(mgc->t.b.h.flags)
&& !lfs3_t_ismutated(mgc->t.b.h.flags) && !lfs3_t_ismutated(mgc->t.b.h.flags)) {
&& !lfs3_t_isnospc(mgc->t.b.h.flags)) {
lfs3->flags &= ~LFS3_I_COMPACTMETA; lfs3->flags &= ~LFS3_I_COMPACTMETA;
} }
#endif #endif
@@ -11578,7 +11537,7 @@ static int lfs3_alloc_repopgbmap(lfs3_t *lfs3) {
// erased-state // erased-state
int err = lfs3_alloc_zerogbmap(lfs3, &gbmap_); int err = lfs3_alloc_zerogbmap(lfs3, &gbmap_);
if (err) { if (err) {
goto failed; return err;
} }
// traverse the filesystem, building up knowledge of what blocks are // traverse the filesystem, building up knowledge of what blocks are
@@ -11593,15 +11552,14 @@ static int lfs3_alloc_repopgbmap(lfs3_t *lfs3) {
if (tag == LFS3_ERR_NOENT) { if (tag == LFS3_ERR_NOENT) {
break; break;
} }
err = tag; return tag;
goto failed;
} }
// track in-use blocks // track in-use blocks
err = lfs3_gbmap_markbptr(lfs3, &gbmap_, tag, &bptr, err = lfs3_gbmap_markbptr(lfs3, &gbmap_, tag, &bptr,
LFS3_TAG_BMINUSE); LFS3_TAG_BMINUSE);
if (err) { if (err) {
goto failed; return err;
} }
} }
@@ -11614,17 +11572,6 @@ static int lfs3_alloc_repopgbmap(lfs3_t *lfs3) {
// //
lfs3_alloc_adoptgbmap(lfs3, &gbmap_, lfs3->lookahead.ckpoint); lfs3_alloc_adoptgbmap(lfs3, &gbmap_, lfs3->lookahead.ckpoint);
return 0; return 0;
failed:;
// not having enough space for the gbmap isn't really an error
if (err == LFS3_ERR_NOSPC) {
LFS3_INFO("Not enough space for gbmap "
"(lookahead %"PRId32"/%"PRId32")",
lfs3->lookahead.known,
lfs3->block_count);
return 0;
}
return err;
} }
#endif #endif
+1 -2
View File
@@ -342,13 +342,12 @@ enum lfs3_btype {
// internally used flags, don't use these // internally used flags, don't use these
#define LFS3_t_TYPE 0xf0000000 // The traversal's type #define LFS3_t_TYPE 0xf0000000 // The traversal's type
#define LFS3_t_TSTATE 0x000f0000 // The current traversal state #define LFS3_t_TSTATE 0x000f0000 // The current traversal state
#define LFS3_t_BTYPE 0x00700000 // The current block type #define LFS3_t_BTYPE 0x00f00000 // The current block type
#define LFS3_t_ZOMBIE 0x08000000 // File has been removed #define LFS3_t_ZOMBIE 0x08000000 // File has been removed
#define LFS3_t_DIRTY 0x04000000 // Filesystem modified outside traversal #define LFS3_t_DIRTY 0x04000000 // Filesystem modified outside traversal
#define LFS3_t_MUTATED 0x02000000 // Filesystem modified during traversal #define LFS3_t_MUTATED 0x02000000 // Filesystem modified during traversal
#define LFS3_t_CKPOINTED \ #define LFS3_t_CKPOINTED \
0x01000000 // Filesystem ckpointed during traversal 0x01000000 // Filesystem ckpointed during traversal
#define LFS3_t_NOSPC 0x00800000 // Optional gc work ran out of space
// GC flags // GC flags
#ifndef LFS3_RDONLY #ifndef LFS3_RDONLY
+1 -2
View File
@@ -165,7 +165,7 @@ FLAGS = [
('^_GBMAP', 0x00080000, "Tstate = gbmap" ), ('^_GBMAP', 0x00080000, "Tstate = gbmap" ),
('^_GBMAP_P', 0x00090000, "Tstate = gbmap_p" ), ('^_GBMAP_P', 0x00090000, "Tstate = gbmap_p" ),
('^_DONE', 0x000a0000, "Tstate = done" ), ('^_DONE', 0x000a0000, "Tstate = done" ),
('t_BTYPE', 0x00700000, "The current block type" ), ('t_BTYPE', 0x00f00000, "The current block type" ),
('^_MDIR', 0x00100000, "Btype = mdir" ), ('^_MDIR', 0x00100000, "Btype = mdir" ),
('^_BTREE', 0x00200000, "Btype = btree" ), ('^_BTREE', 0x00200000, "Btype = btree" ),
('^_DATA', 0x00300000, "Btype = data" ), ('^_DATA', 0x00300000, "Btype = data" ),
@@ -173,7 +173,6 @@ FLAGS = [
('t_DIRTY', 0x04000000, "Filesystem modified outside traversal" ), ('t_DIRTY', 0x04000000, "Filesystem modified outside traversal" ),
('t_MUTATED', 0x02000000, "Filesystem modified during traversal" ), ('t_MUTATED', 0x02000000, "Filesystem modified during traversal" ),
('t_CKPOINTED', 0x01000000, "Filesystem ckpointed during traversal" ), ('t_CKPOINTED', 0x01000000, "Filesystem ckpointed during traversal" ),
('t_NOSPC', 0x00800000, "Optional gc work ran out of space" ),
# Block allocator flags # Block allocator flags
('alloc_ERASE', 0x00000001, "Please erase the block" ), ('alloc_ERASE', 0x00000001, "Please erase the block" ),
+30 -6
View File
@@ -977,6 +977,8 @@ defines.BADBLOCK_BEHAVIOR = [
] ]
# we need prog checking to detect read errors # we need prog checking to detect read errors
defines.CKPROGS = 'BADBLOCK_BEHAVIOR >= LFS3_EMUBD_BADBLOCK_READERROR' defines.CKPROGS = 'BADBLOCK_BEHAVIOR >= LFS3_EMUBD_BADBLOCK_READERROR'
# you probably need to flush if you expect errors
defines.FLUSH = true
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.OPS = '2*N' defines.OPS = '2*N'
defines.SIZE = [ defines.SIZE = [
@@ -1070,7 +1072,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
lfs3_file_open(&lfs3, &sim_files[j]->file, name, lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT) => 0; LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0)) => 0;
// write some initial data if we don't exist // write some initial data if we don't exist
if (!exist || sticky) { if (!exist || sticky) {
@@ -1429,6 +1433,8 @@ defines.BADBLOCK_BEHAVIOR = [
] ]
# we need prog checking to detect read errors # we need prog checking to detect read errors
defines.CKPROGS = 'BADBLOCK_BEHAVIOR >= LFS3_EMUBD_BADBLOCK_READERROR' defines.CKPROGS = 'BADBLOCK_BEHAVIOR >= LFS3_EMUBD_BADBLOCK_READERROR'
# you probably need to flush if you expect errors
defines.FLUSH = true
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.OPS = '2*N' defines.OPS = '2*N'
defines.SIZE = [ defines.SIZE = [
@@ -1526,7 +1532,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
lfs3_file_open(&lfs3, &sim_files[j]->file, name, lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT) => 0; LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0)) => 0;
// write some initial data if we don't exist // write some initial data if we don't exist
if (!exist || sticky) { if (!exist || sticky) {
@@ -2933,6 +2941,8 @@ defines.BADBLOCK_BEHAVIOR = [
# we need prog checking to detect read errors # we need prog checking to detect read errors
defines.CKPROGS = 'BADBLOCK_BEHAVIOR >= LFS3_EMUBD_BADBLOCK_READERROR' defines.CKPROGS = 'BADBLOCK_BEHAVIOR >= LFS3_EMUBD_BADBLOCK_READERROR'
defines.MIRROR = [false, true] defines.MIRROR = [false, true]
# you probably need to flush if you expect errors
defines.FLUSH = true
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.OPS = '2*N' defines.OPS = '2*N'
defines.SIZE = [ defines.SIZE = [
@@ -3031,7 +3041,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
lfs3_file_open(&lfs3, &sim_files[j]->file, name, lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT) => 0; LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0)) => 0;
// write some initial data if we don't exist // write some initial data if we don't exist
if (!exist || sticky) { if (!exist || sticky) {
@@ -3386,6 +3398,8 @@ defines.BADBLOCK_BEHAVIOR = [
# we need prog checking to detect read errors # we need prog checking to detect read errors
defines.CKPROGS = 'BADBLOCK_BEHAVIOR >= LFS3_EMUBD_BADBLOCK_READERROR' defines.CKPROGS = 'BADBLOCK_BEHAVIOR >= LFS3_EMUBD_BADBLOCK_READERROR'
defines.MIRROR = [false, true] defines.MIRROR = [false, true]
# you probably need to flush if you expect errors
defines.FLUSH = true
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.OPS = '2*N' defines.OPS = '2*N'
defines.SIZE = [ defines.SIZE = [
@@ -3488,7 +3502,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
lfs3_file_open(&lfs3, &sim_files[j]->file, name, lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT) => 0; LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0)) => 0;
// write some initial data if we don't exist // write some initial data if we don't exist
if (!exist || sticky) { if (!exist || sticky) {
@@ -4888,6 +4904,8 @@ defines.BADBLOCK_BEHAVIOR = [
# we need prog checking to detect read errors # we need prog checking to detect read errors
defines.CKPROGS = 'BADBLOCK_BEHAVIOR >= LFS3_EMUBD_BADBLOCK_READERROR' defines.CKPROGS = 'BADBLOCK_BEHAVIOR >= LFS3_EMUBD_BADBLOCK_READERROR'
defines.MIRROR = [false, true] defines.MIRROR = [false, true]
# you probably need to flush if you expect errors
defines.FLUSH = true
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.OPS = '2*N' defines.OPS = '2*N'
defines.SIZE = [ defines.SIZE = [
@@ -4986,7 +5004,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
lfs3_file_open(&lfs3, &sim_files[j]->file, name, lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT) => 0; LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0)) => 0;
// write some initial data if we don't exist // write some initial data if we don't exist
if (!exist || sticky) { if (!exist || sticky) {
@@ -5341,6 +5361,8 @@ defines.BADBLOCK_BEHAVIOR = [
# we need prog checking to detect read errors # we need prog checking to detect read errors
defines.CKPROGS = 'BADBLOCK_BEHAVIOR >= LFS3_EMUBD_BADBLOCK_READERROR' defines.CKPROGS = 'BADBLOCK_BEHAVIOR >= LFS3_EMUBD_BADBLOCK_READERROR'
defines.MIRROR = [false, true] defines.MIRROR = [false, true]
# you probably need to flush if you expect errors
defines.FLUSH = true
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.OPS = '2*N' defines.OPS = '2*N'
defines.SIZE = [ defines.SIZE = [
@@ -5443,7 +5465,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
lfs3_file_open(&lfs3, &sim_files[j]->file, name, lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT) => 0; LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0)) => 0;
// write some initial data if we don't exist // write some initial data if we don't exist
if (!exist || sticky) { if (!exist || sticky) {
+10 -2
View File
@@ -3746,6 +3746,8 @@ defines.CKPROGS = 'METHOD == 0'
defines.CKFETCHES = 'METHOD == 2' defines.CKFETCHES = 'METHOD == 2'
defines.CKMETAPARITY = false defines.CKMETAPARITY = false
defines.CKDATACKSUMS = 'METHOD == 3' defines.CKDATACKSUMS = 'METHOD == 3'
# you probably need to flush if you expect errors
defines.FLUSH = true
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.SIZE = [ defines.SIZE = [
'0', '0',
@@ -3922,7 +3924,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
int err = lfs3_file_open(&lfs3, &sim_files[j]->file, name, int err = lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT); LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0));
assert(!err || err == LFS3_ERR_NOSPC); assert(!err || err == LFS3_ERR_NOSPC);
if (err == LFS3_ERR_NOSPC) { if (err == LFS3_ERR_NOSPC) {
free(sim_files[j]); free(sim_files[j]);
@@ -4345,6 +4349,8 @@ defines.CKPROGS = 'METHOD == 0'
defines.CKFETCHES = 'METHOD == 2' defines.CKFETCHES = 'METHOD == 2'
defines.CKMETAPARITY = false defines.CKMETAPARITY = false
defines.CKDATACKSUMS = 'METHOD == 3' defines.CKDATACKSUMS = 'METHOD == 3'
# you probably need to flush if you expect errors
defines.FLUSH = true
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.SIZE = [ defines.SIZE = [
'0', '0',
@@ -4525,7 +4531,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
int err = lfs3_file_open(&lfs3, &sim_files[j]->file, name, int err = lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT); LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0));
assert(!err || err == LFS3_ERR_NOSPC); assert(!err || err == LFS3_ERR_NOSPC);
if (err == LFS3_ERR_NOSPC) { if (err == LFS3_ERR_NOSPC) {
free(sim_files[j]); free(sim_files[j]);
+10 -2
View File
@@ -707,6 +707,8 @@ defines.BADBLOCK_BEHAVIOR = [
] ]
# we need prog checking to detect read errors # we need prog checking to detect read errors
defines.CKPROGS = 'BADBLOCK_BEHAVIOR >= LFS3_EMUBD_BADBLOCK_READERROR' defines.CKPROGS = 'BADBLOCK_BEHAVIOR >= LFS3_EMUBD_BADBLOCK_READERROR'
# you probably need to flush if you expect errors
defines.FLUSH = true
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.SIZE = [ defines.SIZE = [
'0', '0',
@@ -806,7 +808,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
int err = lfs3_file_open(&lfs3, &sim_files[j]->file, name, int err = lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT); LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0));
assert(!err || err == LFS3_ERR_NOSPC); assert(!err || err == LFS3_ERR_NOSPC);
if (err == LFS3_ERR_NOSPC) { if (err == LFS3_ERR_NOSPC) {
free(sim_files[j]); free(sim_files[j]);
@@ -1212,6 +1216,8 @@ defines.BADBLOCK_BEHAVIOR = [
] ]
# we need prog checking to detect read errors # we need prog checking to detect read errors
defines.CKPROGS = 'BADBLOCK_BEHAVIOR >= LFS3_EMUBD_BADBLOCK_READERROR' defines.CKPROGS = 'BADBLOCK_BEHAVIOR >= LFS3_EMUBD_BADBLOCK_READERROR'
# you probably need to flush if you expect errors
defines.FLUSH = true
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.SIZE = [ defines.SIZE = [
'0', '0',
@@ -1315,7 +1321,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
int err = lfs3_file_open(&lfs3, &sim_files[j]->file, name, int err = lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT); LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0));
assert(!err || err == LFS3_ERR_NOSPC); assert(!err || err == LFS3_ERR_NOSPC);
if (err == LFS3_ERR_NOSPC) { if (err == LFS3_ERR_NOSPC) {
free(sim_files[j]); free(sim_files[j]);
+15 -5
View File
@@ -2659,9 +2659,11 @@ code = '''
} }
// gc! // gc!
// err = lfs3_fs_gc(&lfs3);
// gc should not error, but may be unable to make progress assert(!err || err == LFS3_ERR_NOSPC);
lfs3_fs_gc(&lfs3) => 0; if (err == LFS3_ERR_NOSPC) {
break;
}
} }
// check the contents of the files that were written // check the contents of the files that were written
@@ -3529,6 +3531,8 @@ defines.GC_FLAGS = '''
defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000]
# set compactmeta thresh to minimum # set compactmeta thresh to minimum
defines.GC_COMPACTMETA_THRESH = 'BLOCK_SIZE/2' defines.GC_COMPACTMETA_THRESH = 'BLOCK_SIZE/2'
# you probably need to flush if you expect errors
defines.FLUSH = false
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.OPS = '2*N' defines.OPS = '2*N'
defines.SIZE = [ defines.SIZE = [
@@ -3611,7 +3615,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
lfs3_file_open(&lfs3, &sim_files[j]->file, name, lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT) => 0; LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0)) => 0;
// write some initial data if we don't exist // write some initial data if we don't exist
if (!exist || sticky) { if (!exist || sticky) {
@@ -3981,6 +3987,8 @@ defines.GC_FLAGS = '''
defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000] defines.GC_STEPS = [-1, 1, 2, 10, 100, 1000]
# set compactmeta thresh to minimum # set compactmeta thresh to minimum
defines.GC_COMPACTMETA_THRESH = 'BLOCK_SIZE/2' defines.GC_COMPACTMETA_THRESH = 'BLOCK_SIZE/2'
# you probably need to flush if you expect errors
defines.FLUSH = false
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.OPS = '2*N' defines.OPS = '2*N'
defines.SIZE = [ defines.SIZE = [
@@ -4067,7 +4075,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
lfs3_file_open(&lfs3, &sim_files[j]->file, name, lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT) => 0; LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0)) => 0;
// write some initial data if we don't exist // write some initial data if we don't exist
if (!exist || sticky) { if (!exist || sticky) {
+10 -2
View File
@@ -1267,6 +1267,8 @@ code = '''
''' '''
[cases.test_grow_incr_spam_uz_fuzz] [cases.test_grow_incr_spam_uz_fuzz]
# you probably need to flush if you expect errors
defines.FLUSH = true
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.OPS = 1024 defines.OPS = 1024
defines.SIZE = [ defines.SIZE = [
@@ -1358,7 +1360,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
int err = lfs3_file_open(&lfs3, &sim_files[j]->file, name, int err = lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT); LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0));
assert(!err || err == LFS3_ERR_NOSPC); assert(!err || err == LFS3_ERR_NOSPC);
if (err == LFS3_ERR_NOSPC) { if (err == LFS3_ERR_NOSPC) {
free(sim_files[j]); free(sim_files[j]);
@@ -1769,6 +1773,8 @@ code = '''
''' '''
[cases.test_grow_incr_spam_uzd_fuzz] [cases.test_grow_incr_spam_uzd_fuzz]
# you probably need to flush if you expect errors
defines.FLUSH = true
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.OPS = 1024 defines.OPS = 1024
defines.SIZE = [ defines.SIZE = [
@@ -1864,7 +1870,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
int err = lfs3_file_open(&lfs3, &sim_files[j]->file, name, int err = lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT); LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0));
assert(!err || err == LFS3_ERR_NOSPC); assert(!err || err == LFS3_ERR_NOSPC);
if (err == LFS3_ERR_NOSPC) { if (err == LFS3_ERR_NOSPC) {
free(sim_files[j]); free(sim_files[j]);
+10 -2
View File
@@ -530,6 +530,8 @@ code = '''
# open files + relocations may create problems for uncreats/zombies # open files + relocations may create problems for uncreats/zombies
[cases.test_relocations_spam_uz_fuzz] [cases.test_relocations_spam_uz_fuzz]
defines.BLOCK_RECYCLES = [4, 1, 0] defines.BLOCK_RECYCLES = [4, 1, 0]
# you probably need to flush if you expect errors
defines.FLUSH = false
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.OPS = 1024 defines.OPS = 1024
defines.SIZE = [ defines.SIZE = [
@@ -604,7 +606,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
lfs3_file_open(&lfs3, &sim_files[j]->file, name, lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT) => 0; LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0)) => 0;
// write some initial data if we don't exist // write some initial data if we don't exist
if (!exist || sticky) { if (!exist || sticky) {
@@ -951,6 +955,8 @@ code = '''
# listing them # listing them
[cases.test_relocations_spam_uzd_fuzz] [cases.test_relocations_spam_uzd_fuzz]
defines.BLOCK_RECYCLES = [4, 1, 0] defines.BLOCK_RECYCLES = [4, 1, 0]
# you probably need to flush if you expect errors
defines.FLUSH = false
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.OPS = 1024 defines.OPS = 1024
defines.SIZE = [ defines.SIZE = [
@@ -1029,7 +1035,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
lfs3_file_open(&lfs3, &sim_files[j]->file, name, lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT) => 0; LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0)) => 0;
// write some initial data if we don't exist // write some initial data if we don't exist
if (!exist || sticky) { if (!exist || sticky) {
+10 -2
View File
@@ -10822,6 +10822,8 @@ code = '''
# fuzz tests involving many uncreats + zombies, this gets a bit crazy # fuzz tests involving many uncreats + zombies, this gets a bit crazy
[cases.test_stickynotes_uz_fuzz] [cases.test_stickynotes_uz_fuzz]
# you probably need to flush if you expect errors
defines.FLUSH = false
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
# do more ops than files to encourage file rewrites # do more ops than files to encourage file rewrites
defines.OPS = '2*N' defines.OPS = '2*N'
@@ -10897,7 +10899,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
lfs3_file_open(&lfs3, &sim_files[j]->file, name, lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT) => 0; LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0)) => 0;
// write some initial data if we don't exist // write some initial data if we don't exist
if (!exist || sticky) { if (!exist || sticky) {
@@ -11242,6 +11246,8 @@ code = '''
# fuzz tests involving many uncreats + zombies + dirs, this gets a bit crazy # fuzz tests involving many uncreats + zombies + dirs, this gets a bit crazy
[cases.test_stickynotes_uzd_fuzz] [cases.test_stickynotes_uzd_fuzz]
# you probably need to flush if you expect errors
defines.FLUSH = false
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
# do more ops than files to encourage file rewrites # do more ops than files to encourage file rewrites
defines.OPS = '2*N' defines.OPS = '2*N'
@@ -11321,7 +11327,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
lfs3_file_open(&lfs3, &sim_files[j]->file, name, lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT) => 0; LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0)) => 0;
// write some initial data if we don't exist // write some initial data if we don't exist
if (!exist || sticky) { if (!exist || sticky) {
+10 -2
View File
@@ -9252,6 +9252,8 @@ defines.CKMETA = [true]
defines.CKDATA = [true] defines.CKDATA = [true]
# set compactmeta thresh to minimum # set compactmeta thresh to minimum
defines.GC_COMPACTMETA_THRESH = 'BLOCK_SIZE/2' defines.GC_COMPACTMETA_THRESH = 'BLOCK_SIZE/2'
# you probably need to flush if you expect errors
defines.FLUSH = false
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.OPS = '2*N' defines.OPS = '2*N'
defines.SIZE = [ defines.SIZE = [
@@ -9346,7 +9348,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
lfs3_file_open(&lfs3, &sim_files[j]->file, name, lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT) => 0; LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0)) => 0;
// write some initial data if we don't exist // write some initial data if we don't exist
if (!exist || sticky) { if (!exist || sticky) {
@@ -9713,6 +9717,8 @@ defines.CKMETA = [true]
defines.CKDATA = [true] defines.CKDATA = [true]
# set compactmeta thresh to minimum # set compactmeta thresh to minimum
defines.GC_COMPACTMETA_THRESH = 'BLOCK_SIZE/2' defines.GC_COMPACTMETA_THRESH = 'BLOCK_SIZE/2'
# you probably need to flush if you expect errors
defines.FLUSH = false
defines.N = [1, 2, 4, 8, 16, 32, 64] defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.OPS = '2*N' defines.OPS = '2*N'
defines.SIZE = [ defines.SIZE = [
@@ -9811,7 +9817,9 @@ code = '''
char name[256]; char name[256];
sprintf(name, "batman%03x", x); sprintf(name, "batman%03x", x);
lfs3_file_open(&lfs3, &sim_files[j]->file, name, lfs3_file_open(&lfs3, &sim_files[j]->file, name,
LFS3_O_RDWR | LFS3_O_CREAT) => 0; LFS3_O_RDWR
| LFS3_O_CREAT
| ((FLUSH) ? LFS3_O_FLUSH : 0)) => 0;
// write some initial data if we don't exist // write some initial data if we don't exist
if (!exist || sticky) { if (!exist || sticky) {