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>2019-07-10 01:51:15 +0300
committerChristopher Haster <chaster@utexas.edu>2019-07-29 05:34:17 +0300
commit0d4c0b105cabc7dd76a9aaa3f82f655a7b35aa79 (patch)
tree407ab6e0a7b9a910fc4e72b9d8fa192444d8dc56
parent4850e01e14373d9808b78f3fb7833e26583744c1 (diff)
Fixed issue where inline files were not cleaned up
Due to the logging nature of metadata pairs, switching from inline files (type3 = 0x201) to CTZ skip-lists (type3 = 0x202) does not explicitly erase inline files, but instead leaves them up to compaction to omit. To save code size, this is handled by the same logic that deduplicates tags. Unfortunately, this wasn't working. Due to a relatively late change in v2 the struct's type field was changed to no longer be a part of determining a tag's "uniqueness". A part of this should have been the modification of directory traversal filtering to respect type-dependent uniqueness, but I missed this. The fix is to add in correct type-dependent filtering. Also there was some clean up necessary around removing delete tags during compaction and outlining files. Note that while this appears to conflict with the possibility of combining inline + ctz files, we still have the device-side-only LFS_TYPE_FROM tag that can be repurposed for 256 additional inline "chunks". Found by Johnxjj
-rw-r--r--lfs.c40
1 files changed, 25 insertions, 15 deletions
diff --git a/lfs.c b/lfs.c
index dd63677..70f54f3 100644
--- a/lfs.c
+++ b/lfs.c
@@ -403,7 +403,7 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
static int lfs_dir_compact(lfs_t *lfs,
lfs_mdir_t *dir, const struct lfs_mattr *attrs, int attrcount,
lfs_mdir_t *source, uint16_t begin, uint16_t end);
-static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file);
+static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file);
static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file);
static void lfs_fs_preporphans(lfs_t *lfs, int8_t orphans);
static void lfs_fs_prepmove(lfs_t *lfs,
@@ -619,11 +619,17 @@ static int lfs_dir_traverse_filter(void *p,
lfs_tag_t *filtertag = p;
(void)buffer;
+ // which mask depends on unique bit in tag structure
+ uint32_t mask = (tag & LFS_MKTAG(0x100, 0, 0))
+ ? LFS_MKTAG(0x7ff, 0x3ff, 0)
+ : LFS_MKTAG(0x700, 0x3ff, 0);
+
// check for redundancy
- uint32_t mask = LFS_MKTAG(0x7ff, 0x3ff, 0);
if ((mask & tag) == (mask & *filtertag) ||
- (mask & tag) == (LFS_MKTAG(LFS_TYPE_DELETE, 0, 0) |
- (LFS_MKTAG(0, 0x3ff, 0) & *filtertag))) {
+ lfs_tag_isdelete(*filtertag) ||
+ (LFS_MKTAG(0x7ff, 0x3ff, 0) & tag) == (
+ LFS_MKTAG(LFS_TYPE_DELETE, 0, 0) |
+ (LFS_MKTAG(0, 0x3ff, 0) & *filtertag))) {
return true;
}
@@ -1632,11 +1638,7 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir,
if (dir != &f->m && lfs_pair_cmp(f->m.pair, dir->pair) == 0 &&
f->type == LFS_TYPE_REG && (f->flags & LFS_F_INLINE) &&
f->ctz.size > lfs->cfg->cache_size) {
- f->flags &= ~LFS_F_READING;
- f->off = 0;
-
- lfs_alloc_ack(lfs);
- int err = lfs_file_relocate(lfs, f);
+ int err = lfs_file_outline(lfs, f);
if (err) {
return err;
}
@@ -2471,7 +2473,6 @@ static int lfs_file_relocate(lfs_t *lfs, lfs_file_t *file) {
lfs_cache_zero(lfs, &lfs->pcache);
file->block = nblock;
- file->flags &= ~LFS_F_INLINE;
file->flags |= LFS_F_WRITING;
return 0;
@@ -2483,6 +2484,18 @@ relocate:
}
}
+static int lfs_file_outline(lfs_t *lfs, lfs_file_t *file) {
+ file->off = file->pos;
+ lfs_alloc_ack(lfs);
+ int err = lfs_file_relocate(lfs, file);
+ if (err) {
+ return err;
+ }
+
+ file->flags &= ~LFS_F_INLINE;
+ return 0;
+}
+
static int lfs_file_flush(lfs_t *lfs, lfs_file_t *file) {
LFS_ASSERT(file->flags & LFS_F_OPENED);
@@ -2616,8 +2629,7 @@ int lfs_file_sync(lfs_t *lfs, lfs_file_t *file) {
relocate:
// inline file doesn't fit anymore
- file->off = file->pos;
- err = lfs_file_relocate(lfs, file);
+ err = lfs_file_outline(lfs, file);
if (err) {
file->flags |= LFS_F_ERRED;
return err;
@@ -2740,9 +2752,7 @@ lfs_ssize_t lfs_file_write(lfs_t *lfs, lfs_file_t *file,
lfs_min(0x3fe, lfs_min(
lfs->cfg->cache_size, lfs->cfg->block_size/8))) {
// inline file doesn't fit anymore
- file->off = file->pos;
- lfs_alloc_ack(lfs);
- int err = lfs_file_relocate(lfs, file);
+ int err = lfs_file_outline(lfs, file);
if (err) {
file->flags |= LFS_F_ERRED;
return err;