From 3eb2f38279aadb35234c5df1fb8e54fd2a035be1 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Wed, 22 Nov 2017 15:28:15 -0600 Subject: [PATCH] Squashed 'littlefs/' changes from 996cd8a..5ee20e8 5ee20e8 Fixed pipefail issue that was preventing CI from reporting errors bf78b09 Added directory list for synchronizing in flight directories e169d06 Removed vestigial function declaration git-subtree-dir: littlefs git-subtree-split: 5ee20e8d774adf0bb538269870b3552fdfc0e046 --- Makefile | 4 ++- lfs.c | 82 +++++++++++++++++++++++++++++++--------------- lfs.h | 5 ++- tests/test_dirs.sh | 46 ++++++++++++++++++++++++-- 4 files changed, 104 insertions(+), 33 deletions(-) diff --git a/Makefile b/Makefile index 2ef12876ee..cf978e7929 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,8 @@ ASM := $(SRC:.c=.s) TEST := $(patsubst tests/%.sh,%,$(wildcard tests/test_*)) +SHELL = /bin/bash -o pipefail + ifdef DEBUG CFLAGS += -O0 -g3 else @@ -35,7 +37,7 @@ test: test_format test_dirs test_files test_seek test_parallel \ test_alloc test_paths test_orphan test_move test_corrupt test_%: tests/test_%.sh ifdef QUIET - ./$< | sed '/^[^-=]/d' + ./$< | sed -n '/^[-=]/p' else ./$< endif diff --git a/lfs.c b/lfs.c index cddc6fa7ff..ea116d27c9 100644 --- a/lfs.c +++ b/lfs.c @@ -569,7 +569,18 @@ relocate: // update references if we relocated LFS_DEBUG("Relocating %d %d to %d %d", oldpair[0], oldpair[1], dir->pair[0], dir->pair[1]); - return lfs_relocate(lfs, oldpair, dir->pair); + int err = lfs_relocate(lfs, oldpair, dir->pair); + if (err) { + return err; + } + } + + // shift over any directories that are affected + for (lfs_dir_t *d = lfs->dirs; d; d = d->next) { + if (lfs_paircmp(d->pair, dir->pair) == 0) { + d->pair[0] = dir->pair[0]; + d->pair[1] = dir->pair[1]; + } } return 0; @@ -628,7 +639,7 @@ static int lfs_dir_append(lfs_t *lfs, lfs_dir_t *dir, } static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { - // either shift out the one entry or remove the whole dir block + // check if we should just drop the directory block if ((dir->d.size & 0x7fffffff) == sizeof(dir->d)+4 + lfs_entry_size(entry)) { lfs_dir_t pdir; @@ -637,38 +648,44 @@ static int lfs_dir_remove(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { return res; } - if (!(pdir.d.size & 0x80000000)) { - return lfs_dir_commit(lfs, dir, (struct lfs_region[]){ - {entry->off, lfs_entry_size(entry), NULL, 0}, - }, 1); - } else { + if (pdir.d.size & 0x80000000) { pdir.d.size &= dir->d.size | 0x7fffffff; pdir.d.tail[0] = dir->d.tail[0]; pdir.d.tail[1] = dir->d.tail[1]; return lfs_dir_commit(lfs, &pdir, NULL, 0); } - } else { - int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ - {entry->off, lfs_entry_size(entry), NULL, 0}, - }, 1); - if (err) { - return err; - } + } - // shift over any files that are affected - for (lfs_file_t *f = lfs->files; f; f = f->next) { - if (lfs_paircmp(f->pair, dir->pair) == 0) { - if (f->poff == entry->off) { - f->pair[0] = 0xffffffff; - f->pair[1] = 0xffffffff; - } else if (f->poff > entry->off) { - f->poff -= lfs_entry_size(entry); - } + // shift out the entry + int err = lfs_dir_commit(lfs, dir, (struct lfs_region[]){ + {entry->off, lfs_entry_size(entry), NULL, 0}, + }, 1); + if (err) { + return err; + } + + // shift over any files/directories that are affected + for (lfs_file_t *f = lfs->files; f; f = f->next) { + if (lfs_paircmp(f->pair, dir->pair) == 0) { + if (f->poff == entry->off) { + f->pair[0] = 0xffffffff; + f->pair[1] = 0xffffffff; + } else if (f->poff > entry->off) { + f->poff -= lfs_entry_size(entry); } } - - return 0; } + + for (lfs_dir_t *d = lfs->dirs; d; d = d->next) { + if (lfs_paircmp(d->pair, dir->pair) == 0) { + if (d->off > entry->off) { + d->off -= lfs_entry_size(entry); + d->pos -= lfs_entry_size(entry); + } + } + } + + return 0; } static int lfs_dir_next(lfs_t *lfs, lfs_dir_t *dir, lfs_entry_t *entry) { @@ -894,11 +911,23 @@ int lfs_dir_open(lfs_t *lfs, lfs_dir_t *dir, const char *path) { dir->head[1] = dir->pair[1]; dir->pos = sizeof(dir->d) - 2; dir->off = sizeof(dir->d); + + // add to list of directories + dir->next = lfs->dirs; + lfs->dirs = dir; + return 0; } int lfs_dir_close(lfs_t *lfs, lfs_dir_t *dir) { - // do nothing, dir is always synchronized + // remove from list of directories + for (lfs_dir_t **p = &lfs->dirs; *p; p = &(*p)->next) { + if (*p == dir) { + *p = dir->next; + break; + } + } + return 0; } @@ -1902,6 +1931,7 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { lfs->root[0] = 0xffffffff; lfs->root[1] = 0xffffffff; lfs->files = NULL; + lfs->dirs = NULL; lfs->deorphaned = false; return 0; diff --git a/lfs.h b/lfs.h index 7757f8b9b4..51d0a86230 100644 --- a/lfs.h +++ b/lfs.h @@ -207,6 +207,7 @@ typedef struct lfs_file { } lfs_file_t; typedef struct lfs_dir { + struct lfs_dir *next; lfs_block_t pair[2]; lfs_off_t off; @@ -249,6 +250,7 @@ typedef struct lfs { lfs_block_t root[2]; lfs_file_t *files; + lfs_dir_t *dirs; lfs_cache_t rcache; lfs_cache_t pcache; @@ -445,8 +447,5 @@ int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data); // Returns a negative error code on failure. int lfs_deorphan(lfs_t *lfs); -// TODO doc -int lfs_deduplicate(lfs_t *lfs); - #endif diff --git a/tests/test_dirs.sh b/tests/test_dirs.sh index 8b69e7e8ce..431889007a 100755 --- a/tests/test_dirs.sh +++ b/tests/test_dirs.sh @@ -282,6 +282,49 @@ tests/test.py << TEST lfs_unmount(&lfs) => 0; TEST +echo "--- Recursive remove ---" +tests/test.py << TEST + lfs_mount(&lfs, &cfg) => 0; + lfs_remove(&lfs, "coldpotato") => LFS_ERR_INVAL; + + lfs_dir_open(&lfs, &dir[0], "coldpotato") => 0; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + + while (true) { + int err = lfs_dir_read(&lfs, &dir[0], &info); + err >= 0 => 1; + if (err == 0) { + break; + } + + strcpy((char*)buffer, "coldpotato/"); + strcat((char*)buffer, info.name); + lfs_remove(&lfs, (char*)buffer) => 0; + } + + lfs_remove(&lfs, "coldpotato") => 0; +TEST +tests/test.py << TEST + lfs_mount(&lfs, &cfg) => 0; + lfs_dir_open(&lfs, &dir[0], "/") => 0; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, ".") => 0; + info.type => LFS_TYPE_DIR; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, "..") => 0; + info.type => LFS_TYPE_DIR; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, "burito") => 0; + info.type => LFS_TYPE_REG; + lfs_dir_read(&lfs, &dir[0], &info) => 1; + strcmp(info.name, "cactus") => 0; + info.type => LFS_TYPE_DIR; + lfs_dir_read(&lfs, &dir[0], &info) => 0; + lfs_dir_close(&lfs, &dir[0]) => 0; + lfs_unmount(&lfs) => 0; +TEST + echo "--- Multi-block remove ---" tests/test.py << TEST lfs_mount(&lfs, &cfg) => 0; @@ -307,9 +350,6 @@ tests/test.py << TEST lfs_dir_read(&lfs, &dir[0], &info) => 1; strcmp(info.name, "burito") => 0; info.type => LFS_TYPE_REG; - lfs_dir_read(&lfs, &dir[0], &info) => 1; - strcmp(info.name, "coldpotato") => 0; - info.type => LFS_TYPE_DIR; lfs_dir_read(&lfs, &dir[0], &info) => 0; lfs_dir_close(&lfs, &dir[0]) => 0; lfs_unmount(&lfs) => 0;