From 3e246da52c206c1989ae598b444693941f89dc95 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Mon, 30 Jul 2018 09:10:04 -0500 Subject: [PATCH] Fixed the orphan test to handle logging metadata-pairs The main issue here was that the old orphan test relied on deleting the block that contained the most recent update. In the new design this doesn't really work since updates get appended to metadata-pairs incrementally. This is fixed by instead using the truncate command on the appropriate block. We're now passing orphan tests. --- lfs.c | 42 +++++++++++++++++++++++++++--------------- lfs.h | 27 +++++++++------------------ tests/test_corrupt.sh | 3 +++ tests/test_orphan.sh | 32 ++++++++++++++++++-------------- 4 files changed, 57 insertions(+), 47 deletions(-) diff --git a/lfs.c b/lfs.c index ae8b4c5..03c4b81 100644 --- a/lfs.c +++ b/lfs.c @@ -3255,6 +3255,12 @@ int lfs_fs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data) { } */ static int lfs_pred(lfs_t *lfs, const lfs_block_t pair[2], lfs_mdir_t *pdir) { + if (lfs_pairisnull(lfs->root)) { + // TODO best place for this? + // TODO needed for relocate + return LFS_ERR_NOENT; + } + // iterate over all directory directory entries pdir->tail[0] = 0; pdir->tail[1] = 1; @@ -3275,6 +3281,11 @@ static int lfs_pred(lfs_t *lfs, const lfs_block_t pair[2], lfs_mdir_t *pdir) { static int32_t lfs_parent(lfs_t *lfs, const lfs_block_t pair[2], lfs_mdir_t *parent) { + if (lfs_pairisnull(lfs->root)) { + // TODO best place for this? + return LFS_ERR_NOENT; + } + // search for both orderings so we can reuse the find function lfs_block_t child[2] = {pair[0], pair[1]}; @@ -3531,18 +3542,19 @@ int lfs_deorphan(lfs_t *lfs) { // return lfs_dir_setattrs(lfs, &dir, &entry, attrs, count); //} -//static int lfs_fs_size_count(void *p, lfs_block_t block) { -// lfs_size_t *size = p; -// *size += 1; -// return 0; -//} -// -//lfs_ssize_t lfs_fs_size(lfs_t *lfs) { -// lfs_size_t size = 0; -// int err = lfs_fs_traverse(lfs, lfs_fs_size_count, &size); -// if (err) { -// return err; -// } -// -// return size; -//} +// TODO need lfs? +static int lfs_fs_size_count(lfs_t *lfs, void *p, lfs_block_t block) { + lfs_size_t *size = p; + *size += 1; + return 0; +} + +lfs_ssize_t lfs_fs_size(lfs_t *lfs) { + lfs_size_t size = 0; + int err = lfs_fs_traverse(lfs, lfs_fs_size_count, &size); + if (err) { + return err; + } + + return size; +} diff --git a/lfs.h b/lfs.h index b83a25c..b384ed3 100644 --- a/lfs.h +++ b/lfs.h @@ -249,7 +249,8 @@ struct lfs_info { // Custom attribute structure struct lfs_attr { - // Type of attribute, provided by user and used to identify the attribute + // 8-bit Type of attribute, provided by user and used to + // identify the attribute uint8_t type; // Pointer to buffer containing the attribute @@ -259,7 +260,7 @@ struct lfs_attr { lfs_size_t size; // Pointer to next attribute in linked list - const struct lfs_attr *next; + struct lfs_attr *next; }; // Optional configuration provided during lfs_file_opencfg @@ -268,9 +269,9 @@ struct lfs_file_config { // If NULL, malloc will be used by default. void *buffer; - // Optional, custom attributes + // Optional, linked list of custom attributes. // TODO document more - const struct lfs_attr *attrs; + struct lfs_attr *attrs; }; @@ -582,7 +583,8 @@ lfs_soff_t lfs_dir_tell(lfs_t *lfs, lfs_dir_t *dir); int lfs_dir_rewind(lfs_t *lfs, lfs_dir_t *dir); -/// Filesystem filesystem operations /// +/// Filesystem filesystem operations /// TODO choose one +/// Miscellaneous littlefs specific operations /// TODO choose one // Get custom attributes on the filesystem // @@ -616,9 +618,6 @@ int lfs_fs_setattr(lfs_t *lfs, // Returns the number of allocated blocks, or a negative error code on failure. lfs_ssize_t lfs_fs_size(lfs_t *lfs); - -/// Miscellaneous littlefs specific operations /// - // Traverse through all blocks in use by the filesystem // // The provided callback will be called with each block address that is @@ -626,16 +625,8 @@ lfs_ssize_t lfs_fs_size(lfs_t *lfs); // blocks are in use or how much of the storage is available. // // Returns a negative error code on failure. -int lfs_traverse(lfs_t *lfs, int (*cb)(void*, lfs_block_t), void *data); - -// Prunes any recoverable errors that may have occured in the filesystem -// -// Not needed to be called by user unless an operation is interrupted -// but the filesystem is still mounted. This is already called on first -// allocation. -// -// Returns a negative error code on failure. -int lfs_deorphan(lfs_t *lfs); +// TODO don't pass lfs_t? +int lfs_fs_traverse(lfs_t *lfs, int (*cb)(lfs_t*, void*, lfs_block_t), void *data); #endif diff --git a/tests/test_corrupt.sh b/tests/test_corrupt.sh index 1491dac..faa6f7e 100755 --- a/tests/test_corrupt.sh +++ b/tests/test_corrupt.sh @@ -78,8 +78,11 @@ do rm -rf blocks mkdir blocks ln -s /dev/zero blocks/$(printf '%x' $i) + echo $i 1i lfs_mktree + echo $i 2i lfs_chktree + echo $i 3i done echo "--- Block persistance ---" diff --git a/tests/test_orphan.sh b/tests/test_orphan.sh index 71d6d4f..a76088b 100755 --- a/tests/test_orphan.sh +++ b/tests/test_orphan.sh @@ -15,25 +15,29 @@ tests/test.py << TEST lfs_mkdir(&lfs, "parent/child") => 0; lfs_remove(&lfs, "parent/orphan") => 0; TEST -# remove most recent file, this should be the update to the previous +# corrupt most recent commit, this should be the update to the previous # linked-list entry and should orphan the child -rm -v blocks/8 -tests/test.py << TEST +truncate -s-14 blocks/8 +tests/test.py << TEST lfs_mount(&lfs, &cfg) => 0; - lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; - unsigned before = 0; - lfs_traverse(&lfs, test_count, &before) => 0; - test_log("before", before); - - lfs_deorphan(&lfs) => 0; lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; - unsigned after = 0; - lfs_traverse(&lfs, test_count, &after) => 0; - test_log("after", after); + lfs_ssize_t before = lfs_fs_size(&lfs); + before => 10; + + lfs_unmount(&lfs) => 0; + lfs_mount(&lfs, &cfg) => 0; + + lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; + lfs_ssize_t orphaned = lfs_fs_size(&lfs); + orphaned => 10; + + lfs_mkdir(&lfs, "parent/otherchild") => 0; + + lfs_stat(&lfs, "parent/orphan", &info) => LFS_ERR_NOENT; + lfs_ssize_t deorphaned = lfs_fs_size(&lfs); + deorphaned => 10; - int diff = before - after; - diff => 2; lfs_unmount(&lfs) => 0; TEST