diff options
author | Christopher Haster <chaster@utexas.edu> | 2018-08-13 22:08:30 +0300 |
---|---|---|
committer | Christopher Haster <chaster@utexas.edu> | 2018-10-18 18:00:48 +0300 |
commit | a2532a34cdfc39657436dcbec86ba7350c515be7 (patch) | |
tree | 43830f4d0eb476333905ecb1a2460e33d013e70a | |
parent | d5e800575daaf871ed629d5f52af2c4fe1a4cc29 (diff) |
Fixed inline files when inline_max == cache_size
The initial implementation of inline files was thrown together fairly
quicky, however it has worked well so far and there hasn't been much
reason to change it.
One shortcut was to trick file writes into thinking they are writing to
imaginary blocks. This works well and reuses most of the file code
paths, as long as we don't flush the imaginary block out to disk.
Initially we did this by limiting inline_max to cache_max-1, ensuring
that the cache never fills up and gets flushed. This was a rather dirty
hack, the better solution, implemented here, is to handle the
representation of an "imaginary" block correctly all the way down into
the cache layer.
So now for files specifically, the value -1 represents a null pointer,
and the value -2 represents an "imaginary" block. This may become a
problem if the number of blocks approaches the max, however this -2
value is never written to disk and can be changed in the future without
breaking compatibility.
-rw-r--r-- | lfs.c | 9 | ||||
-rwxr-xr-x | tests/test_alloc.sh | 8 |
2 files changed, 11 insertions, 6 deletions
@@ -142,7 +142,7 @@ static inline void lfs_cache_zero(lfs_t *lfs, lfs_cache_t *pcache) { static int lfs_cache_flush(lfs_t *lfs, lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate) { - if (pcache->block != 0xffffffff) { + if (pcache->block != 0xffffffff && pcache->block != 0xfffffffe) { LFS_ASSERT(pcache->block < lfs->cfg->block_count); lfs_size_t diff = lfs_alignup(pcache->size, lfs->cfg->prog_size); int err = lfs->cfg->prog(lfs->cfg, pcache->block, @@ -2158,7 +2158,10 @@ static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) { return 0; relocate: - continue; + LFS_DEBUG("Bad block at %"PRIu32, nblock); + + // just clear cache and try a new block + lfs_cache_drop(lfs, &lfs->pcache); } } @@ -2397,7 +2400,7 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, } if ((file->flags & LFS_F_INLINE) && - file->pos + nsize >= lfs->inline_max) { + file->pos + nsize > lfs->inline_max) { // inline file doesn't fit anymore file->block = 0xfffffffe; file->off = file->pos; diff --git a/tests/test_alloc.sh b/tests/test_alloc.sh index 55d1043..21fee96 100755 --- a/tests/test_alloc.sh +++ b/tests/test_alloc.sh @@ -341,6 +341,10 @@ tests/test.py << TEST } lfs_file_close(&lfs, &file[0]) => 0; + // remount to force reset of lookahead + lfs_unmount(&lfs) => 0; + lfs_mount(&lfs, &cfg) => 0; + // open hole lfs_remove(&lfs, "bump") => 0; @@ -350,7 +354,7 @@ tests/test.py << TEST for (lfs_size_t i = 0; i < cfg.block_size; i += 2) { memcpy(&buffer[i], "hi", 2); } - lfs_file_write(&lfs, &file[0], buffer, cfg.block_size) => LFS_ERR_NOSPC; + lfs_file_write(&lfs, &file[0], buffer, 2*cfg.block_size) => LFS_ERR_NOSPC; lfs_file_close(&lfs, &file[0]) => 0; lfs_unmount(&lfs) => 0; @@ -388,7 +392,6 @@ tests/test.py << TEST // remount to force reset of lookahead lfs_unmount(&lfs) => 0; - lfs_mount(&lfs, &cfg) => 0; // rewrite one file @@ -451,7 +454,6 @@ tests/test.py << TEST // remount to force reset of lookahead lfs_unmount(&lfs) => 0; - lfs_mount(&lfs, &cfg) => 0; // rewrite one file with a hole of one block |