From a2532a34cdfc39657436dcbec86ba7350c515be7 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Mon, 13 Aug 2018 14:08:30 -0500 Subject: [PATCH] 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. --- lfs.c | 9 ++++++--- tests/test_alloc.sh | 8 +++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/lfs.c b/lfs.c index 40744c9..81a19f6 100644 --- a/lfs.c +++ b/lfs.c @@ -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