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.
This commit is contained in:
Christopher Haster
2024-07-25 14:05:04 -05:00
parent 35db3bc97f
commit 0893c1f6be
3 changed files with 318 additions and 296 deletions
+223 -189
View File
@@ -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;
+75 -87
View File
@@ -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;
+20 -20
View File
@@ -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(