Skip to content

Read data is incorrect after lfs_file_seek() when using LFS_READONLY #534

Open
@maboytim

Description

@maboytim

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions