From 0893c1f6be31db04241798578c4148c20af3b3f7 Mon Sep 17 00:00:00 2001 From: Christopher Haster Date: Thu, 25 Jul 2024 14:05:04 -0500 Subject: [PATCH] Increased internal flags 16 bits -> 32 bits If we add CKMETA/CKDATA and eventually REPAIRMETA/REPAIRDATA to the file open flags, we'll end up with 17 flags total (13 user-facing, 4 internal), which is a bit (heh) too much for a 16-bit flags field! There are a few ways to solve this, dropping features for one, instead I've decided to expand the fields flag to 32-bits. Fortunately this was already the field size for all user-facing fields. To avoid a RAM increase, I've also shoved the opened-file types and traversal tstates into the same field. We have various flags in quite a few places now, here's how everything fits together: 8 8 8 8 .----++----++----++----. .----..---..--..-------. o_flags: |type|| f ||t || o | |----||---|:--:'-------' |----||---|:--:--------. d_flags: |type|| f |: : | |----||---|:--:--------' |----||---|:--'--..----. t_flags: |type|| f || t ||tstt| '----''---'|-----|'----' .----------|-----|-----. gc_flags: | | t | | '----------|-----|-----' .-----.---.|-----|.----. m_flags: | | m || t || m | '-----|---|'-----'|----| .----.|---|-------|----| i_flags: | i || m | | m | '----''---'-------'----' Unfortunately, using the full 32-bit flag space highlights that C99's enum types are kind of garbage... In C99 enums are strictly signed ints, which means attempting to use them for 32-bit bit fields overflows. There is no way around this so I've switched our flag definitions to #defines. I've kept types as enums for now but I'm keeping my eye on them... --- The tradeoff of merging the type/btype/tstate/flags fields is that it takes more code to extract/encode the various subfields. Since these fields our heavily used in our codebase, this really adds up: code stack before: 35888 2696 after: 36048 (+0.4%) 2696 (+0.0%) At least in theory the type fields can be optimized to a byte load, but not btype/tstate. Also accessing bits in higher positions may be adding cost. --- lfs.c | 412 +++++++++++++++++++++++------------------- lfs.h | 162 ++++++++--------- tests/test_mtree.toml | 40 ++-- 3 files changed, 318 insertions(+), 296 deletions(-) diff --git a/lfs.c b/lfs.c index 68305e21..6d3efaa3 100644 --- a/lfs.c +++ b/lfs.c @@ -5161,7 +5161,7 @@ static inline int lfsr_sprout_cmp( } // needed in lfsr_sprout_estimate -static inline bool lfsr_omdir_isbshrub(const lfsr_omdir_t *o); +static inline bool lfsr_f_isbshrub(uint32_t flags); // these are used in mdir compaction static lfs_ssize_t lfsr_sprout_estimate(lfs_t *lfs, @@ -5169,7 +5169,7 @@ static lfs_ssize_t lfsr_sprout_estimate(lfs_t *lfs, // only include the last reference const lfsr_sprout_t *last = NULL; for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { - if (lfsr_omdir_isbshrub(o) + if (lfsr_f_isbshrub(o->flags) && lfsr_bshrub_isbsprout(&o->mdir, &((lfsr_obshrub_t*)o)->bshrub) && lfsr_sprout_cmp( @@ -5200,7 +5200,7 @@ static int lfsr_sprout_compact(lfs_t *lfs, const lfsr_rbyd_t *rbyd_, // stage any opened inlined files with their new location so we // can update these later if our commit is a success for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { - if (lfsr_omdir_isbshrub(o) + if (lfsr_f_isbshrub(o->flags) && lfsr_bshrub_isbsprout(&o->mdir, &((lfsr_obshrub_t*)o)->bshrub) && lfsr_sprout_cmp( @@ -5317,7 +5317,7 @@ static lfs_ssize_t lfsr_shrub_estimate(lfs_t *lfs, // only include the last reference const lfsr_shrub_t *last = NULL; for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { - if (lfsr_omdir_isbshrub(o) + if (lfsr_f_isbshrub(o->flags) && lfsr_bshrub_isbshrub(&o->mdir, &((lfsr_obshrub_t*)o)->bshrub) && lfsr_shrub_cmp( @@ -5351,7 +5351,7 @@ static int lfsr_shrub_compact(lfs_t *lfs, lfsr_rbyd_t *rbyd_, // // this should include our current bshrub for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { - if (lfsr_omdir_isbshrub(o) + if (lfsr_f_isbshrub(o->flags) && lfsr_bshrub_isbshrub(&o->mdir, &((lfsr_obshrub_t*)o)->bshrub) && lfsr_shrub_cmp( @@ -5458,7 +5458,7 @@ static lfs_ssize_t lfsr_bshrub_estimate(lfs_t *lfs, // this includes our current shrub for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { - if (lfsr_omdir_isbshrub(o) + if (lfsr_f_isbshrub(o->flags) && o->mdir.mid == mdir->mid) { if (lfsr_bshrub_isbsprout(&o->mdir, &((lfsr_obshrub_t*)o)->bshrub)) { @@ -5648,7 +5648,7 @@ static int lfsr_bshrub_commit_(lfs_t *lfs, // as unerased if (lfsr_bshrub_isbtree(mdir, bshrub)) { for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { - if (lfsr_omdir_isbshrub(o) + if (lfsr_f_isbshrub(o->flags) && &((lfsr_obshrub_t*)o)->bshrub != bshrub && lfsr_bshrub_isbshruborbtree( &((lfsr_obshrub_t*)o)->bshrub) @@ -5737,7 +5737,7 @@ static int lfsr_bshrub_commit_(lfs_t *lfs, // update _all_ shrubs with the new estimate for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { - if (lfsr_omdir_isbshrub(o) + if (lfsr_f_isbshrub(o->flags) && o->mdir.mid == mdir->mid && lfsr_bshrub_isbshrub(&o->mdir, &((lfsr_obshrub_t*)o)->bshrub)) { @@ -5889,6 +5889,129 @@ static int lfsr_data_readmptr(lfs_t *lfs, lfsr_data_t *data, /// various flag things /// +// open flags +static inline bool lfsr_o_isrdonly(uint32_t flags) { + return (flags & 3) == LFS_O_RDONLY; +} + +static inline bool lfsr_o_iswronly(uint32_t flags) { + return (flags & 3) == LFS_O_WRONLY; +} + +static inline bool lfsr_o_iscreat(uint32_t flags) { + return flags & LFS_O_CREAT; +} + +static inline bool lfsr_o_isexcl(uint32_t flags) { + return flags & LFS_O_EXCL; +} + +static inline bool lfsr_o_istrunc(uint32_t flags) { + return flags & LFS_O_TRUNC; +} + +static inline bool lfsr_o_isappend(uint32_t flags) { + return flags & LFS_O_APPEND; +} + +static inline bool lfsr_o_isflush(uint32_t flags) { + return flags & LFS_O_FLUSH; +} + +static inline bool lfsr_o_issync(uint32_t flags) { + return flags & LFS_O_SYNC; +} + +static inline bool lfsr_o_isdesync(uint32_t flags) { + return flags & LFS_O_DESYNC; +} + +// internal open flags +static inline uint8_t lfsr_f_type(uint32_t flags) { + return flags >> 24; +} + +static inline uint32_t lfsr_f_settype(uint32_t flags, uint8_t type) { + return (flags & ~0xff000000) | ((uint32_t)type << 24); +} + +static inline bool lfsr_f_isbshrub(uint32_t flags) { + // it turns out that bshrub types share a bit + return flags & 0x01000000; +} + +static inline bool lfsr_f_isunflush(uint32_t flags) { + return flags & LFS_F_UNFLUSH; +} + +static inline bool lfsr_f_isunsync(uint32_t flags) { + return flags & LFS_F_UNSYNC; +} + +static inline bool lfsr_f_isorphan(uint32_t flags) { + return flags & LFS_F_ORPHAN; +} + +static inline bool lfsr_f_iszombie(uint32_t flags) { + return flags & LFS_F_ZOMBIE; +} + +// traversal flags +static inline bool lfsr_t_ismtreeonly(uint32_t flags) { + return flags & LFS_T_MTREEONLY; +} + +static inline bool lfsr_t_ismkconsistent(uint32_t flags) { + return flags & LFS_T_MKCONSISTENT; +} + +static inline bool lfsr_t_islookahead(uint32_t flags) { + return flags & LFS_T_LOOKAHEAD; +} + +static inline bool lfsr_t_iscompact(uint32_t flags) { + return flags & LFS_T_COMPACT; +} + +static inline bool lfsr_t_isckmeta(uint32_t flags) { + return flags & LFS_T_CKMETA; +} + +static inline bool lfsr_t_isckdata(uint32_t flags) { + return flags & LFS_T_CKDATA; +} + +// internal traversal flags +static inline uint8_t lfsr_f_tstate(uint32_t flags) { + return (flags >> 0) & 0xf; +} + +static inline uint32_t lfsr_f_settstate(uint32_t flags, uint8_t tstate) { + return (flags & ~0x0000000f) | (tstate << 0); +} + +static inline uint8_t lfsr_f_btype(uint32_t flags) { + return (flags >> 4) & 0xf; +} + +static inline uint32_t lfsr_f_setbtype(uint32_t flags, uint8_t btype) { + return (flags & ~0x000000f0) | (btype << 4); +} + +static inline bool lfsr_f_isdirty(uint32_t flags) { + return flags & LFS_F_DIRTY; +} + +static inline bool lfsr_f_ismutated(uint32_t flags) { + return flags & LFS_F_MUTATED; +} + +static inline uint32_t lfsr_f_swapdirty(uint32_t flags) { + uint32_t x = ((flags >> 19) ^ (flags >> 18)) & 0x1; + return flags ^ (x << 19) ^ (x << 18); +} + +// mount flags static inline bool lfsr_m_isrdonly(uint32_t flags) { return flags & LFS_M_RDONLY; } @@ -5897,14 +6020,15 @@ static inline bool lfsr_m_isckprogs(uint32_t flags) { return flags & LFS_M_CKPROGS; } -static inline bool lfsr_i_isuncompacted(uint32_t flags) { - return flags & LFS_I_UNCOMPACTED; -} - +// internal fs flags static inline bool lfsr_f_hasorphans(uint32_t flags) { return flags & LFS_F_ORPHANS; } +static inline bool lfsr_f_isuncompacted(uint32_t flags) { + return flags & LFS_F_UNCOMPACTED; +} + // on-demand flags // needed in lfsr_fs_isinconsistent @@ -5927,12 +6051,6 @@ static bool lfsr_fs_canlookahead(const lfs_t *lfs) { // we maintain a linked-list of all opened mdirs, in order to keep // metadata state in-sync, these may be casted to specific file types -static inline bool lfsr_omdir_isbshrub(const lfsr_omdir_t *o) { - // it turns out that bshrub types share a bit - return o->type & 0x1; -} - - static bool lfsr_omdir_isopen(lfs_t *lfs, const lfsr_omdir_t *o) { for (lfsr_omdir_t *o_ = lfs->omdirs; o_; o_ = o_->next) { if (o_ == o) { @@ -5973,7 +6091,8 @@ static bool lfsr_omdir_ismidopen(lfs_t *lfs, lfsr_smid_t mid) { for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { // we really only care about regular open files here, all // others are either transient (dirs) or fake (orphans) - if (o->type == LFS_TYPE_REG && o->mdir.mid == mid) { + if (lfsr_f_type(o->flags) == LFS_TYPE_REG + && o->mdir.mid == mid) { return true; } } @@ -5990,7 +6109,7 @@ static void lfsr_traversal_clobber(lfs_t *lfs, lfsr_traversal_t *t); static void lfsr_omdir_clobber(lfs_t *lfs, const lfsr_omdir_t *o, bool dirty) { for (lfsr_omdir_t *o_ = lfs->omdirs; o_; o_ = o_->next) { - if (o_->type == LFS_TYPE_TRAVERSAL) { + if (lfsr_f_type(o_->flags) == LFS_TYPE_TRAVERSAL) { o_->flags |= (dirty) ? LFS_F_DIRTY : 0; if (o && ((lfsr_traversal_t*)o_)->ot == o) { @@ -6785,7 +6904,7 @@ static int lfsr_mdir_commit__(lfs_t *lfs, lfsr_mdir_t *mdir, // unsynced files for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { // belongs to our mid? - if (!(lfsr_omdir_isbshrub(o) + if (!(lfsr_f_isbshrub(o->flags) && o->mdir.mid == mdir__->mid)) { continue; } @@ -6973,7 +7092,7 @@ static lfs_ssize_t lfsr_mdir_estimate__(lfs_t *lfs, const lfsr_mdir_t *mdir, // opened files by mid for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { // belongs to our mdir + rid? - if (!(lfsr_omdir_isbshrub(o) + if (!(lfsr_f_isbshrub(o->flags) && lfsr_mdir_cmp(&o->mdir, mdir) == 0 && lfsr_mid_rid(lfs, o->mdir.mid) == a_rid)) { continue; @@ -7121,7 +7240,7 @@ static int lfsr_mdir_compact__(lfs_t *lfs, lfsr_mdir_t *mdir_, // we're not quite done! we also need to bring over any unsynced files for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { // belongs to our mdir? - if (!(lfsr_omdir_isbshrub(o) + if (!(lfsr_f_isbshrub(o->flags) && lfsr_mdir_cmp(&o->mdir, mdir) == 0 && lfsr_mid_rid(lfs, o->mdir.mid) >= start_rid && (lfsr_rid_t)lfsr_mid_rid(lfs, o->mdir.mid) @@ -7377,7 +7496,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, } // stage any bsprouts/bshrubs - if (lfsr_omdir_isbshrub(o)) { + if (lfsr_f_isbshrub(o->flags)) { ((lfsr_obshrub_t*)o)->bshrub_ = ((lfsr_obshrub_t*)o)->bshrub; } } @@ -7844,7 +7963,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // we may have touched any number of mdirs, so assume uncompacted // until lfsr_fs_gc can prove otherwise - lfs->flags |= LFS_I_UNCOMPACTED; + lfs->flags |= LFS_F_UNCOMPACTED; // update any gstate changes lfsr_fs_commitgdelta(lfs); @@ -7860,7 +7979,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // removed? if (o->mdir.mid < mid_ - attrs[i].weight) { // we should not be removing opened regular files - LFS_ASSERT(o->type != LFS_TYPE_REG); + LFS_ASSERT(lfsr_f_type(o->flags) != LFS_TYPE_REG); o->flags |= LFS_F_ZOMBIE; o->mdir.mid = mid_; } else { @@ -7875,7 +7994,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, // update any staged bsprouts/bshrubs for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { - if (lfsr_omdir_isbshrub(o)) { + if (lfsr_f_isbshrub(o->flags)) { ((lfsr_obshrub_t*)o)->bshrub = ((lfsr_obshrub_t*)o)->bshrub_; } } @@ -7887,7 +8006,7 @@ static int lfsr_mdir_commit(lfs_t *lfs, lfsr_mdir_t *mdir, if (lfsr_mdir_cmp(&mroot_, &lfs->mroot) != 0 || lfsr_mtree_cmp(&mtree_, &lfs->mtree) != 0) { for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { - if (o->type == LFS_TYPE_TRAVERSAL + if (lfsr_f_type(o->flags) == LFS_TYPE_TRAVERSAL && o->mdir.mid == -1 // don't clobber the current mdir, assume upper layers // know what they're doing @@ -8244,9 +8363,10 @@ enum { #define LFSR_TRAVERSAL(_flags) \ ((lfsr_traversal_t){ \ - .o.o.type=LFS_TYPE_TRAVERSAL, \ - .o.o.state=LFSR_TSTATE_MROOTANCHOR, \ - .o.o.flags=_flags, \ + .o.o.flags \ + = (LFS_TYPE_TRAVERSAL << 24) \ + | (LFSR_TSTATE_MROOTANCHOR << 4) \ + | (_flags), \ .o.o.mdir.mid=-1, \ .o.o.mdir.rbyd.blocks={-1,-1}, \ .o.bshrub.u.bshrub.blocks={-1}, \ @@ -8255,58 +8375,11 @@ enum { .u.mtortoise.step=0, \ .u.mtortoise.power=0}) -static inline uint8_t lfsr_t_btype(uint32_t flags) { - // store btype in flags to avoid needing an extra field - return flags & 0x7; -} - -static inline bool lfsr_t_ismtreeonly(uint32_t flags) { - return flags & LFS_T_MTREEONLY; -} - -static inline bool lfsr_t_ismkconsistent(uint32_t flags) { - return flags & LFS_T_MKCONSISTENT; -} - -static inline bool lfsr_t_islookahead(uint32_t flags) { - return flags & LFS_T_LOOKAHEAD; -} - -static inline bool lfsr_t_iscompact(uint32_t flags) { - return flags & LFS_T_COMPACT; -} - -static inline bool lfsr_t_isckmeta(uint32_t flags) { - return flags & LFS_T_CKMETA; -} - -static inline bool lfsr_t_isckdata(uint32_t flags) { - return flags & LFS_T_CKDATA; -} - -static inline bool lfsr_f_isdirty(uint32_t flags) { - return flags & LFS_F_DIRTY; -} - -static inline bool lfsr_f_ismutated(uint32_t flags) { - return flags & LFS_F_MUTATED; -} - -static inline uint32_t lfsr_f_swapdirty(uint32_t flags) { - uint32_t x = ((flags >> 14) ^ (flags >> 12)) & 0x1; - return flags ^ (x << 14) ^ (x << 12); -} - - - -// needed in lfsr_mtree_traverse_ -static inline bool lfsr_f_isunsync(uint32_t flags); - // low-level traversal _only_ finds blocks static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t, lfsr_tag_t *tag_, lfsr_bptr_t *bptr_) { while (true) { - switch (t->o.o.state) { + switch (lfsr_f_tstate(t->o.o.flags)) { // start with the mrootanchor 0x{0,1} // // note we make sure to include all mroots in our mroot chain! @@ -8320,7 +8393,8 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t, } // transition to traversing the mroot chain - t->o.o.state = LFSR_TSTATE_MROOTCHAIN; + t->o.o.flags = lfsr_f_settstate(t->o.o.flags, + LFSR_TSTATE_MROOTCHAIN); if (tag_) { *tag_ = LFSR_TAG_MDIR; @@ -8342,7 +8416,8 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t, // traverse any files in our mroot next if (err == LFS_ERR_NOENT) { t->o.o.mdir.mid = 0; - t->o.o.state = LFSR_TSTATE_MDIR; + t->o.o.flags = lfsr_f_settstate(t->o.o.flags, + LFSR_TSTATE_MDIR); continue; } return err; @@ -8405,7 +8480,8 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t, } // transition to traversing the mdir - t->o.o.state = LFSR_TSTATE_MDIR; + t->o.o.flags = lfsr_f_settstate(t->o.o.flags, + LFSR_TSTATE_MDIR); if (tag_) { *tag_ = LFSR_TAG_MDIR; @@ -8425,7 +8501,8 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t, // transition to traversing the mtree t->u.bt = LFSR_BTRAVERSAL(); - t->o.o.state = LFSR_TSTATE_MTREE; + t->o.o.flags = lfsr_f_settstate(t->o.o.flags, + LFSR_TSTATE_MTREE); continue; } else { @@ -8441,14 +8518,16 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t, if (err) { // end of mtree? guess we're done if (err == LFS_ERR_NOENT) { - t->o.o.state = LFSR_TSTATE_DONE; + t->o.o.flags = lfsr_f_settstate(t->o.o.flags, + LFSR_TSTATE_DONE); continue; } return err; } // transition to traversing the mdir - t->o.o.state = LFSR_TSTATE_MDIR; + t->o.o.flags = lfsr_f_settstate(t->o.o.flags, + LFSR_TSTATE_MDIR); if (tag_) { *tag_ = LFSR_TAG_MDIR; @@ -8466,7 +8545,8 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t, || lfsr_mid_rid(lfs, t->o.o.mdir.mid) >= (lfsr_srid_t)t->o.o.mdir.rbyd.weight) { t->o.o.mdir.mid = lfsr_mid_bid(lfs, t->o.o.mdir.mid) + 1; - t->o.o.state = LFSR_TSTATE_MDIRS; + t->o.o.flags = lfsr_f_settstate(t->o.o.flags, + LFSR_TSTATE_MDIRS); continue; } @@ -8503,13 +8583,15 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t, // no? next we need to check any opened files } else { t->ot = lfs->omdirs; - t->o.o.state = LFSR_TSTATE_OMDIRS; + t->o.o.flags = lfsr_f_settstate(t->o.o.flags, + LFSR_TSTATE_OMDIRS); continue; } // start traversing t->u.bt = LFSR_BTRAVERSAL(); - t->o.o.state = LFSR_TSTATE_BTREE; + t->o.o.flags = lfsr_f_settstate(t->o.o.flags, + LFSR_TSTATE_BTREE); continue; // scan for blocks/btrees in our opened file list @@ -8517,7 +8599,8 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t, // reached end of opened files? return to mdir traversal if (!t->ot) { t->o.o.mdir.mid += 1; - t->o.o.state = LFSR_TSTATE_MDIR; + t->o.o.flags = lfsr_f_settstate(t->o.o.flags, + LFSR_TSTATE_MDIR); continue; } @@ -8530,7 +8613,7 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t, // this list anyways // if (t->ot->mdir.mid != t->o.o.mdir.mid - || t->ot->type != LFS_TYPE_REG + || lfsr_f_type(t->ot->flags) != LFS_TYPE_REG || !lfsr_f_isunsync(t->ot->flags)) { t->ot = t->ot->next; continue; @@ -8540,7 +8623,8 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t, const lfsr_file_t *file = (const lfsr_file_t*)t->ot; t->o.bshrub = file->o.bshrub; t->u.bt = LFSR_BTRAVERSAL(); - t->o.o.state = LFSR_TSTATE_OBTREE; + t->o.o.flags = lfsr_f_settstate(t->o.o.flags, + LFSR_TSTATE_OBTREE); continue; // traverse any btrees we see, this includes the mtree and any file @@ -8555,19 +8639,25 @@ static int lfsr_mtree_traverse_(lfs_t *lfs, lfsr_traversal_t *t, if (err) { if (err == LFS_ERR_NOENT) { // end of mtree? start iterating over mdirs - if (t->o.o.state == LFSR_TSTATE_MTREE) { + if (lfsr_f_tstate(t->o.o.flags) + == LFSR_TSTATE_MTREE) { t->o.o.mdir.mid = 0; - t->o.o.state = LFSR_TSTATE_MDIRS; + t->o.o.flags = lfsr_f_settstate(t->o.o.flags, + LFSR_TSTATE_MDIRS); continue; // end of mdir btree? start iterating over opened files - } else if (t->o.o.state == LFSR_TSTATE_BTREE) { + } else if (lfsr_f_tstate(t->o.o.flags) + == LFSR_TSTATE_BTREE) { t->ot = lfs->omdirs; - t->o.o.state = LFSR_TSTATE_OMDIRS; + t->o.o.flags = lfsr_f_settstate(t->o.o.flags, + LFSR_TSTATE_OMDIRS); continue; // end of opened btree? go to next opened file - } else if (t->o.o.state == LFSR_TSTATE_OBTREE) { + } else if (lfsr_f_tstate(t->o.o.flags) + == LFSR_TSTATE_OBTREE) { t->ot = t->ot->next; - t->o.o.state = LFSR_TSTATE_OMDIRS; + t->o.o.flags = lfsr_f_settstate(t->o.o.flags, + LFSR_TSTATE_OMDIRS); continue; } else { LFS_UNREACHABLE(); @@ -8698,7 +8788,7 @@ dropped:; // swap back dirty/mutated flags t->o.o.flags = lfsr_f_swapdirty(t->o.o.flags); // continue traversal - t->o.o.state = LFSR_TSTATE_MDIRS; + t->o.o.flags = lfsr_f_settstate(t->o.o.flags, LFSR_TSTATE_MDIRS); goto dropped; } } @@ -8767,7 +8857,7 @@ eot:; if (lfsr_t_iscompact(t->o.o.flags) && !lfsr_f_isdirty(t->o.o.flags) && !lfsr_f_ismutated(t->o.o.flags)) { - lfs->flags &= ~LFS_I_UNCOMPACTED; + lfs->flags &= ~LFS_F_UNCOMPACTED; } return LFS_ERR_NOENT; @@ -9112,7 +9202,7 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) { for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { // mark any clobbered orphans as zombied if (exists - && o->type == LFS_TYPE_REG + && lfsr_f_type(o->flags) == LFS_TYPE_REG && o->mdir.mid == mdir.mid) { o->flags = (o->flags & ~LFS_F_ORPHAN) | LFS_F_ZOMBIE @@ -9121,7 +9211,7 @@ int lfsr_mkdir(lfs_t *lfs, const char *path) { // update dir positions } else if (!exists - && o->type == LFS_TYPE_DIR + && lfsr_f_type(o->flags) == LFS_TYPE_DIR && ((lfsr_dir_t*)o)->did == did && o->mdir.mid >= mdir.mid) { ((lfsr_dir_t*)o)->pos += 1; @@ -9182,7 +9272,6 @@ empty:; } // needed in lfsr_remove -static inline bool lfsr_f_iszombie(uint32_t flags); static int lfsr_fs_fixgrm(lfs_t *lfs); int lfsr_remove(lfs_t *lfs, const char *path) { @@ -9257,7 +9346,7 @@ int lfsr_remove(lfs_t *lfs, const char *path) { for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { // mark any clobbered orphans as zombied orphans if (zombie - && o->type == LFS_TYPE_REG + && lfsr_f_type(o->flags) == LFS_TYPE_REG && o->mdir.mid == mdir.mid) { o->flags |= LFS_F_ORPHAN | LFS_F_ZOMBIE @@ -9266,12 +9355,12 @@ int lfsr_remove(lfs_t *lfs, const char *path) { // mark any removed dirs as zombied } else if (did_ - && o->type == LFS_TYPE_DIR + && lfsr_f_type(o->flags) == LFS_TYPE_DIR && ((lfsr_dir_t*)o)->did == did_) { o->flags |= LFS_F_ZOMBIE; // update dir positions - } else if (o->type == LFS_TYPE_DIR + } else if (lfsr_f_type(o->flags) == LFS_TYPE_DIR && ((lfsr_dir_t*)o)->did == did && o->mdir.mid >= mdir.mid) { if (lfsr_f_iszombie(o->flags)) { @@ -9281,7 +9370,7 @@ int lfsr_remove(lfs_t *lfs, const char *path) { } // clobber entangled traversals - } else if (o->type == LFS_TYPE_TRAVERSAL) { + } else if (lfsr_f_type(o->flags) == LFS_TYPE_TRAVERSAL) { if (lfsr_f_iszombie(o->flags)) { o->flags &= ~LFS_F_ZOMBIE; o->mdir.mid -= 1; @@ -9407,7 +9496,7 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) { for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { // mark any clobbered orphans as zombied if (exists - && o->type == LFS_TYPE_REG + && lfsr_f_type(o->flags) == LFS_TYPE_REG && o->mdir.mid == new_mdir.mid) { o->flags = (o->flags & ~LFS_F_ORPHAN) | LFS_F_ZOMBIE @@ -9415,18 +9504,18 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) { | LFS_O_DESYNC; // update moved files with the new mdir - } else if (o->type == LFS_TYPE_REG + } else if (lfsr_f_type(o->flags) == LFS_TYPE_REG && o->mdir.mid == lfs->grm.mids[0]) { o->mdir = new_mdir; // mark any removed dirs as zombied } else if (new_did_ - && o->type == LFS_TYPE_DIR + && lfsr_f_type(o->flags) == LFS_TYPE_DIR && ((lfsr_dir_t*)o)->did == new_did_) { o->flags |= LFS_F_ZOMBIE; // update dir positions - } else if (o->type == LFS_TYPE_DIR) { + } else if (lfsr_f_type(o->flags) == LFS_TYPE_DIR) { if (!exists && ((lfsr_dir_t*)o)->did == new_did && o->mdir.mid >= new_mdir.mid) { @@ -9443,7 +9532,7 @@ int lfsr_rename(lfs_t *lfs, const char *old_path, const char *new_path) { } // clobber entangled traversals - } else if (o->type == LFS_TYPE_TRAVERSAL + } else if (lfsr_f_type(o->flags) == LFS_TYPE_TRAVERSAL && ((exists && o->mdir.mid == new_mdir.mid) || o->mdir.mid == lfs->grm.mids[0])) { lfsr_traversal_clobber(lfs, (lfsr_traversal_t*)o); @@ -9550,8 +9639,7 @@ int lfsr_dir_open(lfs_t *lfs, lfsr_dir_t *dir, const char *path) { LFS_ASSERT(!lfsr_omdir_isopen(lfs, &dir->o)); // setup dir state - dir->o.type = LFS_TYPE_DIR; - dir->o.flags = 0; + dir->o.flags = lfsr_f_settype(0, LFS_TYPE_DIR); // lookup our directory lfsr_mdir_t mdir; @@ -9772,60 +9860,7 @@ int lfsr_dir_rewind(lfs_t *lfs, lfsr_dir_t *dir) { /// File operations /// -// flag things -static inline bool lfsr_o_isrdonly(uint32_t flags) { - return (flags & 3) == LFS_O_RDONLY; -} - -static inline bool lfsr_o_iswronly(uint32_t flags) { - return (flags & 3) == LFS_O_WRONLY; -} - -static inline bool lfsr_o_iscreat(uint32_t flags) { - return flags & LFS_O_CREAT; -} - -static inline bool lfsr_o_isexcl(uint32_t flags) { - return flags & LFS_O_EXCL; -} - -static inline bool lfsr_o_istrunc(uint32_t flags) { - return flags & LFS_O_TRUNC; -} - -static inline bool lfsr_o_isappend(uint32_t flags) { - return flags & LFS_O_APPEND; -} - -static inline bool lfsr_o_isflush(uint32_t flags) { - return flags & LFS_O_FLUSH; -} - -static inline bool lfsr_o_issync(uint32_t flags) { - return flags & LFS_O_SYNC; -} - -static inline bool lfsr_o_isdesync(uint32_t flags) { - return flags & LFS_O_DESYNC; -} - -static inline bool lfsr_f_isunflush(uint32_t flags) { - return flags & LFS_F_UNFLUSH; -} - -static inline bool lfsr_f_isunsync(uint32_t flags) { - return flags & LFS_F_UNSYNC; -} - -static inline bool lfsr_f_isorphan(uint32_t flags) { - return flags & LFS_F_ORPHAN; -} - -static inline bool lfsr_f_iszombie(uint32_t flags) { - return flags & LFS_F_ZOMBIE; -} - -// other file helpers +// file helpers static inline lfs_size_t lfsr_file_buffersize(lfs_t *lfs, const lfsr_file_t *file) { return (file->cfg->buffer_size) @@ -9888,8 +9923,7 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file, } // setup file state - file->o.o.type = LFS_TYPE_REG; - file->o.o.flags = flags; + file->o.o.flags = lfsr_f_settype(flags, LFS_TYPE_REG); file->cfg = cfg; file->pos = 0; file->eblock = 0; @@ -9936,7 +9970,7 @@ int lfsr_file_opencfg(lfs_t *lfs, lfsr_file_t *file, // update dir positions for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { - if (o->type == LFS_TYPE_DIR + if (lfsr_f_type(o->flags) == LFS_TYPE_DIR && ((lfsr_dir_t*)o)->did == did && o->mdir.mid >= file->o.o.mdir.mid) { ((lfsr_dir_t*)o)->pos += 1; @@ -11364,7 +11398,7 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) { // update in-device state for (lfsr_omdir_t *o = lfs->omdirs; o; o = o->next) { - if (o->type == LFS_TYPE_REG + if (lfsr_f_type(o->flags) == LFS_TYPE_REG && o->mdir.mid == file->o.o.mdir.mid // don't double update && o != &file->o.o) { @@ -11395,7 +11429,7 @@ int lfsr_file_sync(lfs_t *lfs, lfsr_file_t *file) { } // clobber entangled traversals - } else if (o->type == LFS_TYPE_TRAVERSAL + } else if (lfsr_f_type(o->flags) == LFS_TYPE_TRAVERSAL && o->mdir.mid == file->o.o.mdir.mid) { lfsr_traversal_clobber(lfs, (lfsr_traversal_t*)o); } @@ -12504,7 +12538,7 @@ static int lfsr_mountinited(lfs_t *lfs) { // default to assuming we need a compaction somewhere, worst case this // just makes lfsr_fs_gc read more than is strictly needed - lfs->flags |= LFS_I_UNCOMPACTED; + lfs->flags |= LFS_F_UNCOMPACTED; return 0; } @@ -12962,7 +12996,7 @@ int lfsr_fs_gc(lfs_t *lfs, lfs_soff_t steps, uint32_t flags) { uint32_t pending = flags & ( ((lfsr_f_hasorphans(lfs->flags)) ? LFS_GC_MKCONSISTENT : 0) | ((lfsr_fs_canlookahead(lfs)) ? LFS_GC_LOOKAHEAD : 0) - | ((lfsr_i_isuncompacted(lfs->flags)) ? LFS_GC_COMPACT : 0) + | ((lfsr_f_isuncompacted(lfs->flags)) ? LFS_GC_COMPACT : 0) | LFS_GC_CKMETA | LFS_GC_CKDATA); @@ -13030,7 +13064,7 @@ int lfsr_fs_gc(lfs_t *lfs, lfs_soff_t steps, uint32_t flags) { | ((!lfsr_fs_canlookahead(lfs)) ? LFS_GC_LOOKAHEAD : 0) - | ((!lfsr_i_isuncompacted(lfs->flags)) + | ((!lfsr_f_isuncompacted(lfs->flags)) ? LFS_GC_COMPACT : 0) // only consider our filesystem checked if we @@ -13128,8 +13162,7 @@ int lfsr_traversal_open(lfs_t *lfs, lfsr_traversal_t *t, uint32_t flags) { LFS_ASSERT(!lfsr_t_ismtreeonly(flags) || !lfsr_t_isckdata(flags)); // setup traversal state - t->o.o.type = LFS_TYPE_TRAVERSAL; - t->o.o.flags = flags; + t->o.o.flags = lfsr_f_settype(flags, LFS_TYPE_TRAVERSAL); // let rewind initialize/reset things int err = lfsr_traversal_rewind_(lfs, t); @@ -13189,7 +13222,7 @@ int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *t, // some redund blocks left over? if (t->blocks[0] != -1) { // write our traversal info - tinfo->btype = lfsr_t_btype(t->o.o.flags); + tinfo->btype = lfsr_f_btype(t->o.o.flags); tinfo->block = t->blocks[0]; t->blocks[0] = t->blocks[1]; @@ -13209,18 +13242,18 @@ int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *t, // figure out type/blocks if (tag == LFSR_TAG_MDIR) { lfsr_mdir_t *mdir = (lfsr_mdir_t*)bptr.data.u.buffer; - t->o.o.flags = (t->o.o.flags & ~0x7) | LFS_BTYPE_MDIR; + t->o.o.flags = lfsr_f_setbtype(t->o.o.flags, LFS_BTYPE_MDIR); t->blocks[0] = mdir->rbyd.blocks[0]; t->blocks[1] = mdir->rbyd.blocks[1]; } else if (tag == LFSR_TAG_BRANCH) { - t->o.o.flags = (t->o.o.flags & ~0x7) | LFS_BTYPE_BTREE; + t->o.o.flags = lfsr_f_setbtype(t->o.o.flags, LFS_BTYPE_BTREE); lfsr_rbyd_t *rbyd = (lfsr_rbyd_t*)bptr.data.u.buffer; t->blocks[0] = rbyd->blocks[0]; t->blocks[1] = -1; } else if (tag == LFSR_TAG_BLOCK) { - t->o.o.flags = (t->o.o.flags & ~0x7) | LFS_BTYPE_DATA; + t->o.o.flags = lfsr_f_setbtype(t->o.o.flags, LFS_BTYPE_DATA); t->blocks[0] = bptr.data.u.disk.block; t->blocks[1] = -1; @@ -13233,23 +13266,23 @@ int lfsr_traversal_read(lfs_t *lfs, lfsr_traversal_t *t, static void lfsr_traversal_clobber(lfs_t *lfs, lfsr_traversal_t *t) { (void)lfs; // mroot/mtree? transition to mdir iteration - if (t->o.o.state < LFSR_TSTATE_MDIRS) { - t->o.o.state = LFSR_TSTATE_MDIRS; + if (lfsr_f_tstate(t->o.o.flags) < LFSR_TSTATE_MDIRS) { + t->o.o.flags = lfsr_f_settstate(t->o.o.flags, LFSR_TSTATE_MDIRS); t->o.o.mdir.mid = 0; t->o.bshrub.u.bshrub.weight = 0; t->o.bshrub.u.bshrub.blocks[0] = -1; t->ot = NULL; // in-mtree mdir? increment the mid (to make progress) and reset to // mdir iteration - } else if (t->o.o.state < LFSR_TSTATE_OMDIRS) { - t->o.o.state = LFSR_TSTATE_MDIR; + } else if (lfsr_f_tstate(t->o.o.flags) < LFSR_TSTATE_OMDIRS) { + t->o.o.flags = lfsr_f_settstate(t->o.o.flags, LFSR_TSTATE_MDIR); t->o.o.mdir.mid += 1; t->o.bshrub.u.bshrub.weight = 0; t->o.bshrub.u.bshrub.blocks[0] = -1; t->ot = NULL; // opened mdir? skip to next omdir - } else if (t->o.o.state < LFSR_TSTATE_DONE) { - t->o.o.state = LFSR_TSTATE_OMDIRS; + } else if (lfsr_f_tstate(t->o.o.flags) < LFSR_TSTATE_DONE) { + t->o.o.flags = lfsr_f_settstate(t->o.o.flags, LFSR_TSTATE_OMDIRS); t->o.bshrub.u.bshrub.weight = 0; t->o.bshrub.u.bshrub.blocks[0] = -1; t->ot = (t->ot) ? t->ot->next : NULL; @@ -13266,8 +13299,9 @@ static void lfsr_traversal_clobber(lfs_t *lfs, lfsr_traversal_t *t) { static int lfsr_traversal_rewind_(lfs_t *lfs, lfsr_traversal_t *t) { (void)lfs; // reset traversal - t->o.o.flags &= ~(LFS_F_DIRTY | LFS_F_MUTATED); - t->o.o.state = LFSR_TSTATE_MROOTANCHOR; + t->o.o.flags = lfsr_f_settstate( + t->o.o.flags & ~(LFS_F_DIRTY | LFS_F_MUTATED), + LFSR_TSTATE_MROOTANCHOR); t->o.o.mdir.mid = -1; t->o.o.mdir.rbyd.weight = 0; t->o.o.mdir.rbyd.blocks[0] = -1; diff --git a/lfs.h b/lfs.h index ed5ed342..a9e8e330 100644 --- a/lfs.h +++ b/lfs.h @@ -113,35 +113,6 @@ enum lfs_error { LFS_ERR_RANGE = -34, // Result out of range }; -// Filesystem mount flags -enum lfs_mount_flags { - LFS_M_RDWR = 0x0000, // Mount the filesystem as read and write - LFS_M_RDONLY = 0x0001, // Mount the filesystem as read only - LFS_M_CKPROGS = 0x0008, // Check progs by reading back progged data - - LFS_M_MTREEONLY = 0x0010, // Only traverse the mtree - LFS_M_MKCONSISTENT = 0x0020, // Make the filesystem consistent - LFS_M_LOOKAHEAD = 0x0040, // Populate lookahead buffer - LFS_M_COMPACT = 0x0080, // Compact metadata logs - LFS_M_CKMETA = 0x0100, // Check metadata checksums - LFS_M_CKDATA = 0x0200, // Check metadata + data checksums -}; - -// Filesystem info flags -enum lfs_fsinfo_flags { - // mount flags - LFS_I_RDONLY = 0x0001, // Filesystem mounted read only - LFS_I_CKPROGS = 0x0008, // Check progs by reading back progged data - - // state flags - LFS_I_INCONSISTENT = 0x0100, // Filesystem needs mkconsistent to write - LFS_I_CANLOOKAHEAD = 0x0400, // Lookahead buffer is not full - LFS_I_UNCOMPACTED = 0x1000, // Filesystem may have uncompacted metadata - - // internally used flags - LFS_F_ORPHANS = 0x8000, // Filesystem may have untracked orphans -}; - // File types enum lfs_type { // file types @@ -155,75 +126,94 @@ enum lfs_type { }; // File open flags -enum lfs_open_flags { - // open flags - LFS_O_RDONLY = 0, // Open a file as read only -#ifndef LFS_READONLY - LFS_O_WRONLY = 1, // Open a file as write only - LFS_O_RDWR = 2, // Open a file as read and write - LFS_O_CREAT = 0x0004, // Create a file if it does not exist - LFS_O_EXCL = 0x0008, // Fail if a file already exists - LFS_O_TRUNC = 0x0010, // Truncate the existing file to zero size - LFS_O_APPEND = 0x0020, // Move to end of file on every write - LFS_O_FLUSH = 0x0040, // Flush data on every write - LFS_O_SYNC = 0x0080, // Sync metadata on every write - LFS_O_DESYNC = 0x0100, // Do not sync or recieve file updates -#endif +#define LFS_O_RDONLY 0 // Open a file as read only +#define LFS_O_WRONLY 1 // Open a file as write only +#define LFS_O_RDWR 2 // Open a file as read and write +#define LFS_O_CREAT 0x00000004 // Create a file if it does not exist +#define LFS_O_EXCL 0x00000008 // Fail if a file already exists +#define LFS_O_TRUNC 0x00000010 // Truncate the existing file to zero size +#define LFS_O_APPEND 0x00000020 // Move to end of file on every write +#define LFS_O_FLUSH 0x00000040 // Flush data on every write +#define LFS_O_SYNC 0x00000080 // Sync metadata on every write +#define LFS_O_DESYNC 0x00000100 // Do not sync or recieve file updates - // internally used flags - LFS_F_UNFLUSH = 0x1000, // File's data does not match disk - LFS_F_UNSYNC = 0x2000, // File's metadata does not match disk - LFS_F_ORPHAN = 0x4000, // File does not exist - LFS_F_ZOMBIE = 0x8000, // File has been removed -}; +// internally used flags +#define LFS_F_TYPE 0xff000000 // The file's type +#define LFS_F_UNFLUSH 0x00100000 // File's data does not match disk +#define LFS_F_UNSYNC 0x00200000 // File's metadata does not match disk +#define LFS_F_ORPHAN 0x00400000 // File does not exist +#define LFS_F_ZOMBIE 0x00800000 // File has been removed // File seek flags -enum lfs_whence_flags { - LFS_SEEK_SET = 0, // Seek relative to an absolute position - LFS_SEEK_CUR = 1, // Seek relative to the current file position - LFS_SEEK_END = 2, // Seek relative to the end of the file -}; +#define LFS_SEEK_SET 0 // Seek relative to an absolute position +#define LFS_SEEK_CUR 1 // Seek relative to the current file position +#define LFS_SEEK_END 2 // Seek relative to the end of the file + +// Filesystem mount flags +#define LFS_M_RDWR 0 // Mount the filesystem as read and write +#define LFS_M_RDONLY 1 // Mount the filesystem as read only +#define LFS_M_CKPROGS 0x00000010 // Check progs by reading back progged data + +#define LFS_M_MTREEONLY \ + 0x00010000 // Only traverse the mtree +#define LFS_M_MKCONSISTENT \ + 0x00000100 // Make the filesystem consistent +#define LFS_M_LOOKAHEAD \ + 0x00000200 // Populate lookahead buffer +#define LFS_M_COMPACT 0x00000800 // Compact metadata logs +#define LFS_M_CKMETA 0x00001000 // Check metadata checksums +#define LFS_M_CKDATA 0x00002000 // Check metadata + data checksums + +// internally used flags +#define LFS_F_ORPHANS 0x01000000 // Filesystem may have untracked orphans +#define LFS_F_UNCOMPACTED \ + 0x08000000 // Filesystem may have uncompacted metadata + +// Filesystem info flags +#define LFS_I_RDONLY 0x00000001 // Filesystem mounted read only +#define LFS_I_CKPROGS 0x00000010 // Check progs by reading back progged data + +#define LFS_I_INCONSISTENT \ + 0x01000000 // Filesystem needs mkconsistent to write +#define LFS_I_CANLOOKAHEAD \ + 0x02000000 // Lookahead buffer is not full +#define LFS_I_UNCOMPACTED \ + 0x08000000 // Filesystem may have uncompacted metadata // Block types enum lfs_btype { LFS_BTYPE_MDIR = 1, LFS_BTYPE_BTREE = 2, LFS_BTYPE_DATA = 3, -// TODO -// LFS_BTYPE_PARITY = 4, -// LFS_BTYPE_BAD = 5, }; // Traversal flags -enum lfs_traversal_flags { - // traversal open flags - LFS_T_MTREEONLY = 0x0010, // Only traverse the mtree - LFS_T_MKCONSISTENT = 0x0020, // Make the filesystem consistent - LFS_T_LOOKAHEAD = 0x0040, // Populate lookahead buffer - LFS_T_COMPACT = 0x0080, // Compact metadata logs - LFS_T_CKMETA = 0x0100, // Check metadata checksums - LFS_T_CKDATA = 0x0200, // Check metadata + data checksums -// TODO -// LFS_T_REPAIRMETA = 0x0400, // Repair metadata blocks -// LFS_T_REPAIRDATA = 0x0800, // Repair metadata + data blocks +#define LFS_T_MTREEONLY \ + 0x00010000 // Only traverse the mtree +#define LFS_T_MKCONSISTENT \ + 0x00000100 // Make the filesystem consistent +#define LFS_T_LOOKAHEAD \ + 0x00000200 // Populate lookahead buffer +#define LFS_T_COMPACT 0x00000800 // Compact metadata logs +#define LFS_T_CKMETA 0x00001000 // Check metadata checksums +#define LFS_T_CKDATA 0x00002000 // Check metadata + data checksums - // internally used flags - LFS_F_DIRTY = 0x1000, // Filesystem modified during traversal - LFS_F_MUTATED = 0x4000, // Filesystem modified by traversal -}; +// internally used flags +#define LFS_F_TSTATE 0x0000000f // The current traversal state +#define LFS_F_BTYPE 0x000000f0 // The current traversal btype +#define LFS_F_DIRTY 0x00040000 // Filesystem modified during traversal +#define LFS_F_MUTATED 0x00080000 // Filesystem modified by traversal // GC flags -enum lfs_gc_flags { - LFS_GC_MTREEONLY = 0x0010, // Only traverse the mtree - LFS_GC_MKCONSISTENT = 0x0020, // Make the filesystem consistent - LFS_GC_LOOKAHEAD = 0x0040, // Populate lookahead buffer - LFS_GC_COMPACT = 0x0080, // Compact metadata logs - LFS_GC_CKMETA = 0x0100, // Check metadata checksums - LFS_GC_CKDATA = 0x0200, // Check metadata + data checksums -// TODO -// LFS_GC_REPAIRMETA = 0x0400, // Repair metadata blocks -// LFS_GC_REPAIRDATA = 0x0800, // Repair metadata + data blocks -}; +#define LFS_GC_MTREEONLY \ + 0x00010000 // Only traverse the mtree +#define LFS_GC_MKCONSISTENT \ + 0x00000100 // Make the filesystem consistent +#define LFS_GC_LOOKAHEAD \ + 0x00000200 // Populate lookahead buffer +#define LFS_GC_COMPACT 0x00000800 // Compact metadata logs +#define LFS_GC_CKMETA 0x00001000 // Check metadata checksums +#define LFS_GC_CKDATA 0x00002000 // Check metadata + data checksums // Configuration provided during initialization of the littlefs @@ -522,9 +512,7 @@ typedef struct lfsr_mdir { typedef struct lfsr_omdir { struct lfsr_omdir *next; - uint8_t type; - uint8_t state; - uint16_t flags; + uint32_t flags; lfsr_mdir_t mdir; } lfsr_omdir_t; @@ -723,7 +711,7 @@ typedef struct lfsr_grm { // The littlefs filesystem type typedef struct lfs { const struct lfs_config *cfg; - uint16_t flags; + uint32_t flags; lfs_size_t block_count; lfs_size_t name_limit; lfs_off_t file_limit; diff --git a/tests/test_mtree.toml b/tests/test_mtree.toml index 216ee474..9fb5af05 100644 --- a/tests/test_mtree.toml +++ b/tests/test_mtree.toml @@ -2598,7 +2598,7 @@ code = ''' lfs_alloc_ckpoint(&lfs); // setup our neighbors - lfsr_omdir_t left = {.type=0}; + lfsr_omdir_t left = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "a", 1, &left.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &left.mdir, LFSR_ATTRS( @@ -2606,7 +2606,7 @@ code = ''' assert(left.mdir.rbyd.weight == 2); lfsr_omdir_open(&lfs, &left); - lfsr_omdir_t right = {.type=0}; + lfsr_omdir_t right = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "c", 1, &right.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &right.mdir, LFSR_ATTRS( @@ -2657,7 +2657,7 @@ code = ''' lfs_alloc_ckpoint(&lfs); // setup our neighbors - lfsr_omdir_t left = {.type=0}; + lfsr_omdir_t left = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "a", 1, &left.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &left.mdir, LFSR_ATTRS( @@ -2665,7 +2665,7 @@ code = ''' assert(left.mdir.rbyd.weight == 2); lfsr_omdir_open(&lfs, &left); - lfsr_omdir_t right = {.type=0}; + lfsr_omdir_t right = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "b", 1, &right.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &right.mdir, LFSR_ATTRS( @@ -2707,7 +2707,7 @@ code = ''' lfs_alloc_ckpoint(&lfs); // setup our neighbors - lfsr_omdir_t left = {.type=0}; + lfsr_omdir_t left = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "a", 1, &left.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &left.mdir, LFSR_ATTRS( @@ -2715,7 +2715,7 @@ code = ''' assert(left.mdir.rbyd.weight == 2); lfsr_omdir_open(&lfs, &left); - lfsr_omdir_t right = {.type=0}; + lfsr_omdir_t right = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "b", 1, &right.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &right.mdir, LFSR_ATTRS( @@ -2759,7 +2759,7 @@ code = ''' lfs_alloc_ckpoint(&lfs); // setup our neighbors - lfsr_omdir_t left = {.type=0}; + lfsr_omdir_t left = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "a", 1, &left.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &left.mdir, LFSR_ATTRS( @@ -2767,7 +2767,7 @@ code = ''' assert(left.mdir.rbyd.weight == 2); lfsr_omdir_open(&lfs, &left); - lfsr_omdir_t right = {.type=0}; + lfsr_omdir_t right = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "d", 1, &right.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &right.mdir, LFSR_ATTRS( @@ -2832,7 +2832,7 @@ code = ''' lfs_alloc_ckpoint(&lfs); // setup our neighbors - lfsr_omdir_t left = {.type=0}; + lfsr_omdir_t left = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "a", 1, &left.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &left.mdir, LFSR_ATTRS( @@ -2840,7 +2840,7 @@ code = ''' assert(left.mdir.rbyd.weight == 2); lfsr_omdir_open(&lfs, &left); - lfsr_omdir_t right = {.type=0}; + lfsr_omdir_t right = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "e", 1, &right.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &right.mdir, LFSR_ATTRS( @@ -2917,7 +2917,7 @@ code = ''' lfs_alloc_ckpoint(&lfs); // setup our neighbors - lfsr_omdir_t left = {.type=0}; + lfsr_omdir_t left = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "a", 1, &left.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &left.mdir, LFSR_ATTRS( @@ -2925,7 +2925,7 @@ code = ''' assert(left.mdir.rbyd.weight == 2); lfsr_omdir_open(&lfs, &left); - lfsr_omdir_t right = {.type=0}; + lfsr_omdir_t right = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "b", 1, &right.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &right.mdir, LFSR_ATTRS( @@ -2975,7 +2975,7 @@ code = ''' lfs_alloc_ckpoint(&lfs); // setup our neighbors - lfsr_omdir_t left = {.type=0}; + lfsr_omdir_t left = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "a", 1, &left.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &left.mdir, LFSR_ATTRS( @@ -2983,7 +2983,7 @@ code = ''' assert(left.mdir.rbyd.weight == 2); lfsr_omdir_open(&lfs, &left); - lfsr_omdir_t right = {.type=0}; + lfsr_omdir_t right = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "d", 1, &right.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &right.mdir, LFSR_ATTRS( @@ -3064,7 +3064,7 @@ code = ''' lfs_alloc_ckpoint(&lfs); // setup our neighbors - lfsr_omdir_t left = {.type=0}; + lfsr_omdir_t left = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "a", 1, &left.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &left.mdir, LFSR_ATTRS( @@ -3072,7 +3072,7 @@ code = ''' assert(left.mdir.rbyd.weight == 2); lfsr_omdir_open(&lfs, &left); - lfsr_omdir_t right = {.type=0}; + lfsr_omdir_t right = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "d", 1, &right.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &right.mdir, LFSR_ATTRS( @@ -3151,7 +3151,7 @@ code = ''' lfs_alloc_ckpoint(&lfs); // setup our neighbors - lfsr_omdir_t left = {.type=0}; + lfsr_omdir_t left = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "a", 1, &left.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &left.mdir, LFSR_ATTRS( @@ -3159,7 +3159,7 @@ code = ''' assert(left.mdir.rbyd.weight == 2); lfsr_omdir_open(&lfs, &left); - lfsr_omdir_t right = {.type=0}; + lfsr_omdir_t right = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "f", 1, &right.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &right.mdir, LFSR_ATTRS( @@ -3253,7 +3253,7 @@ code = ''' lfs_alloc_ckpoint(&lfs); // setup our neighbors - lfsr_omdir_t left = {.type=0}; + lfsr_omdir_t left = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "a", 1, &left.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &left.mdir, LFSR_ATTRS( @@ -3261,7 +3261,7 @@ code = ''' assert(left.mdir.rbyd.weight == 2); lfsr_omdir_open(&lfs, &left); - lfsr_omdir_t right = {.type=0}; + lfsr_omdir_t right = {.flags=0}; lfsr_mtree_namelookup(&lfs, 0, "e", 1, &right.mdir, NULL, NULL) => LFS_ERR_NOENT; lfsr_mdir_commit(&lfs, &right.mdir, LFSR_ATTRS(