Description
After having read some data and performing a lfs_file_seek() the next data read is incorrect because it is read from the buffer instead of from the block device. This doesn't seem to happen when not using LFS_READONLY even if the file is open only for reading.
#define LFS_VERSION 0x00020004
The code below from lfs_file_rawread() thinks the read data is in the buffer and a new block isn't needed even though the seek was to a position outside of the buffer:
// check if we need a new block
if (!(file->flags & LFS_F_READING) ||
file->off == lfs->cfg->block_size) {
if (!(file->flags & LFS_F_INLINE)) {
int err = lfs_ctz_find(lfs, NULL, &file->cache,
file->ctz.head, file->ctz.size,
file->pos, &file->block, &file->off);
if (err) {
return err;
}
} else {
file->block = LFS_BLOCK_INLINE;
file->off = file->pos;
}
file->flags |= LFS_F_READING;
}
- because LFS_F_READING is set from the previous read. The issue seems to be here in lfs_file_rawseek():
#ifndef LFS_READONLY
// write out everything beforehand, may be noop if rdonly
int err = lfs_file_flush(lfs, file);
if (err) {
return err;
}
#endif
The flush is not performed for READONLY which is apparently where the buffer must be invalidated. I added this change:
#ifndef LFS_READONLY
// write out everything beforehand, may be noop if rdonly
int err = lfs_file_flush(lfs, file);
if (err) {
return err;
}
#else
file->flags &= ~LFS_F_READING;
#endif
which seems to fix the problem although I think more complex logic that does this only if the seek is actually outside of the buffer might be a more appropriate fix. In my case though I happen to know that it is outside of the buffer (otherwise the read data would not have been incorrect in the first place) so this is sufficient for my application.