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
+45 -45
View File
@@ -180,7 +180,7 @@ code = '''
# test we can detect at least fully clobbered blocks
[cases.test_ck_ckmeta_easy]
# METHOD=0 => lfs3_fs_ckmeta
# METHOD=0 => lfs3_fs_ck
# METHOD=1 => lfs3_fs_gc
# METHOD=2 => lfs3_trv_read
# METHOD=3 => lfs3_mount
@@ -268,9 +268,9 @@ code = '''
}
clobbered:;
// find clobbered blocks with lfs3_fs_ckmeta
// find clobbered blocks with lfs3_fs_ck
if (METHOD == 0) {
lfs3_fs_ckmeta(&lfs3) => LFS3_ERR_CORRUPT;
lfs3_fs_ck(&lfs3, LFS3_FSCK_CKMETA) => LFS3_ERR_CORRUPT;
// find clobbered blocks with lfs3_fs_gc
} else if (METHOD == 1) {
@@ -317,7 +317,7 @@ done:;
'''
[cases.test_ck_ckdata_easy]
# METHOD=0 => lfs3_fs_ckdata
# METHOD=0 => lfs3_fs_ck
# METHOD=1 => lfs3_fs_gc
# METHOD=2 => lfs3_trv_read
# METHOD=3 => lfs3_mount
@@ -406,9 +406,9 @@ code = '''
}
clobbered:;
// find clobbered blocks with lfs3_fs_ckmeta
// find clobbered blocks with lfs3_fs_ck
if (METHOD == 0) {
lfs3_fs_ckdata(&lfs3) => LFS3_ERR_CORRUPT;
lfs3_fs_ck(&lfs3, LFS3_FSCK_CKDATA) => LFS3_ERR_CORRUPT;
// find clobbered blocks with lfs3_fs_gc
} else if (METHOD == 1) {
@@ -456,7 +456,7 @@ done:;
# test some more interesting errors
[cases.test_ck_ckmeta_hard]
# METHOD=0 => lfs3_fs_ckmeta
# METHOD=0 => lfs3_fs_ck
# METHOD=1 => lfs3_fs_gc
# METHOD=2 => lfs3_trv_read
# METHOD=3 => lfs3_mount
@@ -550,9 +550,9 @@ code = '''
printf("flipping 0x%x.%x+%x\n", badblock, badbit/8, badbit%8);
lfs3_emubd_flipbit(CFG, badblock, badbit) => 0;
// find clobbered blocks with lfs3_fs_ckmeta
// find clobbered blocks with lfs3_fs_ck
if (METHOD == 0) {
int err = lfs3_fs_ckmeta(&lfs3);
int err = lfs3_fs_ck(&lfs3, LFS3_FSCK_CKMETA);
assert(!err || err == LFS3_ERR_CORRUPT);
if (err == LFS3_ERR_CORRUPT) {
goto detected;
@@ -711,7 +711,7 @@ done:;
'''
[cases.test_ck_ckdata_hard]
# METHOD=0 => lfs3_fs_ckdata
# METHOD=0 => lfs3_fs_ck
# METHOD=1 => lfs3_fs_gc
# METHOD=2 => lfs3_trv_read
# METHOD=3 => lfs3_mount
@@ -806,9 +806,9 @@ code = '''
printf("flipping 0x%x.%x+%x\n", badblock, badbit/8, badbit%8);
lfs3_emubd_flipbit(CFG, badblock, badbit) => 0;
// find clobbered blocks with lfs3_fs_ckdata
// find clobbered blocks with lfs3_fs_ck
if (METHOD == 0) {
int err = lfs3_fs_ckdata(&lfs3);
int err = lfs3_fs_ck(&lfs3, LFS3_FSCK_CKDATA);
assert(!err || err == LFS3_ERR_CORRUPT);
if (err == LFS3_ERR_CORRUPT) {
goto detected;
@@ -971,8 +971,8 @@ done:;
# test we can detect at least fully clobbered blocks
[cases.test_ck_file_ckmeta_easy]
# METHOD=0 => lfs3_file_ckmeta
# METHOD=1 => lfs3_file_close+open+ckmeta
# METHOD=0 => lfs3_file_ck
# METHOD=1 => lfs3_file_close+open+ck
# METHOD=2 => lfs3_file_close+open
defines.METHOD = [0, 1, 2]
defines.N = [1, 2, 4, 8, 16, 32, 64]
@@ -1042,15 +1042,15 @@ code = '''
}
clobbered:;
// find clobbered blocks with lfs3_file_ckmeta
// find clobbered blocks with lfs3_file_ck
if (METHOD == 0) {
lfs3_file_ckmeta(&lfs3, &file) => LFS3_ERR_CORRUPT;
lfs3_file_ck(&lfs3, &file, LFS3_CK_CKMETA) => LFS3_ERR_CORRUPT;
// find clobbered blocks with lfs3_file_close+open+ckmeta
// find clobbered blocks with lfs3_file_close+open+ck
} else if (METHOD == 1) {
lfs3_file_close(&lfs3, &file) => 0;
lfs3_file_open(&lfs3, &file, "octopus", LFS3_O_RDONLY) => 0;
lfs3_file_ckmeta(&lfs3, &file) => LFS3_ERR_CORRUPT;
lfs3_file_ck(&lfs3, &file, LFS3_CK_CKMETA) => LFS3_ERR_CORRUPT;
// find clobbered blocks with lfs3_file_close+open
} else if (METHOD == 2) {
@@ -1070,8 +1070,8 @@ done:;
'''
[cases.test_ck_file_ckdata_easy]
# METHOD=0 => lfs3_file_ckdata
# METHOD=1 => lfs3_file_close+open+ckdata
# METHOD=0 => lfs3_file_ck
# METHOD=1 => lfs3_file_close+open+ck
# METHOD=2 => lfs3_file_close+open
defines.METHOD = [0, 1, 2]
defines.N = [1, 2, 4, 8, 16, 32, 64]
@@ -1142,15 +1142,15 @@ code = '''
}
clobbered:;
// find clobbered blocks with lfs3_file_ckmeta
// find clobbered blocks with lfs3_file_ck
if (METHOD == 0) {
lfs3_file_ckdata(&lfs3, &file) => LFS3_ERR_CORRUPT;
lfs3_file_ck(&lfs3, &file, LFS3_CK_CKDATA) => LFS3_ERR_CORRUPT;
// find clobbered blocks with lfs3_file_close+open+ckmeta
// find clobbered blocks with lfs3_file_close+open+ck
} else if (METHOD == 1) {
lfs3_file_close(&lfs3, &file) => 0;
lfs3_file_open(&lfs3, &file, "octopus", LFS3_O_RDONLY) => 0;
lfs3_file_ckdata(&lfs3, &file) => LFS3_ERR_CORRUPT;
lfs3_file_ck(&lfs3, &file, LFS3_CK_CKDATA) => LFS3_ERR_CORRUPT;
// find clobbered blocks with lfs3_file_close+open
} else if (METHOD == 2) {
@@ -1172,8 +1172,8 @@ done:;
# test some more interesting errors
[cases.test_ck_file_ckmeta_hard]
# METHOD=0 => lfs3_file_ckmeta
# METHOD=1 => lfs3_file_close+open+ckmeta
# METHOD=0 => lfs3_file_ck
# METHOD=1 => lfs3_file_close+open+ck
# METHOD=2 => lfs3_file_close+open
defines.METHOD = [0, 1, 2]
defines.N = [1, 2, 4, 8, 16, 32, 64]
@@ -1251,19 +1251,19 @@ code = '''
printf("flipping 0x%x.%x+%x\n", badblock, badbit/8, badbit%8);
lfs3_emubd_flipbit(CFG, badblock, badbit) => 0;
// find clobbered blocks with lfs3_file_ckmeta
// find clobbered blocks with lfs3_file_ck
if (METHOD == 0) {
int err = lfs3_file_ckmeta(&lfs3, &file);
int err = lfs3_file_ck(&lfs3, &file, LFS3_CK_CKMETA);
assert(!err || err == LFS3_ERR_CORRUPT);
if (err == LFS3_ERR_CORRUPT) {
goto detected;
}
// find clobbered blocks with lfs3_file_close+open+ckmeta
// find clobbered blocks with lfs3_file_close+open+ck
} else if (METHOD == 1) {
lfs3_file_close(&lfs3, &file) => 0;
lfs3_file_open(&lfs3, &file, "octopus", LFS3_O_RDONLY) => 0;
int err = lfs3_file_ckmeta(&lfs3, &file);
int err = lfs3_file_ck(&lfs3, &file, LFS3_CK_CKMETA);
assert(!err || err == LFS3_ERR_CORRUPT);
if (err == LFS3_ERR_CORRUPT) {
goto detected;
@@ -1322,8 +1322,8 @@ done:;
'''
[cases.test_ck_file_ckdata_hard]
# METHOD=0 => lfs3_file_ckdata
# METHOD=1 => lfs3_file_close+open+ckdata
# METHOD=0 => lfs3_file_ck
# METHOD=1 => lfs3_file_close+open+ck
# METHOD=2 => lfs3_file_close+open
defines.METHOD = [0, 1, 2]
defines.N = [1, 2, 4, 8, 16, 32, 64]
@@ -1402,9 +1402,9 @@ code = '''
printf("flipping 0x%x.%x+%x\n", badblock, badbit/8, badbit%8);
lfs3_emubd_flipbit(CFG, badblock, badbit) => 0;
// find clobbered blocks with lfs3_file_ckdata
// find clobbered blocks with lfs3_file_ck
if (METHOD == 0) {
int err = lfs3_file_ckdata(&lfs3, &file);
int err = lfs3_file_ck(&lfs3, &file, LFS3_CK_CKDATA);
assert(!err || err == LFS3_ERR_CORRUPT);
if (err == LFS3_ERR_CORRUPT) {
goto detected;
@@ -1414,7 +1414,7 @@ code = '''
} else if (METHOD == 1) {
lfs3_file_close(&lfs3, &file) => 0;
lfs3_file_open(&lfs3, &file, "octopus", LFS3_O_RDONLY) => 0;
int err = lfs3_file_ckdata(&lfs3, &file);
int err = lfs3_file_ck(&lfs3, &file, LFS3_CK_CKDATA);
assert(!err || err == LFS3_ERR_CORRUPT);
if (err == LFS3_ERR_CORRUPT) {
goto detected;
@@ -2827,14 +2827,14 @@ code = '''
// run ckdata?
if (CKDATA) {
int err = lfs3_fs_ckdata(&lfs3);
int err = lfs3_fs_ck(&lfs3, LFS3_FSCK_CKDATA);
assert(!err || err == LFS3_ERR_CORRUPT);
if (err == LFS3_ERR_CORRUPT) {
goto corrupt_mounted;
}
// run ckmeta?
} else if (CKMETA && !MTREEONLY) {
int err = lfs3_fs_ckmeta(&lfs3);
int err = lfs3_fs_ck(&lfs3, LFS3_FSCK_CKMETA);
assert(!err || err == LFS3_ERR_CORRUPT);
if (err == LFS3_ERR_CORRUPT) {
goto corrupt_mounted;
@@ -3145,14 +3145,14 @@ code = '''
// run ckdata?
if (CKDATA) {
int err = lfs3_fs_ckdata(&lfs3);
int err = lfs3_fs_ck(&lfs3, LFS3_FSCK_CKDATA);
assert(!err || err == LFS3_ERR_CORRUPT);
if (err == LFS3_ERR_CORRUPT) {
goto corrupt_mounted;
}
// run ckmeta?
} else if (CKMETA && !MTREEONLY) {
int err = lfs3_fs_ckmeta(&lfs3);
int err = lfs3_fs_ck(&lfs3, LFS3_FSCK_CKMETA);
assert(!err || err == LFS3_ERR_CORRUPT);
if (err == LFS3_ERR_CORRUPT) {
goto corrupt_mounted;
@@ -3561,14 +3561,14 @@ code = '''
// run ckdata?
if (CKDATA) {
int err = lfs3_fs_ckdata(&lfs3);
int err = lfs3_fs_ck(&lfs3, LFS3_FSCK_CKDATA);
assert(!err || err == LFS3_ERR_CORRUPT);
if (err == LFS3_ERR_CORRUPT) {
goto corrupt_open;
}
// run ckmeta?
} else if (CKMETA && !MTREEONLY) {
int err = lfs3_fs_ckmeta(&lfs3);
int err = lfs3_fs_ck(&lfs3, LFS3_FSCK_CKMETA);
assert(!err || err == LFS3_ERR_CORRUPT);
if (err == LFS3_ERR_CORRUPT) {
goto corrupt_open;
@@ -3846,14 +3846,14 @@ code = '''
// run ckdata?
if (CKDATA) {
int err = lfs3_fs_ckdata(&lfs3);
int err = lfs3_fs_ck(&lfs3, LFS3_FSCK_CKDATA);
assert(!err || err == LFS3_ERR_CORRUPT);
if (err == LFS3_ERR_CORRUPT) {
goto corrupt_mounted;
}
// run ckmeta?
} else if (CKMETA && !MTREEONLY) {
int err = lfs3_fs_ckmeta(&lfs3);
int err = lfs3_fs_ck(&lfs3, LFS3_FSCK_CKMETA);
assert(!err || err == LFS3_ERR_CORRUPT);
if (err == LFS3_ERR_CORRUPT) {
goto corrupt_mounted;
@@ -4450,14 +4450,14 @@ code = '''
// run ckdata?
if (CKDATA) {
int err = lfs3_fs_ckdata(&lfs3);
int err = lfs3_fs_ck(&lfs3, LFS3_FSCK_CKDATA);
assert(!err || err == LFS3_ERR_CORRUPT);
if (err == LFS3_ERR_CORRUPT) {
goto corrupt_mounted;
}
// run ckmeta?
} else if (CKMETA && !MTREEONLY) {
int err = lfs3_fs_ckmeta(&lfs3);
int err = lfs3_fs_ck(&lfs3, LFS3_FSCK_CKMETA);
assert(!err || err == LFS3_ERR_CORRUPT);
if (err == LFS3_ERR_CORRUPT) {
goto corrupt_mounted;
+17 -17
View File
@@ -1293,7 +1293,7 @@ code = '''
done:;
'''
# test that our explicit functions (lfs3_fs_ckmeta/ckdata) work as well,
# test that our explicit functions (lfs3_fs_ck) work as well,
# these call the same logic internally
[cases.test_gc_ckmeta_explicit]
defines.N = [1, 2, 4, 8, 16, 32, 64]
@@ -1377,8 +1377,8 @@ code = '''
}
clobbered:;
// lfs3_fs_ckmeta should find the clobbered block
lfs3_fs_ckmeta(&lfs3) => LFS3_ERR_CORRUPT;
// lfs3_fs_ckshould find the clobbered block
lfs3_fs_ck(&lfs3, LFS3_FSCK_CKMETA) => LFS3_ERR_CORRUPT;
lfs3_unmount(&lfs3) => 0;
}
@@ -1468,8 +1468,8 @@ code = '''
}
clobbered:;
// lfs3_fs_ckdata should find the clobbered block
lfs3_fs_ckdata(&lfs3) => LFS3_ERR_CORRUPT;
// lfs3_fs_ckshould find the clobbered block
lfs3_fs_ck(&lfs3, LFS3_FSCK_CKDATA) => LFS3_ERR_CORRUPT;
lfs3_unmount(&lfs3) => 0;
}
@@ -1482,7 +1482,7 @@ done:;
# AFTER=0 => after running lfs3_fs_gc once
# AFTER=1 => after running lfs3_fs_gc to completion
# AFTER=2 => after running lfs3_trv_t
# AFTER=3 => after lfs3_fs_ckmeta
# AFTER=3 => after lfs3_fs_ck
# AFTER=4 => after remounting with LFS3_M_CKMETA
defines.AFTER = [0, 1, 2, 3, 4]
defines.GC_FLAGS = 'LFS3_GC_CKMETA'
@@ -1563,9 +1563,9 @@ code = '''
}
lfs3_trv_close(&lfs3, &trv) => 0;
// run lfs3_fs_ckmeta
// run lfs3_fs_ck
} else if (AFTER == 3) {
lfs3_fs_ckmeta(&lfs3) => 0;
lfs3_fs_ck(&lfs3, LFS3_FSCK_CKMETA) => 0;
struct lfs3_fsinfo fsinfo;
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
@@ -1648,7 +1648,7 @@ done:;
# AFTER=0 => after running lfs3_fs_gc once
# AFTER=1 => after running lfs3_fs_gc to completion
# AFTER=2 => after running lfs3_trv_t
# AFTER=3 => after lfs3_fs_ckdata
# AFTER=3 => after lfs3_fs_ck
# AFTER=4 => after remounting with LFS3_M_CKDATA
defines.AFTER = [0, 1, 2, 3, 4]
defines.GC_FLAGS = 'LFS3_GC_CKDATA'
@@ -1729,9 +1729,9 @@ code = '''
}
lfs3_trv_close(&lfs3, &trv) => 0;
// run lfs3_fs_ckdata
// run lfs3_fs_ck
} else if (AFTER == 3) {
lfs3_fs_ckdata(&lfs3) => 0;
lfs3_fs_ck(&lfs3, LFS3_FSCK_CKDATA) => 0;
struct lfs3_fsinfo fsinfo;
lfs3_fs_stat(&lfs3, &fsinfo) => 0;
@@ -2010,11 +2010,11 @@ code = '''
}
if (CKMETA && (fsinfo.flags & LFS3_I_CKMETA)) {
lfs3_fs_ckmeta(&lfs3) => 0;
lfs3_fs_ck(&lfs3, LFS3_FSCK_CKMETA) => 0;
}
if (CKDATA && (fsinfo.flags & LFS3_I_CKDATA)) {
lfs3_fs_ckdata(&lfs3) => 0;
lfs3_fs_ck(&lfs3, LFS3_FSCK_CKDATA) => 0;
}
}
@@ -2245,11 +2245,11 @@ code = '''
}
if (CKMETA && (fsinfo.flags & LFS3_I_CKMETA)) {
lfs3_fs_ckmeta(&lfs3) => 0;
lfs3_fs_ck(&lfs3, LFS3_FSCK_CKMETA) => 0;
}
if (CKDATA && (fsinfo.flags & LFS3_I_CKDATA)) {
lfs3_fs_ckdata(&lfs3) => 0;
lfs3_fs_ck(&lfs3, LFS3_FSCK_CKDATA) => 0;
}
}
@@ -2416,11 +2416,11 @@ code = '''
}
if (CKMETA && (fsinfo.flags & LFS3_I_CKMETA)) {
lfs3_fs_ckmeta(&lfs3) => 0;
lfs3_fs_ck(&lfs3, LFS3_FSCK_CKMETA) => 0;
}
if (CKDATA && (fsinfo.flags & LFS3_I_CKDATA)) {
lfs3_fs_ckdata(&lfs3) => 0;
lfs3_fs_ck(&lfs3, LFS3_FSCK_CKDATA) => 0;
}
}