mirror of
https://github.com/littlefs-project/littlefs.git
synced 2025-10-30 04:02:29 +00:00
In v2.5, we introduced an optimization to avoid rereading data when seeking inside the file cache. Unfortunately this used a slightly wrong condition to check if the cache was "live", which meant seeks from end-of-blocks could end up with invalid caches and wrong data. Not great. The problem is the nuance of when a file's cache is "live": 1. The file is marked as LFS_F_READING or LFS_F_WRITING. But we can't reuse the cache when writing, so we only care about LFS_F_READING. 2. file->off != lfs->cfg->block_size (end-of-block). This is an optimization to avoid eagerly reading blocks we may not actually care about. We weren't checking for the end-of-block case, which meant if you seeked _from_ the end of a block to a seemingly valid location in the file cache, you could end up with an invalid cache. Note that end-of-block may not be powers-of-two due to CTZ skip-list pointers. --- The fix is to check for the end-of-block case in lfs_file_seek. Note this now matches the need-new-block logic in lfs_file_flushedread. This logic change may also make lfs_file_seek call lfs_file_flush more often, but only in cases where lfs_file_flush is a noop. I've also extended the test_seek tests to cover a few more boundary-read cases and prevent a regression in the future. Found by wjl and lrodorigo