From 9064fa6dbb17c46defb716c4345c8ba1100bc4c2 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Sat, 17 Mar 2018 20:32:16 -0500 Subject: [PATCH] WIP Better implementation of inline files, now with overflowing --- lfs.c | 91 ++++++++++++++++++++++++++++++---------------- tests/test_dirs.sh | 2 +- 2 files changed, 60 insertions(+), 33 deletions(-) diff --git a/lfs.c b/lfs.c index 1918065..79d664b 100644 --- a/lfs.c +++ b/lfs.c @@ -544,6 +544,7 @@ static int lfs_commit_disk(lfs_t *lfs, struct lfs_commit *c, } } +// TODO handle overflowing reads (zero?) static int lfs_dir_commit(lfs_t *lfs, lfs_dir_t *dir, struct lfs_region *regions) { // state for copying over @@ -1142,6 +1143,8 @@ int lfs_dir_read(lfs_t *lfs, lfs_dir_t *dir, struct lfs_info *info) { break; } + // TODO common info constructor? + // TODO also used in lfs_stat info->type = 0xf & entry.d.type; if (entry.d.type == (LFS_STRUCT_CTZ | LFS_TYPE_REG)) { info->size = entry.d.u.file.size; @@ -1442,23 +1445,6 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file, return LFS_ERR_EXIST; } - // setup file struct - file->pair[0] = cwd.pair[0]; - file->pair[1] = cwd.pair[1]; - file->poff = entry.off; - file->head = entry.d.u.file.head; - file->size = entry.d.u.file.size; - file->flags = flags; - file->pos = 0; - - if (flags & LFS_O_TRUNC) { - if (file->size != 0) { - file->flags |= LFS_F_DIRTY; - } - file->head = 0xffffffff; - file->size = 0; - } - // allocate buffer if needed file->cache.block = 0xffffffff; if (lfs->cfg->file_buffer) { @@ -1475,6 +1461,25 @@ int lfs_file_open(lfs_t *lfs, lfs_file_t *file, } } + // TODO combine these below? + // setup file struct + file->pair[0] = cwd.pair[0]; + file->pair[1] = cwd.pair[1]; + file->poff = entry.off; + file->head = entry.d.u.file.head; + file->size = entry.d.u.file.size; + file->flags = flags; + file->pos = 0; + + if (flags & LFS_O_TRUNC) { + if (file->size != 0) { + file->flags |= LFS_F_DIRTY; + } + + entry.d.type = LFS_STRUCT_INLINE | LFS_TYPE_REG; + entry.d.elen = 0; + } + // load inline files if ((0x70 & entry.d.type) == LFS_STRUCT_INLINE) { file->head = 0xfffffffe; @@ -1518,9 +1523,7 @@ int lfs_file_close(lfs_t *lfs, lfs_file_t *file) { } static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) { -relocate: - LFS_DEBUG("Bad block at %d", file->block); - +relocate:; // just relocate what exists into new block lfs_block_t nblock; int err = lfs_alloc(lfs, &nblock); @@ -1573,6 +1576,7 @@ static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) { } if (file->flags & LFS_F_WRITING) { + file->size = lfs_max(file->pos, file->size); file->flags &= ~LFS_F_WRITING; file->flags |= LFS_F_DIRTY; } @@ -1632,6 +1636,7 @@ static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) { break; relocate: + LFS_DEBUG("Bad block at %d", file->block); err = lfs_file_relocate(lfs, file); if (err) { return err; @@ -1666,7 +1671,7 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { return err; } - // TODO entry read? + // TODO entry read function? lfs_entry_t entry = {.off = file->poff}; err = lfs_bd_read(lfs, cwd.pair[0], entry.off, &entry.d, sizeof(entry.d)); @@ -1675,12 +1680,12 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { return err; } LFS_ASSERT((0xf & entry.d.type) == LFS_TYPE_REG); - entry.size = 4 + entry.d.elen + entry.d.alen + entry.d.nlen; if (file->flags & LFS_F_INLINE) { - file->size = lfs_max(file->pos, file->size); lfs_ssize_t diff = file->size - entry.d.elen; + entry.d.type = LFS_STRUCT_INLINE | LFS_TYPE_REG; entry.d.elen = file->size; + entry.size = 4 + entry.d.elen + entry.d.alen + entry.d.nlen; err = lfs_dir_update(lfs, &cwd, &entry, &(struct lfs_region){ @@ -1693,12 +1698,17 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) { return err; } } else { + lfs_ssize_t diff = sizeof(entry.d) - entry.d.elen; + entry.d.type = LFS_STRUCT_CTZ | LFS_TYPE_REG; + entry.d.elen = sizeof(entry.d); entry.d.u.file.head = file->head; entry.d.u.file.size = file->size; + entry.size = 4 + entry.d.elen + entry.d.alen + entry.d.nlen; + // TODO combine up? err = lfs_dir_update(lfs, &cwd, &entry, &(struct lfs_region){ - 0, 0, + 0, diff, lfs_commit_mem, &entry.d, sizeof(entry.d)}); if (err) { return err; @@ -1737,12 +1747,13 @@ lfs_ssize_t lfs_file_read(lfs_t *lfs, lfs_file_t *file, nsize = size; while (nsize > 0) { + // TODO can this be collapsed? // check if we need a new block if (!(file->flags & LFS_F_READING) || file->off == lfs->cfg->block_size) { if (file->flags & LFS_F_INLINE) { file->block = 0xfffffffe; - file->off = 0; + file->off = file->pos; } else { int err = lfs_ctz_find(lfs, &file->cache, NULL, file->head, file->size, @@ -1806,19 +1817,31 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file, } } - while (nsize > 0) { - //printf("pos %d\n", file->pos + nsize); - // TODO combine with block allocation? - if (file->pos + nsize >= LFS_INLINE_MAX) { - file->flags &= ~LFS_F_INLINE; + // TODO combine with block allocation? + // TODO need to move out if no longer fits in block also + // TODO store INLINE_MAX in superblock? + if ((file->pos + nsize >= LFS_INLINE_MAX) || + (file->pos + nsize >= lfs->cfg->read_size)) { + int err = lfs_file_relocate(lfs, file); + if (err) { + file->flags |= LFS_F_ERRED; + return err; } + file->flags &= ~LFS_F_INLINE; + file->flags |= LFS_F_WRITING; + } + + while (nsize > 0) { + // TODO can this be collapsed? + // TODO can we reduce this now that block 0 is never allocated? + // TODO actually, how does this behave if inline max == 0? // check if we need a new block if (!(file->flags & LFS_F_WRITING) || file->off == lfs->cfg->block_size) { if (file->flags & LFS_F_INLINE) { file->block = 0xfffffffe; - file->off = 0; + file->off = file->pos; } else { if (!(file->flags & LFS_F_WRITING) && file->pos > 0) { // find out which block we're extending from @@ -1910,6 +1933,8 @@ lfs_soff_t lfs_file_seek(lfs_t *lfs, lfs_file_t *file, return file->pos; } +// TODO handle inlining? +// TODO note at least needs tests for trunc on inlined file int lfs_file_truncate(lfs_t *lfs, lfs_file_t *file, lfs_off_t size) { if ((file->flags & 3) == LFS_O_RDONLY) { return LFS_ERR_BADF; @@ -2002,8 +2027,10 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) { memset(info, 0, sizeof(*info)); info->type = 0xf & entry.d.type; - if (info->type == LFS_TYPE_REG) { + if (entry.d.type == (LFS_STRUCT_CTZ | LFS_TYPE_REG)) { info->size = entry.d.u.file.size; + } else if (entry.d.type == (LFS_STRUCT_INLINE | LFS_TYPE_REG)) { + info->size = entry.d.elen; } if (lfs_paircmp(entry.d.u.dir, lfs->root) == 0) { diff --git a/tests/test_dirs.sh b/tests/test_dirs.sh index 11dc26e..53d76f7 100755 --- a/tests/test_dirs.sh +++ b/tests/test_dirs.sh @@ -357,7 +357,7 @@ tests/test.py << TEST TEST echo "--- Multi-block directory with files ---" -tests/test.py -s << TEST +tests/test.py << TEST lfs_mount(&lfs, &cfg) => 0; lfs_mkdir(&lfs, "prickly-pear") => 0; for (int i = 0; i < $LARGESIZE; i++) {