diff options
author | Christopher Haster <chaster@utexas.edu> | 2021-01-11 09:01:05 +0300 |
---|---|---|
committer | Christopher Haster <chaster@utexas.edu> | 2021-01-11 09:14:34 +0300 |
commit | 745d98cde08850cd0322daed86e5584a891095eb (patch) | |
tree | bb11dd13eaee02a369bdba326224103bd34a811c /lfs.c | |
parent | 3216b07c3bce220115ea8c5c8b3eb1e452bf6de0 (diff) |
Fixed lfs_file_truncate issue where internal state may not be flushed
This was caused by the new lfs_file_rawseek optimization that can skip
flushing when calculated file->pos is unchanged combined with an
implicit expectation in lfs_file_truncate that lfs_file_rawseek
unconditionally sets file->pos.
Because of this assumption, lfs_file_truncate could leave file->pos in
an outdated state while changing the internal file metadata. Humorously,
this was always gauranteed to trigger the skip in lfs_file_rawseek when
we try to restore the file->pos, leaving the file->cache used to do the
CTZ skip-list lookup in a potentially bad state.
The easiest fix is to just update file->pos correctly. Note we don't
want to explicitly flush since we can leverage the same noop
optimization if we truncate to the file position. Which I've added a
test for.
Diffstat (limited to 'lfs.c')
-rw-r--r-- | lfs.c | 3 |
1 files changed, 3 insertions, 0 deletions
@@ -3106,6 +3106,9 @@ static int lfs_file_rawtruncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) { return err; } + // need to set pos/block/off consistently so seeking back to + // the old position does not get confused + file->pos = size; file->ctz.head = file->block; file->ctz.size = size; file->flags |= LFS_F_DIRTY | LFS_F_READING; |