Skip to content

Commit a2532a3

Browse files
committed
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.
1 parent d5e8005 commit a2532a3

File tree

2 files changed

+11
-6
lines changed

2 files changed

+11
-6
lines changed

lfs.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,7 @@ static inline void lfs_cache_zero(lfs_t *lfs, lfs_cache_t *pcache) {
142142

143143
static int lfs_cache_flush(lfs_t *lfs,
144144
lfs_cache_t *pcache, lfs_cache_t *rcache, bool validate) {
145-
if (pcache->block != 0xffffffff) {
145+
if (pcache->block != 0xffffffff && pcache->block != 0xfffffffe) {
146146
LFS_ASSERT(pcache->block < lfs->cfg->block_count);
147147
lfs_size_t diff = lfs_alignup(pcache->size, lfs->cfg->prog_size);
148148
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) {
21582158
return 0;
21592159

21602160
relocate:
2161-
continue;
2161+
LFS_DEBUG("Bad block at %"PRIu32, nblock);
2162+
2163+
// just clear cache and try a new block
2164+
lfs_cache_drop(lfs, &lfs->pcache);
21622165
}
21632166
}
21642167

@@ -2397,7 +2400,7 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
23972400
}
23982401

23992402
if ((file->flags & LFS_F_INLINE) &&
2400-
file->pos + nsize >= lfs->inline_max) {
2403+
file->pos + nsize > lfs->inline_max) {
24012404
// inline file doesn't fit anymore
24022405
file->block = 0xfffffffe;
24032406
file->off = file->pos;

tests/test_alloc.sh

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,10 @@ tests/test.py << TEST
341341
}
342342
lfs_file_close(&lfs, &file[0]) => 0;
343343
344+
// remount to force reset of lookahead
345+
lfs_unmount(&lfs) => 0;
346+
lfs_mount(&lfs, &cfg) => 0;
347+
344348
// open hole
345349
lfs_remove(&lfs, "bump") => 0;
346350
@@ -350,7 +354,7 @@ tests/test.py << TEST
350354
for (lfs_size_t i = 0; i < cfg.block_size; i += 2) {
351355
memcpy(&buffer[i], "hi", 2);
352356
}
353-
lfs_file_write(&lfs, &file[0], buffer, cfg.block_size) => LFS_ERR_NOSPC;
357+
lfs_file_write(&lfs, &file[0], buffer, 2*cfg.block_size) => LFS_ERR_NOSPC;
354358
lfs_file_close(&lfs, &file[0]) => 0;
355359
356360
lfs_unmount(&lfs) => 0;
@@ -388,7 +392,6 @@ tests/test.py << TEST
388392
389393
// remount to force reset of lookahead
390394
lfs_unmount(&lfs) => 0;
391-
392395
lfs_mount(&lfs, &cfg) => 0;
393396
394397
// rewrite one file
@@ -451,7 +454,6 @@ tests/test.py << TEST
451454
452455
// remount to force reset of lookahead
453456
lfs_unmount(&lfs) => 0;
454-
455457
lfs_mount(&lfs, &cfg) => 0;
456458
457459
// rewrite one file with a hole of one block

0 commit comments

Comments
 (0)