gc: Made CKMETA/CKDATA progressable, added lfsr_gc_unck
LFS_GC_CKMETA and LFS_GC_CKDATA are a bit unique in that their work is
never really done.
Where LFS_GC_MKCONSISTENT/COMPACT can prove things about the system,
LFS_GC_CKMETA/CKDATA can't, because it's always possible for new
bit-errors to develop. Even _during_ an LFS_GC_CKMETA/CKDATA traversal.
But while this is technically true, it's not a very useful state of
things for our lfsr_gc API...
---
What we really want is some way to know if ckmeta/ckdata has completed
"recently" (for some definition of recently), and to let users indicate
when they need another ckmeta/ckdata scan.
To try to solve this:
1. Added LFS_I_CANCKMETA and LFS_I_CANCKDATA to indicate when lfsr_gc
has not checked metadata/data.
These are set during mount (unless mounting with
LFS_M_CKMETA/CKDATA), and cleared when either lfsr_gc completes or
lfsr_fs_ckmeta/data is called. Once cleared, littlefs will not reset
them on its own.
2. Added lfsr_gc_unck to allow users to explicitly reset LFS_I_CKMETA
and/or LFS_I_CKDATA, which will tell lfsr_gc to check metadata/data
again on the next call.
There is some subtlety around clobbering ongoing traversals, but a
mask and some tests should prevent this from being a problem.
Currently, lfsr_gc_unck also allows clearing of other gc flags, but
I'm not sure there's any real use-case for this...
Note that you can still get the previous behavior if you just call
lfsr_gc_unck after every lfsr_gc call.
This also changes info flag behavior slightly in default mode, with
LFS_I_CANCKMETA/CANCKDATA telling you if metadata/data has been checked
since mount. Which does seem useful? Maybe these flags deserve a better
name?
Code changes:
code stack ctx
default before: 37796 (+0.0%) 2608 (+0.0%) 620 (+0.0%)
default after: 37792 (+0.0%) 2608 (+0.0%) 620 (+0.0%)
gc before: 37896 2608 768
gc after: 37938 (+0.1%) 2608 (+0.0%) 768 (+0.0.%)
This commit is contained in:
@@ -6728,6 +6728,14 @@ static inline bool lfsr_i_isuncompacted(uint32_t flags) {
|
||||
return flags & LFS_I_UNCOMPACTED;
|
||||
}
|
||||
|
||||
static inline bool lfsr_i_canckmeta(uint32_t flags) {
|
||||
return flags & LFS_I_CANCKMETA;
|
||||
}
|
||||
|
||||
static inline bool lfsr_i_canckdata(uint32_t flags) {
|
||||
return flags & LFS_I_CANCKDATA;
|
||||
}
|
||||
|
||||
// on-demand flags
|
||||
|
||||
// needed in lfsr_fs_isinconsistent
|
||||
@@ -9621,6 +9629,7 @@ failed:;
|
||||
eot:;
|
||||
// was lookahead scan successful?
|
||||
if (lfsr_t_islookahead(t->o.o.flags)
|
||||
&& !lfsr_t_ismtreeonly(t->o.o.flags)
|
||||
&& !lfsr_t_isdirty(t->o.o.flags)
|
||||
&& !lfsr_t_ismutated(t->o.o.flags)) {
|
||||
lfs_alloc_markfree(lfs);
|
||||
@@ -9640,6 +9649,21 @@ eot:;
|
||||
lfs->flags &= ~LFS_I_UNCOMPACTED;
|
||||
}
|
||||
|
||||
// was ckmeta/ckdata successful? we only consider our filesystem
|
||||
// checked if we weren't mutated
|
||||
if (lfsr_t_isckmeta(t->o.o.flags)
|
||||
&& !lfsr_t_ismtreeonly(t->o.o.flags)
|
||||
&& !lfsr_t_isdirty(t->o.o.flags)
|
||||
&& !lfsr_t_ismutated(t->o.o.flags)) {
|
||||
lfs->flags &= ~LFS_I_CANCKMETA;
|
||||
}
|
||||
if (lfsr_t_isckdata(t->o.o.flags)
|
||||
&& !lfsr_t_ismtreeonly(t->o.o.flags)
|
||||
&& !lfsr_t_isdirty(t->o.o.flags)
|
||||
&& !lfsr_t_ismutated(t->o.o.flags)) {
|
||||
lfs->flags &= ~LFS_I_CANCKDATA;
|
||||
}
|
||||
|
||||
return LFS_ERR_NOENT;
|
||||
}
|
||||
|
||||
@@ -13188,7 +13212,10 @@ static int lfs_init(lfs_t *lfs, uint32_t flags,
|
||||
| LFS_I_UNTIDY
|
||||
// default to assuming we need compaction somewhere, worst case
|
||||
// this just makes lfsr_gc read more than is strictly needed
|
||||
| LFS_I_UNCOMPACTED;
|
||||
| LFS_I_UNCOMPACTED
|
||||
// default to needing a ckmeta/ckdata scan
|
||||
| LFS_I_CANCKMETA
|
||||
| LFS_I_CANCKDATA;
|
||||
|
||||
// copy block_count so we can mutate it
|
||||
lfs->block_count = lfs->cfg->block_count;
|
||||
@@ -14196,7 +14223,9 @@ int lfsr_fs_stat(lfs_t *lfs, struct lfs_fsinfo *fsinfo) {
|
||||
| LFS_IFDEF_CKFETCHES(LFS_I_CKFETCHES, 0)
|
||||
| LFS_IFDEF_CKPARITY(LFS_I_CKPARITY, 0)
|
||||
| LFS_IFDEF_CKDATACKSUMS(LFS_I_CKDATACKSUMS, 0)
|
||||
| LFS_I_UNCOMPACTED);
|
||||
| LFS_I_UNCOMPACTED
|
||||
| LFS_I_CANCKMETA
|
||||
| LFS_I_CANCKDATA);
|
||||
// some flags we calculate on demand
|
||||
fsinfo->flags |= (lfsr_fs_isinconsistent(lfs)) ? LFS_I_INCONSISTENT : 0;
|
||||
fsinfo->flags |= (lfsr_fs_canlookahead(lfs)) ? LFS_I_CANLOOKAHEAD : 0;
|
||||
@@ -14403,6 +14432,8 @@ static int lfsr_fs_ck(lfs_t *lfs, uint32_t flags) {
|
||||
}
|
||||
}
|
||||
|
||||
// clear relevant ck flags
|
||||
lfs->flags &= ~flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -14452,10 +14483,10 @@ static int lfsr_fs_gc(lfs_t *lfs, lfsr_traversal_t *t,
|
||||
uint32_t pending = flags & (
|
||||
(lfs->flags & (
|
||||
LFS_I_UNTIDY
|
||||
| LFS_I_UNCOMPACTED))
|
||||
| ((lfsr_fs_canlookahead(lfs)) ? LFS_GC_LOOKAHEAD : 0)
|
||||
| LFS_GC_CKMETA
|
||||
| LFS_GC_CKDATA);
|
||||
| LFS_I_UNCOMPACTED
|
||||
| LFS_I_CANCKMETA
|
||||
| LFS_I_CANCKDATA))
|
||||
| ((lfsr_fs_canlookahead(lfs)) ? LFS_GC_LOOKAHEAD : 0));
|
||||
|
||||
while (pending && (lfs_off_t)steps > 0) {
|
||||
// checkpoint the allocator to maximize any lookahead scans
|
||||
@@ -14507,13 +14538,11 @@ static int lfsr_fs_gc(lfs_t *lfs, lfsr_traversal_t *t,
|
||||
pending &= (
|
||||
(lfs->flags & (
|
||||
LFS_I_UNTIDY
|
||||
| LFS_I_UNCOMPACTED))
|
||||
| ((lfsr_fs_canlookahead(lfs)) ? LFS_GC_LOOKAHEAD : 0)
|
||||
// only consider our filesystem checked if we
|
||||
// weren't mutated
|
||||
| ((lfsr_t_isdirty(t->o.o.flags)
|
||||
|| lfsr_t_ismutated(t->o.o.flags))
|
||||
? LFS_GC_CKMETA | LFS_GC_CKDATA
|
||||
| LFS_I_UNCOMPACTED
|
||||
| LFS_I_CANCKMETA
|
||||
| LFS_I_CANCKDATA))
|
||||
| ((lfsr_fs_canlookahead(lfs))
|
||||
? LFS_GC_LOOKAHEAD
|
||||
: 0));
|
||||
}
|
||||
|
||||
@@ -14767,6 +14796,30 @@ int lfsr_gc(lfs_t *lfs) {
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef LFS_GC
|
||||
// unperform janitorial work
|
||||
int lfsr_gc_unck(lfs_t *lfs, uint32_t flags) {
|
||||
// unknown flags?
|
||||
LFS_ASSERT((flags & ~(
|
||||
LFS_I_INCONSISTENT
|
||||
| LFS_I_CANLOOKAHEAD
|
||||
| LFS_I_UNCOMPACTED
|
||||
| LFS_I_CANCKMETA
|
||||
| LFS_I_CANCKDATA)) == 0);
|
||||
|
||||
// reset the requested flags
|
||||
lfs->flags |= flags;
|
||||
|
||||
// and clear from any ongoing traversals
|
||||
//
|
||||
// lfsr_fs_gc will terminate early if it discovers it can no longer
|
||||
// make progress
|
||||
lfs->gc.t.o.o.flags &= ~flags;
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user