diff --git a/lfs.c b/lfs.c index 71ee40e1..31a95df0 100644 --- a/lfs.c +++ b/lfs.c @@ -5079,13 +5079,15 @@ static inline lfs_size_t lfsr_mdir_weight(const lfsr_mdir_t *mdir) { } // track "opened" mdirs that may need to by updated -static void lfsr_mdir_addopened(lfs_t *lfs, lfsr_openedmdir_t *opened) { - opened->next = lfs->opened; - lfs->opened = opened; +static void lfsr_mdir_addopened(lfs_t *lfs, + uint8_t type, lfsr_openedmdir_t *opened) { + opened->next = lfs->opened[type]; + lfs->opened[type] = opened; } -static void lfsr_mdir_removeopened(lfs_t *lfs, lfsr_openedmdir_t *opened) { - for (lfsr_openedmdir_t **p = &lfs->opened; *p; p = &(*p)->next) { +static void lfsr_mdir_removeopened(lfs_t *lfs, + uint8_t type, lfsr_openedmdir_t *opened) { + for (lfsr_openedmdir_t **p = &lfs->opened[type]; *p; p = &(*p)->next) { if (*p == opened) { *p = (*p)->next; break; @@ -5093,8 +5095,9 @@ static void lfsr_mdir_removeopened(lfs_t *lfs, lfsr_openedmdir_t *opened) { } } -static bool lfsr_mdir_isopened(lfs_t *lfs, const lfsr_openedmdir_t *opened) { - for (lfsr_openedmdir_t *p = lfs->opened; p; p = p->next) { +static bool lfsr_mdir_isopened(lfs_t *lfs, + uint8_t type, const lfsr_openedmdir_t *opened) { + for (lfsr_openedmdir_t *p = lfs->opened[type]; p; p = p->next) { if (p == opened) { return true; } @@ -5669,6 +5672,7 @@ static int lfsr_mtree_split_(lfs_t *lfs, lfsr_btree_t *mtree_, } else if (mdir_->rbyd.weight > 0) { LFS_DEBUG("Dropping mdir 0x{%"PRIx32",%"PRIx32"}", mdir_->rbyd.block, mdir_->redund_block); + mdir_->mid = LFSR_MID_RM; // update our mtree uint8_t buf[LFSR_MPTR_DSIZE]; @@ -5687,6 +5691,7 @@ static int lfsr_mtree_split_(lfs_t *lfs, lfsr_btree_t *mtree_, } else if (msibling_->rbyd.weight > 0) { LFS_DEBUG("Dropping mdir 0x{%"PRIx32",%"PRIx32"}", msibling_->rbyd.block, msibling_->redund_block); + msibling_->mid = LFSR_MID_RM; // update our mtree uint8_t buf[LFSR_MPTR_DSIZE]; @@ -5707,6 +5712,8 @@ static int lfsr_mtree_split_(lfs_t *lfs, lfsr_btree_t *mtree_, mdir_->rbyd.block, mdir_->redund_block); LFS_DEBUG("Dropping mdir 0x{%"PRIx32",%"PRIx32"}", msibling_->rbyd.block, msibling_->redund_block); + mdir_->mid = LFSR_MID_RM; + msibling_->mid = LFSR_MID_RM; // update our mtree err = lfsr_btree_pop(lfs, mtree_, mid); @@ -5817,6 +5824,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid, } else { LFS_DEBUG("Dropping mdir 0x{%"PRIx32",%"PRIx32"}", mdir_.rbyd.block, mdir_.redund_block); + mdir_.mid = LFSR_MID_RM; // don't really need to update our mtree here } @@ -5856,6 +5864,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid, } else if (mdir->mid != LFSR_MID_MROOT && mdir_.rbyd.weight == 0) { LFS_DEBUG("Dropping mdir 0x{%"PRIx32",%"PRIx32"}", mdir->rbyd.block, mdir->redund_block); + mdir_.mid = LFSR_MID_RM; // update our mtree err = lfsr_btree_pop(lfs, &mtree_, mdir->mid); @@ -6116,48 +6125,58 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, lfs_ssize_t *rid, } // update any opened mdirs - for (lfsr_openedmdir_t *opened = lfs->opened; - opened; - opened = opened->next) { - // avoid double-updating our current mdir - if (&opened->mdir == mdir) { - continue; - } - - if (opened->mdir.mid == mdir->mid) { - LFS_ASSERT(opened->rid < (lfs_ssize_t)mdir->rbyd.weight); + for (uint8_t type = 0; type < 2; type++) { + for (lfsr_openedmdir_t *opened = lfs->opened[type]; + opened; + opened = opened->next) { + // avoid double-updating our current mdir + if (&opened->mdir == mdir) { + continue; + } // first play out any attrs that change our rid for (lfs_size_t i = 0; i < attr_count; i++) { - if (opened->rid >= attrs[i].id) { + if (opened->mdir.mid == mdir->mid + && opened->rid >= attrs[i].id) { + LFS_ASSERT(opened->rid <= (lfs_ssize_t)mdir->rbyd.weight); // removed? - if (opened->rid + attrs[i].delta < attrs[i].id) { - opened->rid = -2; + if (type == LFS_TYPE_REG + && opened->rid + attrs[i].delta < attrs[i].id) { opened->mdir.mid = LFSR_MID_RM; } else { opened->rid += attrs[i].delta; } } + + // adjust dir positions if any delta changes + if (type == LFS_TYPE_DIR + && (opened->mdir.mid > mdir->mid + || (opened->mdir.mid == mdir->mid + && opened->rid >= attrs[i].id))) { + ((lfsr_dir_t*)opened)->pos += attrs[i].delta; + } } - // TODO wait shouldn't this be mid? - // update mdir to follow rid - if (opened->rid == -2) { - // skip removed mdirs - } else if (opened->rid >= (lfs_ssize_t)mdir_.rbyd.weight) { - LFS_ASSERT(lfsr_btree_weight(&mtree_) - != lfsr_mtree_weight(lfs)); - opened->rid = opened->rid - mdir_.rbyd.weight; - opened->mdir = msibling_; - } else { - opened->mdir = mdir_; + // update mid if we had a split or drop + if (opened->mdir.mid == mdir->mid) { + if (opened->rid >= (lfs_ssize_t)mdir_.rbyd.weight) { + LFS_ASSERT(lfsr_btree_weight(&mtree_) + != lfsr_mtree_weight(lfs)); + opened->rid = opened->rid - mdir_.rbyd.weight; + opened->mdir = msibling_; + } else { + opened->mdir = mdir_; + // if dropped, rewind to previous mid, this is needed for + // dir read to find the next mdir correctly + if (type == LFS_TYPE_DIR && mdir_.mid == LFSR_MID_RM) { + opened->mdir.mid = mdir->mid - 1; + } + } + } else if (opened->mdir.mid > mdir->mid + && lfsr_btree_weight(&mtree_) != lfsr_mtree_weight(lfs)) { + opened->mdir.mid += lfsr_btree_weight(&mtree_) + - lfsr_mtree_weight(lfs); } - - // update mid if we had a split or drop - } else if (opened->mdir.mid > mdir->mid - && lfsr_btree_weight(&mtree_) != lfsr_mtree_weight(lfs)) { - opened->mdir.mid += lfsr_btree_weight(&mtree_) - - lfsr_mtree_weight(lfs); } } @@ -7300,7 +7319,7 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) { // as "opened" temporarily // TODO is this the best workaround for rid update issues? parent.rid -= 1; - lfsr_mdir_addopened(lfs, &parent); + lfsr_mdir_addopened(lfs, LFS_TYPE_REG, &parent); // Conveniently, we just found where our dstart should go. The dstart // tag is an empty entry that marks our directory as being allocated. @@ -7323,7 +7342,7 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) { goto failed_with_parent; } - lfsr_mdir_removeopened(lfs, &parent); + lfsr_mdir_removeopened(lfs, LFS_TYPE_REG, &parent); parent.rid += 1; // commit our new directory into our parent, zeroing out our grm @@ -7339,7 +7358,7 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) { return 0; failed_with_parent: - lfsr_mdir_removeopened(lfs, &parent); + lfsr_mdir_removeopened(lfs, LFS_TYPE_REG, &parent); return err; } @@ -7496,14 +7515,14 @@ int lfsr_dir_open(lfs_t *lfs, lfsr_dir_t *dir, const char *path) { } // add to tracked mdirs - lfsr_mdir_addopened(lfs, &dir->mdir); - dir->off = 0; + lfsr_mdir_addopened(lfs, LFS_TYPE_DIR, &dir->mdir); + dir->pos = 0; return 0; } int lfsr_dir_close(lfs_t *lfs, lfsr_dir_t *dir) { // remove from tracked mdirs - lfsr_mdir_removeopened(lfs, &dir->mdir); + lfsr_mdir_removeopened(lfs, LFS_TYPE_DIR, &dir->mdir); return 0; } @@ -7539,15 +7558,15 @@ int lfsr_dir_read(lfs_t *lfs, lfsr_dir_t *dir, struct lfs_info *info) { memset(info, 0, sizeof(struct lfs_info)); // handle "." and ".." specially - if (dir->off == 0) { + if (dir->pos == 0) { info->type = LFS_TYPE_DIR; strcpy(info->name, "."); - dir->off += 1; + dir->pos += 1; return 0; - } else if (dir->off == 1) { + } else if (dir->pos == 1) { info->type = LFS_TYPE_DIR; strcpy(info->name, ".."); - dir->off += 1; + dir->pos += 1; return 0; } @@ -11131,8 +11150,9 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { // TODO maybe reorganize this function? - // zero opened mdir list - lfs->opened = NULL; + // zero linked-lists of opened mdirs + lfs->opened[LFS_TYPE_REG] = NULL; + lfs->opened[LFS_TYPE_DIR] = NULL; // zero gstate memset(lfs->grm, 0, LFSR_GRM_DSIZE); diff --git a/lfs.h b/lfs.h index 5f3fb9d8..20a40691 100644 --- a/lfs.h +++ b/lfs.h @@ -420,7 +420,7 @@ typedef struct lfs_dir { typedef struct lfsr_dir { lfsr_openedmdir_t mdir; - lfs_off_t off; + lfs_off_t pos; } lfsr_dir_t; // littlefs file type @@ -500,8 +500,9 @@ typedef struct lfs { uint8_t grm[LFSR_GRM_DSIZE]; uint8_t grmd[LFSR_GRM_DSIZE]; - // linked-list of opened mdirs - lfsr_openedmdir_t *opened; + // linked-lists of opened mdirs, we keep a separate linked-list + // for each type since these need to be handled a bit differently + lfsr_openedmdir_t *opened[2]; #ifdef LFS_MIGRATE struct lfs1 *lfs1; diff --git a/tests/t3_mtree.toml b/tests/t3_mtree.toml index 5cf99b78..5863e2fd 100644 --- a/tests/t3_mtree.toml +++ b/tests/t3_mtree.toml @@ -2680,8 +2680,8 @@ code = ''' lfsr_openedmdir_t left_neighbor = {.rid=0, .mdir=lfs.mroot}; lfsr_openedmdir_t right_neighbor = {.rid=1, .mdir=lfs.mroot}; - lfsr_mdir_addopened(&lfs, &left_neighbor); - lfsr_mdir_addopened(&lfs, &right_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); // insert a new entry, this should update our neighbors lfsr_mdir_commit(&lfs, &lfs.mroot, &(lfs_ssize_t){-1}, LFSR_ATTRS( @@ -2703,8 +2703,8 @@ code = ''' assert(right_neighbor.mdir.mid == -1); assert(memcmp(&right_neighbor.mdir, &lfs.mroot, sizeof(lfsr_mdir_t)) == 0); - lfsr_mdir_removeopened(&lfs, &left_neighbor); - lfsr_mdir_removeopened(&lfs, &right_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); lfsr_unmount(&lfs) => 0; ''' @@ -2729,8 +2729,8 @@ code = ''' lfsr_openedmdir_t left_neighbor = {.rid=0, .mdir=lfs.mroot}; lfsr_openedmdir_t right_neighbor = {.rid=1, .mdir=lfs.mroot}; - lfsr_mdir_addopened(&lfs, &left_neighbor); - lfsr_mdir_addopened(&lfs, &right_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); // try removing our left entry lfsr_mdir_commit(&lfs, &lfs.mroot, &(lfs_ssize_t){-1}, LFSR_ATTRS( @@ -2740,14 +2740,13 @@ code = ''' assert(lfs.mroot.rbyd.weight == 1); // assert that our neighbors were updated correctly - assert(left_neighbor.rid == -2); - assert(left_neighbor.mdir.mid == -2); + assert(left_neighbor.mdir.mid == LFSR_MID_RM); assert(right_neighbor.rid == 0); assert(right_neighbor.mdir.mid == -1); assert(memcmp(&right_neighbor.mdir, &lfs.mroot, sizeof(lfsr_mdir_t)) == 0); - lfsr_mdir_removeopened(&lfs, &left_neighbor); - lfsr_mdir_removeopened(&lfs, &right_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); lfsr_unmount(&lfs) => 0; ''' @@ -2772,8 +2771,8 @@ code = ''' lfsr_openedmdir_t left_neighbor = {.rid=0, .mdir=lfs.mroot}; lfsr_openedmdir_t right_neighbor = {.rid=1, .mdir=lfs.mroot}; - lfsr_mdir_addopened(&lfs, &left_neighbor); - lfsr_mdir_addopened(&lfs, &right_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); // try removing our left entry lfsr_mdir_commit(&lfs, &lfs.mroot, &(lfs_ssize_t){-1}, LFSR_ATTRS( @@ -2786,11 +2785,10 @@ code = ''' assert(left_neighbor.rid == 0); assert(left_neighbor.mdir.mid == -1); assert(memcmp(&left_neighbor.mdir, &lfs.mroot, sizeof(lfsr_mdir_t)) == 0); - assert(right_neighbor.rid == -2); - assert(right_neighbor.mdir.mid == -2); + assert(right_neighbor.mdir.mid == LFSR_MID_RM); - lfsr_mdir_removeopened(&lfs, &left_neighbor); - lfsr_mdir_removeopened(&lfs, &right_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); lfsr_unmount(&lfs) => 0; ''' @@ -2817,8 +2815,8 @@ code = ''' lfsr_openedmdir_t left_neighbor = {.rid=0, .mdir=lfs.mroot}; lfsr_openedmdir_t right_neighbor = {.rid=1, .mdir=lfs.mroot}; - lfsr_mdir_addopened(&lfs, &left_neighbor); - lfsr_mdir_addopened(&lfs, &right_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); // prepare mroot with a large attr so the next entry can not fit uint8_t buffer[SIZE]; @@ -2862,8 +2860,8 @@ code = ''' assert(right_neighbor.mdir.mid == 0); assert(memcmp(&right_neighbor.mdir, &mdir, sizeof(lfsr_mdir_t)) == 0); - lfsr_mdir_removeopened(&lfs, &left_neighbor); - lfsr_mdir_removeopened(&lfs, &right_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); lfsr_unmount(&lfs) => 0; ''' @@ -2890,8 +2888,8 @@ code = ''' lfsr_openedmdir_t left_neighbor = {.rid=0, .mdir=lfs.mroot}; lfsr_openedmdir_t right_neighbor = {.rid=1, .mdir=lfs.mroot}; - lfsr_mdir_addopened(&lfs, &left_neighbor); - lfsr_mdir_addopened(&lfs, &right_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); // create 2 large entries that needs to be uninlined and split uint8_t buffer[SIZE]; @@ -2935,8 +2933,8 @@ code = ''' assert(right_neighbor.mdir.mid == 1); assert(memcmp(&right_neighbor.mdir, &msibling, sizeof(lfsr_mdir_t)) == 0); - lfsr_mdir_removeopened(&lfs, &left_neighbor); - lfsr_mdir_removeopened(&lfs, &right_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); lfsr_unmount(&lfs) => 0; ''' @@ -2963,8 +2961,8 @@ code = ''' lfsr_openedmdir_t left_neighbor = {.rid=0, .mdir=lfs.mroot}; lfsr_openedmdir_t right_neighbor = {.rid=1, .mdir=lfs.mroot}; - lfsr_mdir_addopened(&lfs, &left_neighbor); - lfsr_mdir_addopened(&lfs, &right_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); // create an uninlined mdir uint8_t buffer[SIZE]; @@ -3030,8 +3028,8 @@ code = ''' assert(right_neighbor.mdir.mid == 1); assert(memcmp(&right_neighbor.mdir, &msibling, sizeof(lfsr_mdir_t)) == 0); - lfsr_mdir_removeopened(&lfs, &left_neighbor); - lfsr_mdir_removeopened(&lfs, &right_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); lfsr_unmount(&lfs) => 0; ''' @@ -3060,8 +3058,8 @@ code = ''' lfsr_openedmdir_t left_neighbor = {.rid=0, .mdir=lfs.mroot}; lfsr_openedmdir_t right_neighbor = {.rid=1, .mdir=lfs.mroot}; - lfsr_mdir_addopened(&lfs, &left_neighbor); - lfsr_mdir_addopened(&lfs, &right_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); // prepare mroot with an attr uint8_t buffer[SIZE]; @@ -3095,8 +3093,8 @@ code = ''' assert(right_neighbor.mdir.mid == -1); assert(memcmp(&right_neighbor.mdir, &lfs.mroot, sizeof(lfsr_mdir_t)) == 0); - lfsr_mdir_removeopened(&lfs, &left_neighbor); - lfsr_mdir_removeopened(&lfs, &right_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); lfsr_unmount(&lfs) => 0; ''' @@ -3125,8 +3123,8 @@ code = ''' lfsr_openedmdir_t left_neighbor = {.rid=0, .mdir=lfs.mroot}; lfsr_openedmdir_t right_neighbor = {.rid=1, .mdir=lfs.mroot}; - lfsr_mdir_addopened(&lfs, &left_neighbor); - lfsr_mdir_addopened(&lfs, &right_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); // prepare mroot with a large attr so the next entry can not fit uint8_t buffer[SIZE]; @@ -3186,8 +3184,8 @@ code = ''' assert(right_neighbor.mdir.mid == 0); assert(memcmp(&right_neighbor.mdir, &mdir, sizeof(lfsr_mdir_t)) == 0); - lfsr_mdir_removeopened(&lfs, &left_neighbor); - lfsr_mdir_removeopened(&lfs, &right_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); lfsr_unmount(&lfs) => 0; ''' @@ -3254,8 +3252,8 @@ code = ''' assert(right_neighbor.mdir.rbyd.weight == 1); right_neighbor.rid = 0; - lfsr_mdir_addopened(&lfs, &left_neighbor); - lfsr_mdir_addopened(&lfs, &right_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); // cause middle mdir to split lfsr_mtree_lookup(&lfs, 1, &mdir) => 0; @@ -3282,8 +3280,8 @@ code = ''' lfsr_mtree_lookup(&lfs, 3, &mdir) => 0; assert(memcmp(&right_neighbor.mdir, &mdir, sizeof(lfsr_mdir_t)) == 0); - lfsr_mdir_removeopened(&lfs, &left_neighbor); - lfsr_mdir_removeopened(&lfs, &right_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); lfsr_unmount(&lfs) => 0; ''' @@ -3350,8 +3348,8 @@ code = ''' assert(right_neighbor.mdir.rbyd.weight == 1); right_neighbor.rid = 0; - lfsr_mdir_addopened(&lfs, &left_neighbor); - lfsr_mdir_addopened(&lfs, &right_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_addopened(&lfs, LFS_TYPE_REG, &right_neighbor); // cause middle mdir to drop lfsr_mtree_lookup(&lfs, 1, &mdir) => 0; @@ -3373,8 +3371,8 @@ code = ''' lfsr_mtree_lookup(&lfs, 1, &mdir) => 0; assert(memcmp(&right_neighbor.mdir, &mdir, sizeof(lfsr_mdir_t)) == 0); - lfsr_mdir_removeopened(&lfs, &left_neighbor); - lfsr_mdir_removeopened(&lfs, &right_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &left_neighbor); + lfsr_mdir_removeopened(&lfs, LFS_TYPE_REG, &right_neighbor); lfsr_unmount(&lfs) => 0; ''' diff --git a/tests/t5_dirs.toml b/tests/t5_dirs.toml index 3f1092c9..924f2cab 100644 --- a/tests/t5_dirs.toml +++ b/tests/t5_dirs.toml @@ -2803,115 +2803,113 @@ code = ''' lfsr_unmount(&lfs) => 0; ''' -# TODO this eventually +# Recursive here just refers to deleting entries in a directory while +# iterating over the directory # -## Recursive here just refers to deleting entries in a directory while -## iterating over the directory -## -## This is a useful feature, but it's unintuitive that this should have -## well-defined behavior, so make sure to test for it -#[cases.t5_dirs_rm_many_recursive] -#defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] -#defines.PARENT = [false, true] -## this test sort of fights against itself when powerloss testing, -## limit it to a _very_ small number of entries for this reason -#if = '!TEST_PL || N <= 32' -#reentrant = true -#code = ''' -# // format once per test -# lfs_t lfs; -# int err = lfsr_mount(&lfs, cfg); -# if (err) { -# lfsr_format(&lfs, cfg) => 0; -# lfsr_mount(&lfs, cfg) => 0; -# } -# -# if (PARENT) { -# err = lfsr_mkdir(&lfs, "pricklypear"); -# assert(!err || (TEST_PL && err == LFS_ERR_EXIST)); -# } -# -# // make this many directories -# for (lfs_size_t i = 0; i < N; i++) { -# char name[256]; -# sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i); -# err = lfsr_mkdir(&lfs, name); -# assert(!err || (TEST_PL && err == LFS_ERR_EXIST)); -# } -# -# // check that our mkdir worked -# for (lfs_size_t i = 0; i < N; i++) { -# char name[256]; -# sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i); -# struct lfs_info info; -# lfsr_stat(&lfs, name, &info) => 0; -# char name2[256]; -# sprintf(name2, "dir%04d", i); -# assert(strcmp(info.name, name2) == 0); -# assert(info.type == LFS_TYPE_DIR); -# } -# -# lfsr_dir_t dir; -# lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0; -# struct lfs_info info; -# lfsr_dir_read(&lfs, &dir, &info) => 0; -# assert(strcmp(info.name, ".") == 0); -# assert(info.type == LFS_TYPE_DIR); -# lfsr_dir_read(&lfs, &dir, &info) => 0; -# assert(strcmp(info.name, "..") == 0); -# assert(info.type == LFS_TYPE_DIR); -# for (lfs_size_t i = 0; i < N; i++) { -# char name[256]; -# sprintf(name, "dir%04d", i); -# lfsr_dir_read(&lfs, &dir, &info) => 0; -# assert(strcmp(info.name, name) == 0); -# assert(info.type == LFS_TYPE_DIR); -# } -# lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT; -# lfsr_dir_close(&lfs, &dir) => 0; -# -# // now remove directories recursively -# lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0; -# lfsr_dir_read(&lfs, &dir, &info) => 0; -# assert(strcmp(info.name, ".") == 0); -# assert(info.type == LFS_TYPE_DIR); -# lfsr_dir_read(&lfs, &dir, &info) => 0; -# assert(strcmp(info.name, "..") == 0); -# assert(info.type == LFS_TYPE_DIR); -# for (lfs_size_t i = 0; i < N; i++) { -# char name[256]; -# sprintf(name, "dir%04d", i); -# lfsr_dir_read(&lfs, &dir, &info) => 0; -# assert(strcmp(info.name, name) == 0); -# assert(info.type == LFS_TYPE_DIR); -# -# char path[1024]; -# sprintf(path, "%s/%s", (PARENT ? "pricklypear" : ""), info.name); -# lfsr_remove(&lfs, path) => 0; -# } -# lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT; -# lfsr_dir_close(&lfs, &dir) => 0; -# -# // check that our removes worked -# for (lfs_size_t i = 0; i < N; i++) { -# char name[256]; -# sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i); -# struct lfs_info info; -# lfsr_stat(&lfs, name, &info) => LFS_ERR_NOENT; -# } -# -# lfsr_dir_open(&lfs, &dir, "/") => 0; -# lfsr_dir_read(&lfs, &dir, &info) => 0; -# assert(strcmp(info.name, ".") == 0); -# assert(info.type == LFS_TYPE_DIR); -# lfsr_dir_read(&lfs, &dir, &info) => 0; -# assert(strcmp(info.name, "..") == 0); -# assert(info.type == LFS_TYPE_DIR); -# lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT; -# lfsr_dir_close(&lfs, &dir) => 0; -# -# lfsr_unmount(&lfs) => 0; -#''' +# This is a useful feature, but it's unintuitive that this should have +# well-defined behavior, so make sure to test for it +[cases.t5_dirs_rm_many_recursive] +defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512] +defines.PARENT = [false, true] +# this test sort of fights against itself when powerloss testing, +# limit it to a _very_ small number of entries for this reason +if = '!TEST_PL || N <= 32' +reentrant = true +code = ''' + // format once per test + lfs_t lfs; + int err = lfsr_mount(&lfs, cfg); + if (err) { + lfsr_format(&lfs, cfg) => 0; + lfsr_mount(&lfs, cfg) => 0; + } + + if (PARENT) { + err = lfsr_mkdir(&lfs, "pricklypear"); + assert(!err || (TEST_PL && err == LFS_ERR_EXIST)); + } + + // make this many directories + for (lfs_size_t i = 0; i < N; i++) { + char name[256]; + sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i); + err = lfsr_mkdir(&lfs, name); + assert(!err || (TEST_PL && err == LFS_ERR_EXIST)); + } + + // check that our mkdir worked + for (lfs_size_t i = 0; i < N; i++) { + char name[256]; + sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i); + struct lfs_info info; + lfsr_stat(&lfs, name, &info) => 0; + char name2[256]; + sprintf(name2, "dir%04d", i); + assert(strcmp(info.name, name2) == 0); + assert(info.type == LFS_TYPE_DIR); + } + + lfsr_dir_t dir; + lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0; + struct lfs_info info; + lfsr_dir_read(&lfs, &dir, &info) => 0; + assert(strcmp(info.name, ".") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_dir_read(&lfs, &dir, &info) => 0; + assert(strcmp(info.name, "..") == 0); + assert(info.type == LFS_TYPE_DIR); + for (lfs_size_t i = 0; i < N; i++) { + char name[256]; + sprintf(name, "dir%04d", i); + lfsr_dir_read(&lfs, &dir, &info) => 0; + assert(strcmp(info.name, name) == 0); + assert(info.type == LFS_TYPE_DIR); + } + lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT; + lfsr_dir_close(&lfs, &dir) => 0; + + // now remove directories recursively + lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0; + lfsr_dir_read(&lfs, &dir, &info) => 0; + assert(strcmp(info.name, ".") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_dir_read(&lfs, &dir, &info) => 0; + assert(strcmp(info.name, "..") == 0); + assert(info.type == LFS_TYPE_DIR); + for (lfs_size_t i = 0; i < N; i++) { + char name[256]; + sprintf(name, "dir%04d", i); + lfsr_dir_read(&lfs, &dir, &info) => 0; + assert(strcmp(info.name, name) == 0); + assert(info.type == LFS_TYPE_DIR); + + char path[1024]; + sprintf(path, "%s/%s", (PARENT ? "pricklypear" : ""), info.name); + lfsr_remove(&lfs, path) => 0; + } + lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT; + lfsr_dir_close(&lfs, &dir) => 0; + + // check that our removes worked + for (lfs_size_t i = 0; i < N; i++) { + char name[256]; + sprintf(name, "%s/dir%04d", (PARENT ? "pricklypear" : ""), i); + struct lfs_info info; + lfsr_stat(&lfs, name, &info) => LFS_ERR_NOENT; + } + + lfsr_dir_open(&lfs, &dir, (PARENT ? "pricklypear" : "/")) => 0; + lfsr_dir_read(&lfs, &dir, &info) => 0; + assert(strcmp(info.name, ".") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_dir_read(&lfs, &dir, &info) => 0; + assert(strcmp(info.name, "..") == 0); + assert(info.type == LFS_TYPE_DIR); + lfsr_dir_read(&lfs, &dir, &info) => LFS_ERR_NOENT; + lfsr_dir_close(&lfs, &dir) => 0; + + lfsr_unmount(&lfs) => 0; +''' [cases.t5_dirs_rm_fuzz] defines.N = [1, 2, 4, 8, 16, 32, 64, 128, 256, 512]