Skip to content

Conversation

@geky
Copy link
Member

@geky geky commented May 13, 2025

A small minor release, driven by features proposed by @sosthene-nitrokey and @yamt, with bug fixes from @DvdGiessen, @selimkeles, and yours truly.

Bringing in:

Draft of release notes follows:


A small minor release, driven by features proposed by @sosthene-nitrokey and @yamt, with bug fixes from @DvdGiessen, @selimkeles, and yours truly.

What's new?

  • Thanks to @sosthene-nitrokey, lfs_fs_grow now supports a limited form of filesystem shrinking (#1094)

    If compiled with LFS_SHRINKNONRELOCATING, lfs_fs_grow can be used to reduce the block_count, as long is it does not require block relocation. This provides a useful path for migrating from old filesystem images created when littlefs ignored the on-disk block_count.

    Note that this is unreliable for general use. littlefs allocates blocks pseudorandomly as a part of wear-leveling, so LFS_SHRINKNONRELOCATING is unlikely to succeed even with small filesystems.

  • Thanks to @yamt, make test should now work on Mac out of the box. This required linker and Makefile changes due to littlefs's test-runner quirks (#1090, #1091)

    As a side-effect, littlefs's Makefile can now compile with Clang. The only limitation being that stack measurements are currently broken. If anyone knows a good Clang alternative to GCC's -fcallgraph-info=su, feel free to create an issue (or PR if you're willing to write a bit of python).

    littlefs's Makefile can also compile with other non-Clang non-GCC compilers if you set the NO_GCC environment variable.

  • @DvdGiessen fixed several bugs related to LFS_CRC (1095)

    • User provided LFS_CRCs no longer create multiple definitions if lfs_util.h is included in more than one file.
    • LFS_CRC no longer needs a trailing semicolon.
  • Thanks to @selimkeles, lfs_fromle32/lfs_frombe32 no longer risk overflow on 16-bit devices (#1100)

  • Found by @Hugh-Baoa, fixed a double deorphan that can occur if an mdir relocates during a remove operation (#1099)

  • Thanks to @DvdGiessen, changeprefix.py no longer breaks if /tmp lives on a different filesystem (#1104)

yamt and others added 19 commits April 7, 2025 16:06
"make test" on macOS:

```
using runner: ./runners/test_runner
found 19 suites, 188 cases, 11242/11770 permutations

running test_alloc: 12/12 cases, 207/207 perms
running test_attrs: 4/4 cases, 20/20 perms
running test_badblocks: 4/4 cases, 300/300 perms
running test_bd: 5/5 cases, 85/85 perms
running test_compat: 17/17 cases, 205/205 perms
running test_dirs: 15/15 cases, 450/450 perms, 1756pls!
running test_entries: 8/8 cases, 32/32 perms
running test_evil: 8/8 cases, 105/105 perms
running test_exhaustion: 5/5 cases, 85/85 perms
running test_files: 10/10 cases, 7155/7155 perms, 9410pls!
running test_interspersed: 4/4 cases, 190/190 perms, 2835pls!
running test_move: 17/17 cases, 161/161 perms, 157pls!
running test_orphans: 6/6 cases, 50/50 perms, 846pls!
running test_paths: 33/33 cases, 325/325 perms
running test_powerloss: 2/2 cases, 21/21 perms
running test_relocations: 4/4 cases, 68/68 perms, 1612pls!
running test_seek: 10/10 cases, 195/195 perms, 1050pls!
running test_superblocks: 17/17 cases, 318/318 perms, 1437pls!
running test_truncate: 7/7 cases, 1270/1270 perms, 9691pls!

done: 11242/11242 passed, 0/11242 failed, 28794pls!, in 585.76s
```
This PR adds a new `lfs_fs_shrink`, which functions similarly to
`lfs_fs_grow`, but supports reducing the block count.

This functions first checks that none of the removed block are in use.
If it is the case, it will fail.
These are the same as the related reentrant variants, but by opting out
of powerloss testing, we can test a much larger number of states without
having to worry about the impact on powerloss testing runtime.

Bumped CYCLES from 20 -> 2000.

This reveals an orphan remove bug found by Hugh-Baoa.
Long story short: There is a specific case where removing a directory
can trigger a deorphan pass, but lfs_remove did not check for this,
would try to clean up the (already cleaned) directory orphan, and
trigger an assert:

  lfs.c:4890:assert: assert failed with false, expected eq true
      LFS_ASSERT(lfs_tag_size(lfs->gstate.tag) > 0x000 || orphans >= 0);

The specific case being a remove commit that triggers a relocation that
creates an orphan.

This is also possible in lfs_rename, but only if you're renaming a
directory that implies a remove, which is a pretty rare operation.

---

This was probably an oversight introduced in the non-recursive commit
logic rework.

Fortunately the fix is to just check if we even have an orphan before
trying to remove it. We can rely on this instead of the file type, so
this fix shouldn't even increase the code size.

Found and root-caused by Hugh-Baoa
In 16 bit and 8 bit architectures, overflow and underflow issues were occuring while using functions lfs_frombe32 and lfs_fromle32
This is the same as the implicit Clang => NO_GCC behavior introduced by
yamt, but with an explicit variable that can be assigned by users using
other, non-gcc, compilers:

  $ NO_GCC=1 make

Note, stack measurements are currently GCC specific:

  $ NO_GCC=1 make stack
  ... snip ...
  FileNotFoundError: [Errno 2] No such file or directory: 'lfs.ci'
  make: *** [Makefile:494: lfs.stack.csv] Error 1
Thanks to yamt, GCC-specific flags should now be disabled if compiling
with clang. Dropping the explicit flags also doubles as a test that the
NO_GCC inference works.
lfs_crc should be static if LFS_CRC is defined
fix: added uint32_t cast to the bitshift places
…phan

Fix double deorphan caused by relocation mid dir remove
drop a few unsupported CFLAGS for clang
adapt the linker sections usage to mach-o
Add support for shrinking a filesystem
@geky geky added this to the v2.11 milestone May 13, 2025
@geky-bot
Copy link
Collaborator

Tests passed ✓, Code: 17104 B (-0.1%), Stack: 1448 B (+0.0%), Structs: 812 B (+0.0%)
Code Stack Structs Coverage
Default 17104 B (-0.1%) 1448 B (+0.0%) 812 B (+0.0%) Lines 2434/2595 lines (+0.0%)
Readonly 6230 B (+0.0%) 448 B (+0.0%) 812 B (+0.0%) Branches 1283/1616 branches (-0.0%)
Threadsafe 17956 B (-0.1%) 1448 B (+0.0%) 820 B (+0.0%) Benchmarks
Multiversion 17176 B (-0.1%) 1448 B (+0.0%) 816 B (+0.0%) Readed 29369693876 B (+0.0%)
Migrate 18768 B (-0.1%) 1752 B (+0.0%) 816 B (+0.0%) Proged 1482874766 B (+0.0%)
Error-asserts 17916 B (+0.1%) 1440 B (+0.0%) 812 B (+0.0%) Erased 1568888832 B (+0.0%)

This prevents a "OSError: [Errno 18] Invalid cross-device link" if the temporary
file was created on different filesystem (such as a tmpfs mount).
@geky-bot
Copy link
Collaborator

Tests passed ✓, Code: 17104 B (-0.1%), Stack: 1448 B (+0.0%), Structs: 812 B (+0.0%)
Code Stack Structs Coverage
Default 17104 B (-0.1%) 1448 B (+0.0%) 812 B (+0.0%) Lines 2434/2595 lines (+0.0%)
Readonly 6230 B (+0.0%) 448 B (+0.0%) 812 B (+0.0%) Branches 1283/1616 branches (-0.0%)
Threadsafe 17956 B (-0.1%) 1448 B (+0.0%) 820 B (+0.0%) Benchmarks
Multiversion 17176 B (-0.1%) 1448 B (+0.0%) 816 B (+0.0%) Readed 29369693876 B (+0.0%)
Migrate 18768 B (-0.1%) 1752 B (+0.0%) 816 B (+0.0%) Proged 1482874766 B (+0.0%)
Error-asserts 17916 B (+0.1%) 1440 B (+0.0%) 812 B (+0.0%) Erased 1568888832 B (+0.0%)

@geky geky merged commit 16ceb67 into master May 15, 2025
113 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants