Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/littlefs-project/littlefs.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristopher Haster <chaster@utexas.edu>2018-08-13 22:08:30 +0300
committerChristopher Haster <chaster@utexas.edu>2018-10-18 18:00:48 +0300
commita2532a34cdfc39657436dcbec86ba7350c515be7 (patch)
tree43830f4d0eb476333905ecb1a2460e33d013e70a
parentd5e800575daaf871ed629d5f52af2c4fe1a4cc29 (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.c9
-rwxr-xr-xtests/test_alloc.sh8
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