Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

Fix metadata_max==prog_size commit->end calculation #1031

Merged
merged 3 commits into from
Dec 6, 2024
Merged

Conversation

geky
Copy link
Member

@geky geky commented Oct 4, 2024

I've been trying to dig into some of the early LFS_ERR_NOSPC errors users have been seeing. Some of the problem is that littlefs returns LFS_ERR_NOSPC for both "no space" errors, and internally whenever metadata can't fit in a block/mdir. This has made tracking down the actual root cause a bit tricky.

I did at least find one bug: In mdir compaction we weren't correctly adjusting commit->end to reserve space for commit-related metadata (checksums, tail pointers, etc) when metadata_max == prog_size.

This went unnoticed due to a lack of testing and requiring metadata_max == prog_size.

Added a quick test to prevent regression, and also added a few more asserts to lfs_init related to possible metadata_max configuration mistakes.

Found by @ajheck, @dpkristensen, @NLLK, and likely others.
Related #755, #896

geky added 3 commits October 4, 2024 13:06
- Added METADATA_MAX to test_runner.
- Added METADATA_MAX to bench_runner.
- Added a simple metadata_max test to test_superblocks, for lack of
  better location.

There have been several issues floating around related to metadata_max
and LFS_ERR_NOSPC which makes me think there's a bug in our metadata_max
logic.

metadata_max was a quick patch and is relatively untested, so an
undetected bug isn't too surprising. This commit adds at least some
testing over metadata_max.

Sure enough, the new test_superblocks_metadata_max test reveals a
curious LFS_ERR_NAMETOOLONG error that shouldn't be there.

More investigation needed.
The inconsistency here between the use of block_size vs metadata_max was
suspicious. Turns out there's a bug when metadata_max == prog_size.

We correctly use metadata_max for the block_size/2 check, but we weren't
using it for the block_size-40 check. The second check seems unnecessary
after the first, but it protects against running out of space in a
commit for commit-related metadata (checksums, tail pointers, etc) when
we can't program half-blocks.

Turns out this is also needed when limiting metadata_max to a single
prog, otherwise we risk erroring with LFS_ERR_NOSPC early.

Found by ajheck, dpkristensen, NLLK, and likely others.
Like the read/prog/block_size checks, these are just asserts. If these
invariants are broken the filesystem will break in surprising ways.
@geky-bot
Copy link
Collaborator

geky-bot commented Oct 4, 2024

Tests passed ✓, Code: 17068 B, Stack: 1440 B, Structs: 812 B
Code Stack Structs Coverage
Default 17068 B 1440 B 812 B Lines 2397/2576 lines
Readonly 6194 B 448 B 812 B Branches 1262/1602 branches
Threadsafe 17928 B 1440 B 820 B Benchmarks
Multiversion 17128 B 1440 B 816 B Readed 29369693876 B
Migrate 18764 B 1744 B 816 B Proged 1482874766 B
Error-asserts 17808 B 1432 B 812 B Erased 1568888832 B

@geky geky added this to the v2.10 milestone Dec 6, 2024
@geky geky merged commit 83fe41b into devel Dec 6, 2024
32 checks passed
@geky geky mentioned this pull request Dec 6, 2024
# for free to join this conversation on GitHub. Already have an account? # to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants