gc: Tweaked lfsr_gc API to be more stateful

Before:

  int lfsr_fs_gc(lfs_t *lfs, lfs_soff_t steps, uint32_t flags);

After:

  int lfsr_gc(lfs_t *lfs);
  int lfsr_gc_setflags(lfs_t *lfs, uint32_t flags);
  int lfsr_gc_setsteps(lfs_t *lfs, lfs_soff_t steps);

---

The interesting thing about the lfsr_gc API is that the caller will
often be very different from whoever configures the system. One example
being an OS calling lfsr_gc in a background loop, while leaving
configuration up to the user.

The idea here, is instead of forcing the OS to come up with its own
stateful system to pass flags to lfsr_gc, we just embed this state in
littlefs directly. The whole point of lfsr_gc is that it's a stateful
system anyways.

Unfortunately this state does require a bit more logic to maintain,
which adds code/ctx cost:

           code          stack          ctx
  before: 37812           2608          752
  after:  37916 (+0.3%)   2608 (+0.0%)  768 (+2.1%)
This commit is contained in:
Christopher Haster
2025-01-06 15:59:51 -06:00
parent 42c81ef7de
commit 5d756fe698
7 changed files with 644 additions and 429 deletions
+9 -3
View File
@@ -490,6 +490,8 @@ defines.FILETYPE = [0, 1, 2]
defines.M = 40
defines.SIZE = 4
defines.COMPACT = [false, true]
defines.GC_FLAGS = 'LFS_GC_COMPACT'
defines.GC_STEPS = -1
defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2'
code = '''
lfs_t lfs;
@@ -527,7 +529,7 @@ code = '''
// try compacting?
if (COMPACT) {
lfsr_fs_gc(&lfs, -1, LFS_GC_COMPACT) => 0;
lfsr_gc(&lfs) => 0;
}
for (int remount = 0; remount < 2; remount++) {
@@ -567,6 +569,8 @@ defines.N = 64
defines.M = 4
defines.SIZE = 4
defines.COMPACT = [false, true]
defines.GC_FLAGS = 'LFS_GC_COMPACT'
defines.GC_STEPS = -1
defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2'
code = '''
lfs_t lfs;
@@ -605,7 +609,7 @@ code = '''
// try compacting?
if (COMPACT) {
lfsr_fs_gc(&lfs, -1, LFS_GC_COMPACT) => 0;
lfsr_gc(&lfs) => 0;
}
for (int remount = 0; remount < 2; remount++) {
@@ -4067,6 +4071,8 @@ defines.N = 64
defines.M = 4
defines.SIZE = 4
defines.COMPACT = [false, true]
defines.GC_FLAGS = 'LFS_GC_COMPACT'
defines.GC_STEPS = -1
defines.GC_COMPACT_THRESH = 'BLOCK_SIZE/2'
code = '''
lfs_t lfs;
@@ -4105,7 +4111,7 @@ code = '''
// try compacting?
if (COMPACT) {
lfsr_fs_gc(&lfs, -1, LFS_GC_COMPACT) => 0;
lfsr_gc(&lfs) => 0;
}
for (int remount = 0; remount < 2; remount++) {
+10 -6
View File
@@ -8,10 +8,12 @@ after = ['test_traversal', 'test_gc', 'test_mount']
# test we can detect at least fully clobbered blocks
[cases.test_ck_ckmeta_easy]
# METHOD=0 => lfsr_fs_ckmeta
# METHOD=1 => lfsr_fs_gc
# METHOD=1 => lfsr_gc
# METHOD=2 => lfsr_traversal_read
# METHOD=3 => lfsr_mount
defines.METHOD = [0, 1, 2, 3]
defines.GC_FLAGS = 'LFS_GC_CKMETA'
defines.GC_STEPS = -1
defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.SIZE = [
'0',
@@ -94,9 +96,9 @@ code = '''
if (METHOD == 0) {
lfsr_fs_ckmeta(&lfs) => LFS_ERR_CORRUPT;
// find clobbered blocks with lfsr_fs_gc
// find clobbered blocks with lfsr_gc
} else if (METHOD == 1) {
lfsr_fs_gc(&lfs, -1, LFS_GC_CKMETA) => LFS_ERR_CORRUPT;
lfsr_gc(&lfs) => LFS_ERR_CORRUPT;
// find clobbered blocks with lfsr_traversal_read
} else if (METHOD == 2) {
@@ -136,10 +138,12 @@ done:;
[cases.test_ck_ckdata_easy]
# METHOD=0 => lfsr_fs_ckdata
# METHOD=1 => lfsr_fs_gc
# METHOD=1 => lfsr_gc
# METHOD=2 => lfsr_traversal_read
# METHOD=3 => lfsr_mount
defines.METHOD = [0, 1, 2, 3]
defines.GC_FLAGS = 'LFS_GC_CKDATA'
defines.GC_STEPS = -1
defines.N = [1, 2, 4, 8, 16, 32, 64]
defines.SIZE = [
'0',
@@ -223,9 +227,9 @@ code = '''
if (METHOD == 0) {
lfsr_fs_ckdata(&lfs) => LFS_ERR_CORRUPT;
// find clobbered blocks with lfsr_fs_gc
// find clobbered blocks with lfsr_gc
} else if (METHOD == 1) {
lfsr_fs_gc(&lfs, -1, LFS_GC_CKDATA) => LFS_ERR_CORRUPT;
lfsr_gc(&lfs) => LFS_ERR_CORRUPT;
// find clobbered blocks with lfsr_traversal_read
} else if (METHOD == 2) {
+371 -240
View File
File diff suppressed because it is too large Load Diff