From 64df0a5e2092a86745def995b44298881a864b93 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Tue, 31 Jul 2018 08:07:36 -0500 Subject: [PATCH] Added orphan bit to xored-globals Unfortunately for us, even with the new ability to store global state, orphans can not be handled as gracefully as moves. This is due to the fact that directory operations can create an unbounded number of orphans. It's usually small, the fact that it's unbounded means we can't store the orphan info in xored-globals. However, one thing we can do to leverage the xored-global state is store a bit indicating if _any_ orphans are present. This means in the common case we can completely avoid the deorphan step, while only using a single bit of the global state, which is effectively free since we can store it in the globals tag itself. If a littlefs drive does not want to consider the orphan bit, it's free to use the previous behaviour of always checking for orphans on first write. --- lfs.c | 365 +++++++++++++++++++++++++++++++++------------------------- lfs.h | 29 ++--- 2 files changed, 221 insertions(+), 173 deletions(-) diff --git a/lfs.c b/lfs.c index cbafda0..25c9a57 100644 --- a/lfs.c +++ b/lfs.c @@ -267,7 +267,7 @@ static int lfs_relocate(lfs_t *lfs, const lfs_block_t oldpair[2], const lfs_block_t newpair[2]); int lfs_scan(lfs_t *lfs); int lfs_fixmove(lfs_t *lfs); -int lfs_deorphan(lfs_t *lfs); +int lfs_forceconsistency(lfs_t *lfs); /// Block allocator /// @@ -456,15 +456,68 @@ static inline lfs_size_t lfs_tagsize(uint32_t tag) { return tag & 0x00000fff; } -// operations on globals -static void lfs_globalsxor(lfs_globals_t *a, const lfs_globals_t *b) { - a->move.pair[0] ^= b->move.pair[0]; - a->move.pair[1] ^= b->move.pair[1]; - a->move.id ^= b->move.id; +// operations on set of globals +static inline void lfs_globalxor(lfs_global_t *a, const lfs_global_t *b) { + for (int i = 0; i < sizeof(lfs_global_t)/2; i++) { + a->u16[i] ^= b->u16[i]; + } } -static bool lfs_globalsiszero(const lfs_globals_t *a) { - return (a->move.pair[0] == 0 && a->move.pair[1] == 0 && a->move.id == 0); +static inline bool lfs_globaliszero(const lfs_global_t *a) { + for (int i = 0; i < sizeof(lfs_global_t)/2; i++) { + if (a->u16[i] != 0) { + return false; + } + } + return true; +} + +static inline void lfs_globalzero(lfs_global_t *a) { + memset(a->u16, 0x00, sizeof(lfs_global_t)); +} + +static inline void lfs_globalones(lfs_global_t *a) { + memset(a->u16, 0xff, sizeof(lfs_global_t)); +} + +static inline void lfs_globalxormove(lfs_global_t *a, + const lfs_block_t pair[2], uint16_t id) { + a->u16[0] ^= id; + for (int i = 0; i < sizeof(lfs_block_t[2])/2; i++) { + a->u16[1+i] ^= ((uint16_t*)pair)[i]; + } +} + +static inline void lfs_globalxordeorphaned(lfs_global_t *a, bool deorphaned) { + a->u16[0] ^= deorphaned << 15; +} + +static inline const lfs_block_t *lfs_globalmovepair(const lfs_t *lfs) { + return (const lfs_block_t*)&lfs->globals.u16[1]; +} + +static inline uint16_t lfs_globalmoveid(const lfs_t *lfs) { + return 0x3ff & lfs->globals.u16[0]; +} + +static inline bool lfs_globalisdeorphaned(const lfs_t *lfs) { + return 0x8000 & lfs->globals.u16[0]; +} + +static inline void lfs_globalmove(lfs_t *lfs, + const lfs_block_t pair[2], uint16_t id) { + lfs_global_t diff; + lfs_globalzero(&diff); + lfs_globalxormove(&diff, lfs_globalmovepair(lfs), lfs_globalmoveid(lfs)); + lfs_globalxormove(&diff, pair, id); + lfs_globalxor(&lfs->locals, &diff); + lfs_globalxor(&lfs->globals, &diff); +} + +static inline void lfs_globaldeorphaned(lfs_t *lfs, bool deorphaned) { + deorphaned ^= lfs_globalisdeorphaned(lfs); + lfs_globalxordeorphaned(&lfs->locals, deorphaned); + lfs_globalxordeorphaned(&lfs->globals, deorphaned); } @@ -670,15 +723,15 @@ static int lfs_commitmove(lfs_t *lfs, struct lfs_commit *commit, } static int lfs_commitglobals(lfs_t *lfs, struct lfs_commit *commit, - lfs_globals_t *locals) { - if (lfs_globalsiszero(&lfs->diff)) { + lfs_global_t *locals) { + if (lfs_globaliszero(&lfs->locals)) { return 0; } - lfs_globalsxor(locals, &lfs->diff); + lfs_globalxor(locals, &lfs->locals); int err = lfs_commitattr(lfs, commit, - LFS_MKTAG(LFS_TYPE_GLOBALS, 0x3ff, sizeof(*locals)), locals); - lfs_globalsxor(locals, &lfs->diff); + LFS_MKTAG(LFS_TYPE_GLOBALS, 0x3ff, sizeof(lfs_global_t)), locals); + lfs_globalxor(locals, &lfs->locals); return err; } @@ -759,7 +812,7 @@ static int lfs_dir_alloc(lfs_t *lfs, lfs_mdir_t *dir, dir->tail[1] = tail[1]; dir->erased = false; dir->split = split; - dir->locals = (lfs_globals_t){{{0}}}; + lfs_globalzero(&dir->locals); // don't write out yet, let caller take care of that return 0; @@ -774,8 +827,8 @@ static int lfs_dir_compact(lfs_t *lfs, // There's nothing special about our global delta, so feed it back // into the global global delta - lfs_globalsxor(&lfs->diff, &dir->locals); - dir->locals = (lfs_globals_t){{{0}}}; + lfs_globalxor(&lfs->locals, &dir->locals); + lfs_globalzero(&dir->locals); // increment revision count dir->rev += 1; @@ -933,8 +986,8 @@ relocate: if (!relocated) { // successful commit, update globals - lfs_globalsxor(&dir->locals, &lfs->diff); - lfs->diff = (lfs_globals_t){{{0}}}; + lfs_globalxor(&dir->locals, &lfs->locals); + lfs_globalzero(&lfs->locals); } else { // update references if we relocated LFS_DEBUG("Relocating %d %d to %d %d", @@ -962,18 +1015,21 @@ relocate: static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir, const lfs_mattr_t *attrs) { - bool canceling = (lfs_paircmp(dir->pair, lfs->globals.move.pair) == 0); - lfs_mattr_t cancel; - if (canceling) { + lfs_mattr_t cancelattr; + lfs_global_t canceldiff; + lfs_globalzero(&canceldiff); + if (lfs_paircmp(dir->pair, lfs_globalmovepair(lfs)) == 0) { // Wait, we have the move? Just cancel this out here // We need to, or else the move can become outdated - lfs->diff.move.pair[0] ^= 0xffffffff ^ lfs->globals.move.pair[0]; - lfs->diff.move.pair[1] ^= 0xffffffff ^ lfs->globals.move.pair[1]; - lfs->diff.move.id ^= 0x3ff ^ lfs->globals.move.id; + lfs_globalxormove(&canceldiff, + lfs_globalmovepair(lfs), lfs_globalmoveid(lfs)); + lfs_globalxormove(&canceldiff, + (lfs_block_t[2]){0xffffffff, 0xffffffff}, 0x3ff); + lfs_globalxor(&lfs->locals, &canceldiff); - cancel.tag = LFS_MKTAG(LFS_TYPE_DELETE, lfs->globals.move.id, 0); - cancel.next = attrs; - attrs = &cancel; + cancelattr.tag = LFS_MKTAG(LFS_TYPE_DELETE, lfs_globalmoveid(lfs), 0); + cancelattr.next = attrs; + attrs = &cancelattr; } // calculate new directory size @@ -1001,7 +1057,7 @@ static int lfs_dir_commit(lfs_t *lfs, lfs_mdir_t *dir, pdir.split = dir->split; pdir.tail[0] = dir->tail[0]; pdir.tail[1] = dir->tail[1]; - lfs_globalsxor(&lfs->diff, &dir->locals); + lfs_globalxor(&lfs->locals, &dir->locals); return lfs_dir_commit(lfs, &pdir, LFS_MKATTR(LFS_TYPE_TAIL + pdir.split, 0x3ff, pdir.tail, sizeof(pdir.tail), @@ -1074,16 +1130,12 @@ compact: dir->off = commit.off; dir->etag = commit.ptag; // successful commit, update globals - lfs_globalsxor(&dir->locals, &lfs->diff); - lfs->diff = (lfs_globals_t){{{0}}}; + lfs_globalxor(&dir->locals, &lfs->locals); + lfs_globalzero(&lfs->locals); } // update globals that are affected - if (canceling) { - lfs->globals.move.pair[0] = 0xffffffff; - lfs->globals.move.pair[1] = 0xffffffff; - lfs->globals.move.id = 0x3ff; - } + lfs_globalxor(&lfs->globals, &canceldiff); // update any directories that are affected for (lfs_dir_t *d = lfs->dirs; d; d = d->next) { @@ -1147,7 +1199,8 @@ static int32_t lfs_dir_find(lfs_t *lfs, uint16_t tempcount = 0; lfs_block_t temptail[2] = {0xffffffff, 0xffffffff}; bool tempsplit = false; - lfs_globals_t templocals = (lfs_globals_t){{{0}}}; + lfs_global_t templocals; + lfs_globalzero(&templocals); while (true) { // extract next tag @@ -1252,11 +1305,11 @@ static int32_t lfs_dir_find(lfs_t *lfs, // consider what we have good enough if (dir->off > 0) { // synthetic move - if (lfs_paircmp(dir->pair, lfs->globals.move.pair) == 0) { - if (lfs->globals.move.id == lfs_tagid(foundtag)) { + if (lfs_paircmp(dir->pair, lfs_globalmovepair(lfs)) == 0) { + if (lfs_globalmoveid(lfs) == lfs_tagid(foundtag)) { foundtag = LFS_ERR_NOENT; } else if (lfs_tagisvalid(foundtag) && - lfs->globals.move.id < lfs_tagid(foundtag)) { + lfs_globalmoveid(lfs) < lfs_tagid(foundtag)) { foundtag -= LFS_MKTAG(0, 1, 0); } } @@ -1286,8 +1339,8 @@ static int lfs_dir_fetch(lfs_t *lfs, static int32_t lfs_dir_get(lfs_t *lfs, lfs_mdir_t *dir, uint32_t getmask, uint32_t gettag, void *buffer) { int32_t getdiff = 0; - if (lfs_paircmp(dir->pair, lfs->globals.move.pair) == 0 && - lfs_tagid(gettag) <= lfs->globals.move.id) { + if (lfs_paircmp(dir->pair, lfs_globalmovepair(lfs)) == 0 && + lfs_tagid(gettag) <= lfs_globalmoveid(lfs)) { // synthetic moves getdiff = LFS_MKTAG(0, 1, 0); } @@ -1422,11 +1475,9 @@ static int lfs_dir_getinfo(lfs_t *lfs, lfs_mdir_t *dir, /// Top level directory operations /// int lfs_mkdir(lfs_t *lfs, const char *path) { // deorphan if we haven't yet, needed at most once after poweron - if (!lfs->deorphaned) { - int err = lfs_deorphan(lfs); - if (err) { - return err; - } + int err = lfs_forceconsistency(lfs); + if (err) { + return err; } lfs_mdir_t cwd; @@ -1445,7 +1496,7 @@ int lfs_mkdir(lfs_t *lfs, const char *path) { lfs_alloc_ack(lfs); lfs_mdir_t dir; - int err = lfs_dir_alloc(lfs, &dir, false, cwd.tail); + err = lfs_dir_alloc(lfs, &dir, false, cwd.tail); if (err) { return err; } @@ -1817,8 +1868,8 @@ int lfs_file_opencfg(lfs_t *lfs, lfs_file_t *file, const char *path, int flags, const struct lfs_file_config *cfg) { // deorphan if we haven't yet, needed at most once after poweron - if ((flags & 3) != LFS_O_RDONLY && !lfs->deorphaned) { - int err = lfs_deorphan(lfs); + if ((flags & 3) != LFS_O_RDONLY) { + int err = lfs_forceconsistency(lfs); if (err) { return err; } @@ -2543,15 +2594,13 @@ int lfs_stat(lfs_t *lfs, const char *path, struct lfs_info *info) { int lfs_remove(lfs_t *lfs, const char *path) { // deorphan if we haven't yet, needed at most once after poweron - if (!lfs->deorphaned) { - int err = lfs_deorphan(lfs); - if (err) { - return err; - } + int err = lfs_forceconsistency(lfs); + if (err) { + return err; } lfs_mdir_t cwd; - int err = lfs_dir_fetch(lfs, &cwd, lfs->root); + err = lfs_dir_fetch(lfs, &cwd, lfs->root); if (err) { return err; } @@ -2580,6 +2629,9 @@ int lfs_remove(lfs_t *lfs, const char *path) { if (dir.count > 0 || dir.split) { return LFS_ERR_NOTEMPTY; } + + // mark fs as orphaned + lfs_globaldeorphaned(lfs, false); } // delete the entry @@ -2596,11 +2648,14 @@ int lfs_remove(lfs_t *lfs, const char *path) { return err; } + // fix orphan + lfs_globaldeorphaned(lfs, true); + // steal state // TODO test for global state stealing? cwd.tail[0] = dir.tail[0]; cwd.tail[1] = dir.tail[1]; - lfs_globalsxor(&lfs->diff, &dir.locals); + lfs_globalxor(&lfs->locals, &dir.locals); err = lfs_dir_commit(lfs, &cwd, LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x3ff, cwd.tail, sizeof(cwd.tail), @@ -2615,11 +2670,9 @@ int lfs_remove(lfs_t *lfs, const char *path) { int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { // deorphan if we haven't yet, needed at most once after poweron - if (!lfs->deorphaned) { - int err = lfs_deorphan(lfs); - if (err) { - return err; - } + int err = lfs_forceconsistency(lfs); + if (err) { + return err; } // find old entry @@ -2665,6 +2718,9 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { if (prevdir.count > 0 || prevdir.split) { return LFS_ERR_NOTEMPTY; } + + // mark fs as orphaned + lfs_globaldeorphaned(lfs, false); } } else { // check that name fits @@ -2678,15 +2734,10 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { } // create move to fix later - lfs->diff.move.pair[0] = oldcwd.pair[0] ^ lfs->globals.move.pair[0]; - lfs->diff.move.pair[1] = oldcwd.pair[1] ^ lfs->globals.move.pair[1]; - lfs->diff.move.id = lfs_tagid(oldtag) ^ lfs->globals.move.id; - lfs->globals.move.pair[0] = oldcwd.pair[0]; - lfs->globals.move.pair[1] = oldcwd.pair[1]; - lfs->globals.move.id = lfs_tagid(oldtag); + lfs_globalmove(lfs, oldcwd.pair, lfs_tagid(oldtag)); // move over all attributes - int err = lfs_dir_commit(lfs, &newcwd, + err = lfs_dir_commit(lfs, &newcwd, LFS_MKATTR(lfs_tagtype(oldtag), newid, newpath, strlen(newpath), LFS_MKATTR(LFS_FROM_MOVE, newid, &oldcwd, lfs_tagid(oldtag), NULL))); @@ -2709,11 +2760,14 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { return err; } + // fix orphan + lfs_globaldeorphaned(lfs, true); + // steal state // TODO test for global state stealing? newcwd.tail[0] = prevdir.tail[0]; newcwd.tail[1] = prevdir.tail[1]; - lfs_globalsxor(&lfs->diff, &prevdir.locals); + lfs_globalxor(&lfs->locals, &prevdir.locals); err = lfs_dir_commit(lfs, &newcwd, LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x3ff, newcwd.tail, sizeof(newcwd.tail), @@ -2743,7 +2797,7 @@ int lfs_rename(lfs_t *lfs, const char *oldpath, const char *newpath) { // // if we were a directory, find pred, replace tail // // TODO can this just deorphan? // if (prevexists && lfs_tagsubtype(prevattr.tag) == LFS_TYPE_DIR) { -// err = lfs_deorphan(lfs); +// err = lfs_forceconsistency(lfs); // if (err) { // return err; // } @@ -2936,10 +2990,7 @@ static int lfs_init(lfs_t *lfs, const struct lfs_config *cfg) { lfs->root[1] = 0xffffffff; lfs->files = NULL; lfs->dirs = NULL; - lfs->deorphaned = false; - lfs->globals.move.pair[0] = 0xffffffff; - lfs->globals.move.pair[1] = 0xffffffff; - lfs->globals.move.id = 0x3ff; + lfs_globalones(&lfs->globals); // scan for any global updates // TODO rm me? need to grab any inits @@ -3348,7 +3399,7 @@ static int lfs_relocate(lfs_t *lfs, } // clean up bad block, which should now be a desync - return lfs_deorphan(lfs); + return lfs_forceconsistency(lfs); } // find pred @@ -3380,7 +3431,7 @@ int lfs_scan(lfs_t *lfs) { } lfs_mdir_t dir = {.tail = {0, 1}}; - lfs->diff = (lfs_globals_t){{{0}}}; + lfs_globalzero(&lfs->locals); // iterate over all directory directory entries while (!lfs_pairisnull(dir.tail)) { @@ -3390,40 +3441,105 @@ int lfs_scan(lfs_t *lfs) { } // xor together indirect deletes - lfs_globalsxor(&lfs->diff, &dir.locals); + lfs_globalxor(&lfs->locals, &dir.locals); } // update littlefs with globals // TODO does this only run once? // TODO Should we inline this into init?? - lfs_globalsxor(&lfs->globals, &lfs->diff); - lfs->diff = (lfs_globals_t){{{0}}}; - if (!lfs_pairisnull(lfs->globals.move.pair)) { + lfs_globalxor(&lfs->globals, &lfs->locals); + lfs_globalzero(&lfs->locals); + if (!lfs_pairisnull(lfs_globalmovepair(lfs))) { LFS_DEBUG("Found move %d %d %d", - lfs->globals.move.pair[0], - lfs->globals.move.pair[1], - lfs->globals.move.id); + lfs_globalmovepair(lfs)[0], + lfs_globalmovepair(lfs)[1], + lfs_globalmoveid(lfs)); } return 0; } -int lfs_deorphan(lfs_t *lfs) { - lfs->deorphaned = true; - if (lfs_pairisnull(lfs->root)) { // TODO rm me? - return 0; +int lfs_forceconsistency(lfs_t *lfs) { + if (!lfs_globalisdeorphaned(lfs)) { + // Fix any orphans + lfs_mdir_t pdir = {.split = true}; + lfs_mdir_t dir = {.tail = {0, 1}}; + + // iterate over all directory directory entries + while (!lfs_pairisnull(dir.tail)) { + int err = lfs_dir_fetch(lfs, &dir, dir.tail); + if (err) { + return err; + } + + // check head blocks for orphans + if (!pdir.split) { + // check if we have a parent + lfs_mdir_t parent; + int32_t tag = lfs_parent(lfs, pdir.tail, &parent); + if (tag < 0 && tag != LFS_ERR_NOENT) { + return tag; + } + + if (tag == LFS_ERR_NOENT) { + // we are an orphan + LFS_DEBUG("Found orphan %d %d", + pdir.tail[0], pdir.tail[1]); + + pdir.tail[0] = dir.tail[0]; + pdir.tail[1] = dir.tail[1]; + err = lfs_dir_commit(lfs, &pdir, + LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x3ff, + pdir.tail, sizeof(pdir.tail), + NULL)); + if (err) { + return err; + } + + break; + } + + lfs_block_t pair[2]; + int32_t res = lfs_dir_get(lfs, &parent, 0x7ffff000, tag, pair); + if (res < 0) { + return res; + } + + if (!lfs_pairsync(pair, pdir.tail)) { + // we have desynced + LFS_DEBUG("Found half-orphan %d %d", pair[0], pair[1]); + + pdir.tail[0] = pair[0]; + pdir.tail[1] = pair[1]; + err = lfs_dir_commit(lfs, &pdir, + LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x3ff, + pdir.tail, sizeof(pdir.tail), + NULL)); + if (err) { + return err; + } + + break; + } + } + + memcpy(&pdir, &dir, sizeof(pdir)); + } + + // mark orphan as fixed + lfs_globaldeorphaned(lfs, false); } - // Fix bad moves - if (!lfs_pairisnull(lfs->globals.move.pair)) { + if (lfs_globalmoveid(lfs) != 0x3ff) { + // Fix bad moves LFS_DEBUG("Fixing move %d %d %d", // TODO move to just deorphan? - lfs->globals.move.pair[0], - lfs->globals.move.pair[1], - lfs->globals.move.id); + lfs_globalmovepair(lfs)[0], + lfs_globalmovepair(lfs)[1], + lfs_globalmoveid(lfs)); // fetch and delete the moved entry lfs_mdir_t movedir; - int err = lfs_dir_fetch(lfs, &movedir, lfs->globals.move.pair); + int err = lfs_dir_fetch(lfs, &movedir, lfs_globalmovepair(lfs)); if (err) { return err; } @@ -3435,69 +3551,6 @@ int lfs_deorphan(lfs_t *lfs) { } } - lfs_mdir_t pdir = {.split = true}; - lfs_mdir_t dir = {.tail = {0, 1}}; - - // iterate over all directory directory entries - while (!lfs_pairisnull(dir.tail)) { - int err = lfs_dir_fetch(lfs, &dir, dir.tail); - if (err) { - return err; - } - - // check head blocks for orphans - if (!pdir.split) { - // check if we have a parent - lfs_mdir_t parent; - int32_t tag = lfs_parent(lfs, pdir.tail, &parent); - if (tag < 0 && tag != LFS_ERR_NOENT) { - return tag; - } - - if (tag == LFS_ERR_NOENT) { - // we are an orphan - LFS_DEBUG("Found orphan %d %d", pdir.tail[0], pdir.tail[1]); - - pdir.tail[0] = dir.tail[0]; - pdir.tail[1] = dir.tail[1]; - err = lfs_dir_commit(lfs, &pdir, - LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x3ff, - pdir.tail, sizeof(pdir.tail), - NULL)); - if (err) { - return err; - } - - break; - } - - lfs_block_t pair[2]; - int32_t res = lfs_dir_get(lfs, &parent, 0x7ffff000, tag, pair); - if (res < 0) { - return res; - } - - if (!lfs_pairsync(pair, pdir.tail)) { - // we have desynced - LFS_DEBUG("Found half-orphan %d %d", pair[0], pair[1]); - - pdir.tail[0] = pair[0]; - pdir.tail[1] = pair[1]; - err = lfs_dir_commit(lfs, &pdir, - LFS_MKATTR(LFS_TYPE_SOFTTAIL, 0x3ff, - pdir.tail, sizeof(pdir.tail), - NULL)); - if (err) { - return err; - } - - break; - } - } - - memcpy(&pdir, &dir, sizeof(pdir)); - } - return 0; } diff --git a/lfs.h b/lfs.h index 62d170d..092161e 100644 --- a/lfs.h +++ b/lfs.h @@ -110,7 +110,7 @@ enum lfs_type { LFS_TYPE_TAIL = 0x0c0, LFS_TYPE_SOFTTAIL = 0x0c0, LFS_TYPE_HARDTAIL = 0x0c1, - LFS_TYPE_CRC = 0x0ff, + LFS_TYPE_CRC = 0x0ff, // TODO are trailing ones useful? LFS_TYPE_INLINESTRUCT = 0x040, LFS_TYPE_CTZSTRUCT = 0x041, @@ -280,12 +280,9 @@ typedef struct lfs_mattr { const struct lfs_mattr *next; } lfs_mattr_t; -typedef struct lfs_globals { - struct lfs_move { - lfs_block_t pair[2]; - uint16_t id; - } move; -} lfs_globals_t; +typedef union lfs_global { + uint16_t u16[5]; +} lfs_global_t; typedef struct lfs_mdir { lfs_block_t pair[2]; @@ -296,7 +293,7 @@ typedef struct lfs_mdir { uint16_t count; bool erased; bool split; - lfs_globals_t locals; + lfs_global_t locals; } lfs_mdir_t; typedef struct lfs_cache { @@ -314,12 +311,13 @@ typedef struct lfs_file { lfs_size_t size; } ctz; - const struct lfs_file_config *cfg; uint32_t flags; lfs_off_t pos; lfs_block_t block; lfs_off_t off; lfs_cache_t cache; + + const struct lfs_file_config *cfg; } lfs_file_t; typedef struct lfs_dir { @@ -353,21 +351,18 @@ typedef struct lfs_free { // The littlefs type typedef struct lfs { - const struct lfs_config *cfg; + lfs_cache_t rcache; + lfs_cache_t pcache; lfs_block_t root[2]; lfs_file_t *files; lfs_dir_t *dirs; - lfs_cache_t rcache; - lfs_cache_t pcache; - + lfs_global_t globals; + lfs_global_t locals; lfs_free_t free; - bool deorphaned; - lfs_globals_t globals2; - lfs_globals_t globals; - lfs_globals_t diff; + const struct lfs_config *cfg; lfs_size_t inline_size; lfs_size_t attr_size; lfs_size_t name_size;