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
+16
View File
@@ -229,6 +229,8 @@ enum lfs_type {
0x00002000 // Lookahead buffer is not full
#define LFS_I_UNCOMPACTED \
0x00008000 // Filesystem may have uncompacted metadata
#define LFS_I_CANCKMETA 0x00010000 // Metadata checksums not checked recently
#define LFS_I_CANCKDATA 0x00020000 // Data checksums not checked recently
// internally used flags, don't use these
#define LFS_I_UNTIDY 0x00001000 // Filesystem may have orphaned stickynotes
@@ -1270,6 +1272,20 @@ int lfsr_traversal_rewind(lfs_t *lfs, lfsr_traversal_t *t);
int lfsr_gc(lfs_t *lfs);
#endif
#ifdef LFS_GC
// Mark janitorial work as incomplete.
//
// Any info flags passed to lfsr_gc_unck will be reset internally,
// forcing the work to be redone.
//
// This is most useful for triggering new ckmeta/ckdata scans with
// LFS_I_CANCKMETA and LFS_I_CANCKDATA. Otherwise littlefs will perform
// only one scan after mount.
//
// Returns a negative error code on failure.
int lfsr_gc_unck(lfs_t *lfs, uint32_t flags);
#endif
/// Filesystem-level filesystem operations