gc: Made CKMETA/CKDATA progressable, added lfsr_gc_unck

LFS_GC_CKMETA and LFS_GC_CKDATA are a bit unique in that their work is
never really done.

Where LFS_GC_MKCONSISTENT/COMPACT can prove things about the system,
LFS_GC_CKMETA/CKDATA can't, because it's always possible for new
bit-errors to develop. Even _during_ an LFS_GC_CKMETA/CKDATA traversal.

But while this is technically true, it's not a very useful state of
things for our lfsr_gc API...

---

What we really want is some way to know if ckmeta/ckdata has completed
"recently" (for some definition of recently), and to let users indicate
when they need another ckmeta/ckdata scan.

To try to solve this:

1. Added LFS_I_CANCKMETA and LFS_I_CANCKDATA to indicate when lfsr_gc
   has not checked metadata/data.

   These are set during mount (unless mounting with
   LFS_M_CKMETA/CKDATA), and cleared when either lfsr_gc completes or
   lfsr_fs_ckmeta/data is called. Once cleared, littlefs will not reset
   them on its own.

2. Added lfsr_gc_unck to allow users to explicitly reset LFS_I_CKMETA
   and/or LFS_I_CKDATA, which will tell lfsr_gc to check metadata/data
   again on the next call.

   There is some subtlety around clobbering ongoing traversals, but a
   mask and some tests should prevent this from being a problem.

   Currently, lfsr_gc_unck also allows clearing of other gc flags, but
   I'm not sure there's any real use-case for this...

Note that you can still get the previous behavior if you just call
lfsr_gc_unck after every lfsr_gc call.

This also changes info flag behavior slightly in default mode, with
LFS_I_CANCKMETA/CANCKDATA telling you if metadata/data has been checked
since mount. Which does seem useful? Maybe these flags deserve a better
name?

Code changes:

                   code          stack          ctx
  default before: 37796 (+0.0%)   2608 (+0.0%)  620 (+0.0%)
  default after:  37792 (+0.0%)   2608 (+0.0%)  620 (+0.0%)

  gc before:      37896           2608          768
  gc after:       37938 (+0.1%)   2608 (+0.0%)  768 (+0.0.%)
This commit is contained in:
Christopher Haster
2025-01-07 13:44:04 -06:00
parent 0617244aa3
commit 39d488a1ef
5 changed files with 764 additions and 125 deletions
+21 -7
View File
@@ -74,7 +74,9 @@ code = '''
: 0)
| ((!MKCONSISTENT) ? LFS_I_INCONSISTENT : 0)
| ((!LOOKAHEAD) ? LFS_I_CANLOOKAHEAD : 0)
| ((!COMPACT) ? LFS_I_UNCOMPACTED : 0)));
| ((!COMPACT) ? LFS_I_UNCOMPACTED : 0)
| ((!CKMETA) ? LFS_I_CANCKMETA : 0)
| ((!CKDATA) ? LFS_I_CANCKDATA : 0)));
lfsr_unmount(&lfs) => 0;
'''
@@ -135,7 +137,9 @@ code = '''
assert(fsinfo.flags == (
LFS_I_INCONSISTENT
| LFS_I_CANLOOKAHEAD
| LFS_I_UNCOMPACTED));
| LFS_I_UNCOMPACTED
| LFS_I_CANCKMETA
| LFS_I_CANCKDATA));
lfsr_unmount(&lfs) => 0;
// with LFS_M_LOOKAHEAD, mount performs a lookahead scan
@@ -148,7 +152,9 @@ code = '''
lfsr_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.flags == (
LFS_I_INCONSISTENT
| LFS_I_UNCOMPACTED));
| LFS_I_UNCOMPACTED
| ((!CKMETA) ? LFS_I_CANCKMETA : 0)
| ((!CKDATA) ? LFS_I_CANCKDATA : 0)));
lfsr_unmount(&lfs) => 0;
'''
@@ -201,7 +207,9 @@ code = '''
assert(fsinfo.flags == (
LFS_I_INCONSISTENT
| LFS_I_CANLOOKAHEAD
| LFS_I_UNCOMPACTED));
| LFS_I_UNCOMPACTED
| LFS_I_CANCKMETA
| LFS_I_CANCKDATA));
lfsr_unmount(&lfs) => 0;
// with LFS_M_COMPACT, mount compact any uncompacted blocks
@@ -215,7 +223,9 @@ code = '''
lfsr_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.flags == (
LFS_I_INCONSISTENT
| ((!LOOKAHEAD) ? LFS_I_CANLOOKAHEAD : 0)));
| ((!LOOKAHEAD) ? LFS_I_CANLOOKAHEAD : 0)
| ((!CKMETA) ? LFS_I_CANCKMETA : 0)
| ((!CKDATA) ? LFS_I_CANCKDATA : 0)));
// mdir should have been compacted
lfsr_file_open(&lfs, &file, "jellyfish", LFS_O_RDONLY) => 0;
@@ -295,7 +305,9 @@ code = '''
assert(fsinfo.flags == (
LFS_I_INCONSISTENT
| LFS_I_CANLOOKAHEAD
| LFS_I_UNCOMPACTED));
| LFS_I_UNCOMPACTED
| LFS_I_CANCKMETA
| LFS_I_CANCKDATA));
lfsr_unmount(&lfs) => 0;
// with LFS_M_MKCONSISTENT, mount cleans up orphans eagerly
@@ -310,7 +322,9 @@ code = '''
lfsr_fs_stat(&lfs, &fsinfo) => 0;
assert(fsinfo.flags == (
((!LOOKAHEAD) ? LFS_I_CANLOOKAHEAD : 0)
| ((!COMPACT) ? LFS_I_UNCOMPACTED : 0)));
| ((!COMPACT) ? LFS_I_UNCOMPACTED : 0)
| ((!CKMETA) ? LFS_I_CANCKMETA : 0)
| ((!CKDATA) ? LFS_I_CANCKDATA : 0)));
// check we can still read the files
lfsr_file_open(&lfs, &file, "cuttlefish", LFS_O_RDONLY) => 0;