Skip to content

Conversation

@dschendt
Copy link
Contributor

@dschendt dschendt commented Sep 3, 2025

When dealing with large block sizes (128KiB, for example) and lots of small files (64 bytes and smaller, in the case of 128KiB block sizes), it's possible to run into the constraint where it seems dir->count can't exceed 1023. For example, here https://github.com/littlefs-project/littlefs/blob/master/lfs.c#L1372. This can result in cases where you can fail to create new files even though you have plenty of disk space left.

@geky-bot
Copy link
Collaborator

geky-bot commented Sep 3, 2025

Tests passed ✓, Code: 17128 B (+0.1%), Stack: 1448 B (+0.0%), Structs: 812 B (+0.0%)
Code Stack Structs Coverage
Default 17128 B (+0.1%) 1448 B (+0.0%) 812 B (+0.0%) Lines 2436/2597 lines (-0.0%)
Readonly 6230 B (+0.0%) 448 B (+0.0%) 812 B (+0.0%) Branches 1284/1618 branches (+0.0%)
Threadsafe 17980 B (+0.1%) 1448 B (+0.0%) 820 B (+0.0%) Benchmarks
Multiversion 17200 B (+0.1%) 1448 B (+0.0%) 816 B (+0.0%) Readed 29369693876 B (+0.0%)
Migrate 18792 B (+0.1%) 1752 B (+0.0%) 816 B (+0.0%) Proged 1482874766 B (+0.0%)
Error-asserts 17936 B (+0.1%) 1440 B (+0.0%) 812 B (+0.0%) Erased 1568888832 B (+0.0%)

@geky geky added needs fix we know what is wrong needs work nothing broken but not ready yet and removed needs fix we know what is wrong labels Sep 22, 2025
@geky
Copy link
Member

geky commented Sep 22, 2025

Hi @dschendt, thanks for creating a PR, sorry about the late response.

Digging through the history, it looks like this logic had a similar check at one point (48bd2bf), but was dropped during the big no-recursion refactor (#658).

Thoughts on moving this check into the if (dir->erased) { statement (L2267) so it's clear these two conditions have a common code path?

Some other notes:

  • The threshold we use in other parts of the codebase (L2158) is < 0xff. We should probably do the same here.

    Maybe the threshold for splitting should be opened back up to all 10 bits, but I think that is out-of-scope for a patch release. At the very least we need to watch out for the special id=0x3ff value that is used to indicate deleted tags (SPEC.md).

  • This should probably check >= (or < in the if statement) instead of relying on == here. I don't think it's possible to increase id by more than 1 in the current implementation, but a comparison is safer.

@geky
Copy link
Member

geky commented Sep 23, 2025

Also worth noting this is side-stepped in littlefs3 (#1111) due to the use of 31-bit leb128 ids. Though that doesn't help in littlefs2.

This matches the logic originally implemented in 48bd2bf, which was lost
during the big no-recursion refactor 84da4c0.

Other notes:

- Checking >= 0xff matches the split logic during compaction (line
  2158):

    end - split < 0xff

- Grouping dir->erased || dir->count >= 0xff together makes it clear
  these share a common code path.

- Checking for dir->count >= 0xff early avoids committing >8-bit ids to
  disk.

  The cat may already be out-of-the bag on this one, but opening the id
  space up to the full 10-bits should probably be on a non-patch
  release.

Found by dschendt
@geky
Copy link
Member

geky commented Sep 25, 2025

Hi @dschendt, I went ahead and adopted the other tweaks to get this in on the impending patch release. Let us know if you see any issues with it.

Worst case if this is merged before you see it, feel free to create another PR for a future patch.

Thanks for the original PR!

@geky geky added next patch and removed needs work nothing broken but not ready yet labels Sep 25, 2025
@geky-bot
Copy link
Collaborator

Tests passed ✓, Code: 17128 B (+0.1%), Stack: 1448 B (+0.0%), Structs: 812 B (+0.0%)
Code Stack Structs Coverage
Default 17128 B (+0.1%) 1448 B (+0.0%) 812 B (+0.0%) Lines 2435/2595 lines (-0.0%)
Readonly 6230 B (+0.0%) 448 B (+0.0%) 812 B (+0.0%) Branches 1285/1618 branches (+0.0%)
Threadsafe 17980 B (+0.1%) 1448 B (+0.0%) 820 B (+0.0%) Benchmarks
Multiversion 17200 B (+0.1%) 1448 B (+0.0%) 816 B (+0.0%) Readed 29369693876 B (+0.0%)
Migrate 18792 B (+0.1%) 1752 B (+0.0%) 816 B (+0.0%) Proged 1482874766 B (+0.0%)
Error-asserts 17940 B (+0.1%) 1440 B (+0.0%) 812 B (+0.0%) Erased 1568888832 B (+0.0%)

@dschendt
Copy link
Contributor Author

@geky Sorry for the late reply, and thank you for taking the time to look at this and give your feedback. I haven't had much time to dig into your suggested changes but I'm not seeing any improvements on disk utilization with them (both before and after I get an error after less than 2,000 2-byte files). Even taking my original changes and changing the comparison to >= 0xff I'm able to see a huge improvement (no errors after 20,000+ 2-byte files). I think we should hold off on merging this and I'd like to take a little more time to dig into this some more.

Curiously, the logic from 48bd2bf was incorrect, and would allow a
commit to be tried if erased _or_ dir->count was at risk of overflow.

That is clearly wrong, we should only try to commit if both conditions
are met...

Found again by dschendt
@geky
Copy link
Member

geky commented Sep 25, 2025

@dschendt, oh thank you for double checking. That's probably because the logic I pushed up was wrong. Curiously, it looks like the logic was backwards in 48bd2bf. Progs to unerased flash tend to get picked up as corrupt during littlefs's prog checks, which may explain why this went unnoticed.

I pushed up what should be the correct logic, but can wait to bring this in.

@geky geky removed the next patch label Sep 25, 2025
@dschendt
Copy link
Contributor Author

@geky No need to wait to pull this in anymore, it looks like it's working as expected for me now. My comment on waiting was just so I could figure out why your implementation wasn't doing what I expected. Seems you figured it out already and seeing your changes it makes sense now. Thanks!

@geky-bot
Copy link
Collaborator

Tests passed ✓, Code: 17124 B (+0.1%), Stack: 1448 B (+0.0%), Structs: 812 B (+0.0%)
Code Stack Structs Coverage
Default 17124 B (+0.1%) 1448 B (+0.0%) 812 B (+0.0%) Lines 2435/2595 lines (-0.0%)
Readonly 6230 B (+0.0%) 448 B (+0.0%) 812 B (+0.0%) Branches 1285/1618 branches (+0.0%)
Threadsafe 17976 B (+0.1%) 1448 B (+0.0%) 820 B (+0.0%) Benchmarks
Multiversion 17196 B (+0.1%) 1448 B (+0.0%) 816 B (+0.0%) Readed 29000746676 B (-1.3%)
Migrate 18788 B (+0.1%) 1752 B (+0.0%) 816 B (+0.0%) Proged 1482895246 B (+0.0%)
Error-asserts 17932 B (+0.0%) 1440 B (+0.0%) 812 B (+0.0%) Erased 1568921600 B (+0.0%)

@geky
Copy link
Member

geky commented Sep 29, 2025

@dschendt, cool beans. Time to get the party started.

Thanks for the PR!

@geky geky changed the base branch from master to devel September 29, 2025 20:08
@geky geky merged commit ed12705 into littlefs-project:devel Sep 29, 2025
95 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants