diff --git a/lfs3.c b/lfs3.c index 0bc3d86a..cc30d38c 100644 --- a/lfs3.c +++ b/lfs3.c @@ -7449,7 +7449,7 @@ static inline void lfs3_t_settstate(uint32_t *flags, uint8_t tstate) { } static inline uint8_t lfs3_t_btype(uint32_t flags) { - return (flags >> 20) & 0x0f; + return (flags >> 20) & 0x7; } static inline uint32_t lfs3_t_btypeflags(uint8_t btype) { @@ -7472,6 +7472,10 @@ static inline bool lfs3_t_isckpointed(uint32_t flags) { return flags & LFS3_t_CKPOINTED; } +static inline bool lfs3_t_isnospc(uint32_t flags) { + return flags & LFS3_t_NOSPC; +} + // mount flags static inline bool lfs3_m_isrdonly(uint32_t flags) { (void)flags; @@ -10668,10 +10672,19 @@ static lfs3_stag_t lfs3_mtree_gc(lfs3_t *lfs3, lfs3_mgc_t *mgc, // erased/bad info and (2) try to best use any available // erased-state int err = lfs3_alloc_zerogbmap(lfs3, &mgc->gbmap_); - if (err) { + if (err && err != LFS3_ERR_NOSPC) { return err; } + // not having enough space isn't really an error + if (err == LFS3_ERR_NOSPC) { + LFS3_WARN("Not enough space for gbmap " + "(lookahead %"PRId32"/%"PRId32")", + lfs3->lookahead.known, + lfs3->block_count); + mgc->t.b.h.flags |= LFS3_t_NOSPC; + } + // keep our own ckpointed flag clear mgc->t.b.h.flags &= ~LFS3_t_CKPOINTED; } @@ -10708,10 +10721,19 @@ dropped:; && !lfs3_t_isckpointed(mgc->t.b.h.flags)) { int err = lfs3_gbmap_markbptr(lfs3, &mgc->gbmap_, tag, bptr_, LFS3_TAG_BMINUSE); - if (err) { + if (err && err != LFS3_ERR_NOSPC) { return err; } + // not having enough space isn't really an error + if (err == LFS3_ERR_NOSPC) { + LFS3_WARN("Not enough space for gbmap " + "(lookahead %"PRId32"/%"PRId32")", + lfs3->lookahead.known, + lfs3->block_count); + mgc->t.b.h.flags |= LFS3_t_NOSPC; + } + // keep our own ckpointed flag clear mgc->t.b.h.flags &= ~LFS3_t_CKPOINTED; } @@ -10724,9 +10746,19 @@ dropped:; lfs3_mdir_t *mdir = (lfs3_mdir_t*)bptr_->d.u.buffer; uint32_t dirty = mgc->t.b.h.flags; int err = lfs3_mdir_mkconsistent(lfs3, mdir); - if (err) { + if (err && err != LFS3_ERR_NOSPC) { return err; } + + // not having enough space isn't really an error + if (err == LFS3_ERR_NOSPC) { + LFS3_WARN("Not enough space for mkconsistent " + "(lookahead %"PRId32"/%"PRId32")", + lfs3->lookahead.known, + lfs3->block_count); + mgc->t.b.h.flags |= LFS3_t_NOSPC; + } + // reset dirty flag mgc->t.b.h.flags &= ~LFS3_t_DIRTY | dirty; // make sure we clear any zombie flags @@ -10763,9 +10795,19 @@ dropped:; // compact the mdir uint32_t dirty = mgc->t.b.h.flags; int err = lfs3_mdir_compact(lfs3, mdir); - if (err) { + if (err && err != LFS3_ERR_NOSPC) { return err; } + + // not having enough space isn't really an error + if (err == LFS3_ERR_NOSPC) { + LFS3_WARN("Not enough space for compactmeta " + "(lookahead %"PRId32"/%"PRId32")", + lfs3->lookahead.known, + lfs3->block_count); + mgc->t.b.h.flags |= LFS3_t_NOSPC; + } + // reset dirty flag mgc->t.b.h.flags &= ~LFS3_t_DIRTY | dirty; } @@ -10790,21 +10832,24 @@ eot:; && lfs3_f_isgbmap(lfs3->flags) && lfs3_t_isrepopgbmap(lfs3->flags) && !lfs3_t_ismtreeonly(mgc->t.b.h.flags) - && !lfs3_t_isckpointed(mgc->t.b.h.flags)) { + && !lfs3_t_isckpointed(mgc->t.b.h.flags) + && !lfs3_t_isnospc(mgc->t.b.h.flags)) { lfs3_alloc_adoptgbmap(lfs3, &mgc->gbmap_, lfs3->lookahead.ckpoint); } #endif // was mkconsistent successful? if (lfs3_t_ismkconsistent(mgc->t.b.h.flags) - && !lfs3_t_isdirty(mgc->t.b.h.flags)) { + && !lfs3_t_isdirty(mgc->t.b.h.flags) + && !lfs3_t_isnospc(mgc->t.b.h.flags)) { lfs3->flags &= ~LFS3_I_MKCONSISTENT; } // was compaction successful? note we may need multiple passes if // we want to be sure everything is compacted if (lfs3_t_compactmeta(mgc->t.b.h.flags) - && !lfs3_t_ismutated(mgc->t.b.h.flags)) { + && !lfs3_t_ismutated(mgc->t.b.h.flags) + && !lfs3_t_isnospc(mgc->t.b.h.flags)) { lfs3->flags &= ~LFS3_I_COMPACTMETA; } #endif diff --git a/lfs3.h b/lfs3.h index 447979c0..4f3d09e4 100644 --- a/lfs3.h +++ b/lfs3.h @@ -342,12 +342,13 @@ enum lfs3_btype { // internally used flags, don't use these #define LFS3_t_TYPE 0xf0000000 // The traversal's type #define LFS3_t_TSTATE 0x000f0000 // The current traversal state -#define LFS3_t_BTYPE 0x00f00000 // The current block type +#define LFS3_t_BTYPE 0x00700000 // The current block type #define LFS3_t_ZOMBIE 0x08000000 // File has been removed #define LFS3_t_DIRTY 0x04000000 // Filesystem modified outside traversal #define LFS3_t_MUTATED 0x02000000 // Filesystem modified during traversal #define LFS3_t_CKPOINTED \ 0x01000000 // Filesystem ckpointed during traversal +#define LFS3_t_NOSPC 0x00800000 // Optional gc work ran out of space // GC flags #ifndef LFS3_RDONLY diff --git a/scripts/dbgflags.py b/scripts/dbgflags.py index d0357591..a8463754 100755 --- a/scripts/dbgflags.py +++ b/scripts/dbgflags.py @@ -165,7 +165,7 @@ FLAGS = [ ('^_GBMAP', 0x00080000, "Tstate = gbmap" ), ('^_GBMAP_P', 0x00090000, "Tstate = gbmap_p" ), ('^_DONE', 0x000a0000, "Tstate = done" ), - ('t_BTYPE', 0x00f00000, "The current block type" ), + ('t_BTYPE', 0x00700000, "The current block type" ), ('^_MDIR', 0x00100000, "Btype = mdir" ), ('^_BTREE', 0x00200000, "Btype = btree" ), ('^_DATA', 0x00300000, "Btype = data" ), @@ -173,6 +173,7 @@ FLAGS = [ ('t_DIRTY', 0x04000000, "Filesystem modified outside traversal" ), ('t_MUTATED', 0x02000000, "Filesystem modified during traversal" ), ('t_CKPOINTED', 0x01000000, "Filesystem ckpointed during traversal" ), + ('t_NOSPC', 0x00800000, "Optional gc work ran out of space" ), # Block allocator flags ('alloc_ERASE', 0x00000001, "Please erase the block" ),