ck: Traded ckmeta/ckdata for flag-based ck functions

TLDR: Replaced lfs3_file_ckmeta/ckdata and lfs3_fs_ckmeta/ckdata with
flag based ck functions:

- lfs3_file_ckmeta -> lfs3_file_ck + LFS3_CK_CKMETA
- lfs3_file_ckdata -> lfs3_file_ck + LFS3_CK_CKDATA
- lfs3_fs_ckmeta -> lfs3_fs_ck + LFS3_FSCK_CKMETA
- lfs3_fs_ckdata -> lfs3_fs_ck + LFS3_FSCK_CKDATA

Note lfs3_fs_ck is equivalent to lfs3_fs_gc, but:

1. Performs the work in one call (equivalent to littlefs2's lfs2_fs_gc)
2. Takes flags at call time (like lfs3_mount) instead of cfg time (like
   lfs3_fs_gc)
3. Avoids the constant RAM necessary to track incremental GC state

---

Motivation:

I've been thinking: It's a bit weird that users are able to one-shot
janitorial work in lfs3_mount, but there's no equivalent function after
the filesystem is mounted.

Originally this is what lfs3_fs_gc was for, but after adding support for
incremental GC, it made sense to hide lfs3_fs_gc behind the opt-in
LFS3_GC ifdef due to the extra (ironically non-gc-able) state.

In theory lfs3_trv_t fills a bit of the gap, but, without the internal
i_flag handling and traversal restarts, it's a bit hard to use. And
basically requires duplicating said log, which we need anyways for
lfs3_mount!

So ideally we'd add an explicit one-shot GC function, but now lfs3_fs_gc
is taken.

While thinking about alternative names, I realized we can just call this
lfs3_fs_ck and completely replace lfs3_fs_ckmeta/ckdata.

This has some extra benefits:

- Avoids an explosion of ckmeta/ckdata/repairmeta/repairdata functions
- Discourages redundant traversals that could accomplish more work
- Makes it less confusing that ckdata implies ckmeta

---

I also tweaked lfs3_file_ck to match, but note that lfs3_file_ck is
internally very different from lfs3_fs_ck. For one, lfs3_file_ck only
supports "actual" check flags (LFS3_CK_*) vs all gc flags (LFS3_FSCK_*):

lfs3_file_ck:

  LFS3_CK_CKMETA          0x00010000  Check metadata checksums
  LFS3_CK_CKDATA          0x00020000  Check metadata + data checksums
  LFS3_CK_REPAIRMETA*     0x00040000  Repair metadata blocks
  LFS3_CK_REPAIRDATA*     0x00080000  Repair metadata + data blocks

  * Planned

lfs3_fs_ck:

  LFS3_FSCK_MKCONSISTENT  0x00000800  Make the filesystem consistent
  LFS3_FSCK_LOOKAHEAD     0x00001000  Repopulate lookahead buffer
  LFS3_FSCK_LOOKGBMAP     0x00002000  Repopulate the gbmap
  LFS3_FSCK_PREERASE*     0x00004000  Pre-erase unused blocks
  LFS3_FSCK_COMPACTMETA   0x00008000  Compact metadata logs
  LFS3_FSCK_CKMETA        0x00010000  Check metadata checksums
  LFS3_FSCK_CKDATA        0x00020000  Check metadata + data checksums
  LFS3_FSCK_REPAIRMETA*   0x00040000  Repair metadata blocks
  LFS3_FSCK_REPAIRDATA*   0x00080000  Repair metadata + data blocks

  * Planned

As a plus, this also saves a bit of code:

                 code          stack          ctx
  before:       35968           2280          660
  after:        35924 (-0.1%)   2280 (+0.0%)  660 (+0.0%)

                 code          stack          ctx
  gbmap before: 38828           2296          772
  gbmap after:  38812 (-0.0%)   2296 (+0.0%)  772 (+0.0%)
This commit is contained in:
Christopher Haster
2025-11-15 23:27:25 -06:00
parent ad2e8b3498
commit 5c0cebb00b
5 changed files with 207 additions and 224 deletions
+64 -32
View File
@@ -362,6 +362,47 @@ enum lfs3_btype {
#define LFS3_t_DIRTY 0x02000000 // Filesystem ckpointed outside traversal
#define LFS3_t_STALE 0x01000000 // Block queue probably out-of-date
// File check flags
#define LFS3_CK_CKMETA 0x00010000 // Check metadata checksums
#define LFS3_CK_CKDATA 0x00020000 // Check metadata + data checksums
// an alias for all possible file check work
#define LFS3_CK_ALL ( \
LFS3_GC_CKMETA \
| LFS3_GC_CKDATA)
// Filesystem check flags
#ifndef LFS3_RDONLY
#define LFS3_FSCK_MKCONSISTENT \
0x00000800 // Make the filesystem consistent
#endif
#ifndef LFS3_RDONLY
#define LFS3_FSCK_LOOKAHEAD \
0x00001000 // Repopulate lookahead buffer
#endif
#if !defined(LFS3_RDONLY) && defined(LFS3_GBMAP)
#define LFS3_FSCK_LOOKGBMAP \
0x00002000 // Repopulate the gbmap
#endif
#ifndef LFS3_RDONLY
#define LFS3_FSCK_COMPACTMETA \
0x00008000 // Compact metadata logs
#endif
#define LFS3_FSCK_CKMETA \
0x00010000 // Check metadata checksums
#define LFS3_FSCK_CKDATA \
0x00020000 // Check metadata + data checksums
// an alias for all possible filesystem check work
#define LFS3_FSCK_ALL ( \
LFS3_IFDEF_RDONLY(0, LFS3_FSCK_MKCONSISTENT) \
| LFS3_IFDEF_RDONLY(0, LFS3_FSCK_LOOKAHEAD) \
| LFS3_IFDEF_RDONLY(0, \
LFS3_IFDEF_GBMAP(LFS3_FSCK_LOOKGBMAP, 0)) \
| LFS3_IFDEF_RDONLY(0, LFS3_FSCK_COMPACTMETA) \
| LFS3_FSCK_CKMETA \
| LFS3_FSCK_CKDATA)
// GC flags
#ifndef LFS3_RDONLY
#define LFS3_GC_MKCONSISTENT \
@@ -1550,17 +1591,11 @@ int lfs3_file_rewind(lfs3_t *lfs3, lfs3_file_t *file);
// Returns the size of the file, or a negative error code on failure.
lfs3_soff_t lfs3_file_size(lfs3_t *lfs3, lfs3_file_t *file);
// Check a file for metadata errors
// Check a file for errors and other work
//
// Returns LFS3_ERR_CORRUPT if a checksum mismatch is found, or a negative
// error code on failure.
int lfs3_file_ckmeta(lfs3_t *lfs3, lfs3_file_t *file);
// Check a file for metadata + data errors
//
// Returns LFS3_ERR_CORRUPT if a checksum mismatch is found, or a negative
// error code on failure.
int lfs3_file_ckdata(lfs3_t *lfs3, lfs3_file_t *file);
int lfs3_file_ck(lfs3_t *lfs3, lfs3_file_t *file, uint32_t flags);
/// Directory operations ///
@@ -1660,30 +1695,6 @@ int lfs3_fs_stat(lfs3_t *lfs3, struct lfs3_fsinfo *fsinfo);
// Returns the number of allocated blocks, or a negative error code on failure.
lfs3_ssize_t lfs3_fs_usage(lfs3_t *lfs3);
// Attempt to make the filesystem consistent and ready for writing
//
// Calling this function is not required, consistency will be implicitly
// enforced on the first operation that writes to the filesystem, but this
// function allows the work to be performed earlier and without other
// filesystem changes.
//
// Returns a negative error code on failure.
#ifndef LFS3_RDONLY
int lfs3_fs_mkconsistent(lfs3_t *lfs3);
#endif
// Check the filesystem for metadata errors
//
// Returns LFS3_ERR_CORRUPT if a checksum mismatch is found, or a negative
// error code on failure.
int lfs3_fs_ckmeta(lfs3_t *lfs3);
// Check the filesystem for metadata + data errors
//
// Returns LFS3_ERR_CORRUPT if a checksum mismatch is found, or a negative
// error code on failure.
int lfs3_fs_ckdata(lfs3_t *lfs3);
// Get the current filesystem checksum
//
// This is a checksum of all metadata + data in the filesystem, which
@@ -1700,6 +1711,27 @@ int lfs3_fs_ckdata(lfs3_t *lfs3);
// Returns a negative error code on failure.
int lfs3_fs_cksum(lfs3_t *lfs3, uint32_t *cksum);
// Attempt to make the filesystem consistent and ready for writing
//
// Calling this function is not required, consistency will be implicitly
// enforced on the first operation that writes to the filesystem, but this
// function allows the work to be performed earlier and without other
// filesystem changes.
//
// Returns a negative error code on failure.
#ifndef LFS3_RDONLY
int lfs3_fs_mkconsistent(lfs3_t *lfs3);
#endif
// Check the filesystem for errors and other work
//
// This actually supports all janitorial work, but spins until all work
// is complete. See lfs3_fs_gc for incremental gc.
//
// Returns LFS3_ERR_CORRUPT if a checksum mismatch is found, or a negative
// error code on failure.
int lfs3_fs_ck(lfs3_t *lfs3, uint32_t flags);
// Perform any janitorial work that may be pending
//
// The exact janitorial work depends on the configured flags and steps.