-

Committer:
aguscahya
Date:
Thu Apr 22 03:49:45 2021 +0000
Revision:
0:1f44439df816
-

Who changed what in which revision?

UserRevisionLine numberNew contents of line
aguscahya 0:1f44439df816 1 #include "spiffs.h"
aguscahya 0:1f44439df816 2 #include "spiffs_nucleus.h"
aguscahya 0:1f44439df816 3
aguscahya 0:1f44439df816 4 // Erases a logical block and updates the erase counter.
aguscahya 0:1f44439df816 5 // If cache is enabled, all pages that might be cached in this block
aguscahya 0:1f44439df816 6 // is dropped.
aguscahya 0:1f44439df816 7 static s32_t spiffs_gc_erase_block(
aguscahya 0:1f44439df816 8 spiffs *fs,
aguscahya 0:1f44439df816 9 spiffs_block_ix bix) {
aguscahya 0:1f44439df816 10 s32_t res;
aguscahya 0:1f44439df816 11 u32_t addr = SPIFFS_BLOCK_TO_PADDR(fs, bix);
aguscahya 0:1f44439df816 12 s32_t size = SPIFFS_CFG_LOG_BLOCK_SZ(fs);
aguscahya 0:1f44439df816 13
aguscahya 0:1f44439df816 14 SPIFFS_GC_DBG("gc: erase block %i\n", bix);
aguscahya 0:1f44439df816 15
aguscahya 0:1f44439df816 16 // here we ignore res, just try erasing the block
aguscahya 0:1f44439df816 17 while (size > 0) {
aguscahya 0:1f44439df816 18 SPIFFS_GC_DBG("gc: erase %08x:%08x\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
aguscahya 0:1f44439df816 19 (void)fs->cfg.hal_erase_f(addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
aguscahya 0:1f44439df816 20 addr += SPIFFS_CFG_PHYS_ERASE_SZ(fs);
aguscahya 0:1f44439df816 21 size -= SPIFFS_CFG_PHYS_ERASE_SZ(fs);
aguscahya 0:1f44439df816 22 }
aguscahya 0:1f44439df816 23 fs->free_blocks++;
aguscahya 0:1f44439df816 24
aguscahya 0:1f44439df816 25 // register erase count for this block
aguscahya 0:1f44439df816 26 res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0,
aguscahya 0:1f44439df816 27 SPIFFS_ERASE_COUNT_PADDR(fs, bix),
aguscahya 0:1f44439df816 28 sizeof(spiffs_obj_id), (u8_t *)&fs->max_erase_count);
aguscahya 0:1f44439df816 29 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 30
aguscahya 0:1f44439df816 31 fs->max_erase_count++;
aguscahya 0:1f44439df816 32 if (fs->max_erase_count == SPIFFS_OBJ_ID_IX_FLAG) {
aguscahya 0:1f44439df816 33 fs->max_erase_count = 0;
aguscahya 0:1f44439df816 34 }
aguscahya 0:1f44439df816 35
aguscahya 0:1f44439df816 36 #if SPIFFS_CACHE
aguscahya 0:1f44439df816 37 {
aguscahya 0:1f44439df816 38 int i;
aguscahya 0:1f44439df816 39 for (i = 0; i < SPIFFS_PAGES_PER_BLOCK(fs); i++) {
aguscahya 0:1f44439df816 40 spiffs_cache_drop_page(fs, SPIFFS_PAGE_FOR_BLOCK(fs, bix) + i);
aguscahya 0:1f44439df816 41 }
aguscahya 0:1f44439df816 42 }
aguscahya 0:1f44439df816 43 #endif
aguscahya 0:1f44439df816 44 return res;
aguscahya 0:1f44439df816 45 }
aguscahya 0:1f44439df816 46
aguscahya 0:1f44439df816 47 // Searches for blocks where all entries are deleted - if one is found,
aguscahya 0:1f44439df816 48 // the block is erased. Compared to the non-quick gc, the quick one ensures
aguscahya 0:1f44439df816 49 // that no updates are needed on existing objects on pages that are erased.
aguscahya 0:1f44439df816 50 s32_t spiffs_gc_quick(
aguscahya 0:1f44439df816 51 spiffs *fs) {
aguscahya 0:1f44439df816 52 s32_t res = SPIFFS_OK;
aguscahya 0:1f44439df816 53 u32_t blocks = fs->block_count;
aguscahya 0:1f44439df816 54 spiffs_block_ix cur_block = 0;
aguscahya 0:1f44439df816 55 u32_t cur_block_addr = 0;
aguscahya 0:1f44439df816 56 int cur_entry = 0;
aguscahya 0:1f44439df816 57 spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
aguscahya 0:1f44439df816 58
aguscahya 0:1f44439df816 59 SPIFFS_GC_DBG("gc_quick: running\n", cur_block);
aguscahya 0:1f44439df816 60 #if SPIFFS_GC_STATS
aguscahya 0:1f44439df816 61 fs->stats_gc_runs++;
aguscahya 0:1f44439df816 62 #endif
aguscahya 0:1f44439df816 63
aguscahya 0:1f44439df816 64 u32_t entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
aguscahya 0:1f44439df816 65
aguscahya 0:1f44439df816 66 // find fully deleted blocks
aguscahya 0:1f44439df816 67 // check each block
aguscahya 0:1f44439df816 68 while (res == SPIFFS_OK && blocks--) {
aguscahya 0:1f44439df816 69 u16_t deleted_pages_in_block = 0;
aguscahya 0:1f44439df816 70
aguscahya 0:1f44439df816 71 int obj_lookup_page = 0;
aguscahya 0:1f44439df816 72 // check each object lookup page
aguscahya 0:1f44439df816 73 while (res == SPIFFS_OK && obj_lookup_page < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
aguscahya 0:1f44439df816 74 int entry_offset = obj_lookup_page * entries_per_page;
aguscahya 0:1f44439df816 75 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
aguscahya 0:1f44439df816 76 0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
aguscahya 0:1f44439df816 77 // check each entry
aguscahya 0:1f44439df816 78 while (res == SPIFFS_OK &&
aguscahya 0:1f44439df816 79 cur_entry - entry_offset < entries_per_page && cur_entry < SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
aguscahya 0:1f44439df816 80 spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
aguscahya 0:1f44439df816 81 if (obj_id == SPIFFS_OBJ_ID_DELETED) {
aguscahya 0:1f44439df816 82 deleted_pages_in_block++;
aguscahya 0:1f44439df816 83 } else if (obj_id == SPIFFS_OBJ_ID_FREE) {
aguscahya 0:1f44439df816 84 // kill scan, go for next block
aguscahya 0:1f44439df816 85 obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs);
aguscahya 0:1f44439df816 86 break;
aguscahya 0:1f44439df816 87 } else {
aguscahya 0:1f44439df816 88 // kill scan, go for next block
aguscahya 0:1f44439df816 89 obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs);
aguscahya 0:1f44439df816 90 break;
aguscahya 0:1f44439df816 91 }
aguscahya 0:1f44439df816 92 cur_entry++;
aguscahya 0:1f44439df816 93 } // per entry
aguscahya 0:1f44439df816 94 obj_lookup_page++;
aguscahya 0:1f44439df816 95 } // per object lookup page
aguscahya 0:1f44439df816 96
aguscahya 0:1f44439df816 97 if (res == SPIFFS_OK && deleted_pages_in_block == SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
aguscahya 0:1f44439df816 98 // found a fully deleted block
aguscahya 0:1f44439df816 99 fs->stats_p_deleted -= deleted_pages_in_block;
aguscahya 0:1f44439df816 100 res = spiffs_gc_erase_block(fs, cur_block);
aguscahya 0:1f44439df816 101 return res;
aguscahya 0:1f44439df816 102 }
aguscahya 0:1f44439df816 103
aguscahya 0:1f44439df816 104 cur_entry = 0;
aguscahya 0:1f44439df816 105 cur_block++;
aguscahya 0:1f44439df816 106 cur_block_addr += SPIFFS_CFG_LOG_BLOCK_SZ(fs);
aguscahya 0:1f44439df816 107 } // per block
aguscahya 0:1f44439df816 108
aguscahya 0:1f44439df816 109 return res;
aguscahya 0:1f44439df816 110 }
aguscahya 0:1f44439df816 111
aguscahya 0:1f44439df816 112 // Checks if garbaga collecting is necessary. If so a candidate block is found,
aguscahya 0:1f44439df816 113 // cleansed and erased
aguscahya 0:1f44439df816 114 s32_t spiffs_gc_check(
aguscahya 0:1f44439df816 115 spiffs *fs,
aguscahya 0:1f44439df816 116 u32_t len) {
aguscahya 0:1f44439df816 117 s32_t res;
aguscahya 0:1f44439df816 118 u32_t free_pages =
aguscahya 0:1f44439df816 119 (SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * fs->block_count
aguscahya 0:1f44439df816 120 - fs->stats_p_allocated - fs->stats_p_deleted;
aguscahya 0:1f44439df816 121 int tries = 0;
aguscahya 0:1f44439df816 122
aguscahya 0:1f44439df816 123 if (fs->free_blocks > 3 &&
aguscahya 0:1f44439df816 124 len < free_pages * SPIFFS_DATA_PAGE_SIZE(fs)) {
aguscahya 0:1f44439df816 125 return SPIFFS_OK;
aguscahya 0:1f44439df816 126 }
aguscahya 0:1f44439df816 127
aguscahya 0:1f44439df816 128 //printf("gcing started %i dirty, blocks %i free, want %i bytes\n", fs->stats_p_allocated + fs->stats_p_deleted, fs->free_blocks, len);
aguscahya 0:1f44439df816 129
aguscahya 0:1f44439df816 130 do {
aguscahya 0:1f44439df816 131 SPIFFS_GC_DBG("\ngc_check #%i: run gc free_blocks:%i pfree:%i pallo:%i pdele:%i [%i] len:%i of %i\n",
aguscahya 0:1f44439df816 132 tries,
aguscahya 0:1f44439df816 133 fs->free_blocks, free_pages, fs->stats_p_allocated, fs->stats_p_deleted, (free_pages+fs->stats_p_allocated+fs->stats_p_deleted),
aguscahya 0:1f44439df816 134 len, free_pages*SPIFFS_DATA_PAGE_SIZE(fs));
aguscahya 0:1f44439df816 135
aguscahya 0:1f44439df816 136 spiffs_block_ix *cands;
aguscahya 0:1f44439df816 137 int count;
aguscahya 0:1f44439df816 138 spiffs_block_ix cand;
aguscahya 0:1f44439df816 139 res = spiffs_gc_find_candidate(fs, &cands, &count);
aguscahya 0:1f44439df816 140 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 141 if (count == 0) {
aguscahya 0:1f44439df816 142 SPIFFS_GC_DBG("gc_check: no candidates, return\n");
aguscahya 0:1f44439df816 143 return res;
aguscahya 0:1f44439df816 144 }
aguscahya 0:1f44439df816 145 #if SPIFFS_GC_STATS
aguscahya 0:1f44439df816 146 fs->stats_gc_runs++;
aguscahya 0:1f44439df816 147 #endif
aguscahya 0:1f44439df816 148 cand = cands[0];
aguscahya 0:1f44439df816 149 fs->cleaning = 1;
aguscahya 0:1f44439df816 150 //printf("gcing: cleaning block %i\n", cand);
aguscahya 0:1f44439df816 151 res = spiffs_gc_clean(fs, cand);
aguscahya 0:1f44439df816 152 fs->cleaning = 0;
aguscahya 0:1f44439df816 153 if (res < 0) {
aguscahya 0:1f44439df816 154 SPIFFS_GC_DBG("gc_check: cleaning block %i, result %i\n", cand, res);
aguscahya 0:1f44439df816 155 } else {
aguscahya 0:1f44439df816 156 SPIFFS_GC_DBG("gc_check: cleaning block %i, result %i\n", cand, res);
aguscahya 0:1f44439df816 157 }
aguscahya 0:1f44439df816 158 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 159
aguscahya 0:1f44439df816 160 res = spiffs_gc_erase_page_stats(fs, cand);
aguscahya 0:1f44439df816 161 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 162
aguscahya 0:1f44439df816 163 res = spiffs_gc_erase_block(fs, cand);
aguscahya 0:1f44439df816 164 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 165
aguscahya 0:1f44439df816 166 free_pages =
aguscahya 0:1f44439df816 167 (SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * fs->block_count
aguscahya 0:1f44439df816 168 - fs->stats_p_allocated - fs->stats_p_deleted;
aguscahya 0:1f44439df816 169
aguscahya 0:1f44439df816 170 } while (++tries < SPIFFS_GC_MAX_RUNS && (fs->free_blocks <= 2 ||
aguscahya 0:1f44439df816 171 len > free_pages*SPIFFS_DATA_PAGE_SIZE(fs)));
aguscahya 0:1f44439df816 172 SPIFFS_GC_DBG("gc_check: finished\n");
aguscahya 0:1f44439df816 173
aguscahya 0:1f44439df816 174 //printf("gcing finished %i dirty, blocks %i free, %i pages free, %i tries, res %i\n",
aguscahya 0:1f44439df816 175 // fs->stats_p_allocated + fs->stats_p_deleted,
aguscahya 0:1f44439df816 176 // fs->free_blocks, free_pages, tries, res);
aguscahya 0:1f44439df816 177
aguscahya 0:1f44439df816 178 return res;
aguscahya 0:1f44439df816 179 }
aguscahya 0:1f44439df816 180
aguscahya 0:1f44439df816 181 // Updates page statistics for a block that is about to be erased
aguscahya 0:1f44439df816 182 s32_t spiffs_gc_erase_page_stats(
aguscahya 0:1f44439df816 183 spiffs *fs,
aguscahya 0:1f44439df816 184 spiffs_block_ix bix) {
aguscahya 0:1f44439df816 185 s32_t res = SPIFFS_OK;
aguscahya 0:1f44439df816 186 int obj_lookup_page = 0;
aguscahya 0:1f44439df816 187 u32_t entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
aguscahya 0:1f44439df816 188 spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
aguscahya 0:1f44439df816 189 int cur_entry = 0;
aguscahya 0:1f44439df816 190 u32_t dele = 0;
aguscahya 0:1f44439df816 191 u32_t allo = 0;
aguscahya 0:1f44439df816 192
aguscahya 0:1f44439df816 193 // check each object lookup page
aguscahya 0:1f44439df816 194 while (res == SPIFFS_OK && obj_lookup_page < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
aguscahya 0:1f44439df816 195 int entry_offset = obj_lookup_page * entries_per_page;
aguscahya 0:1f44439df816 196 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
aguscahya 0:1f44439df816 197 0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
aguscahya 0:1f44439df816 198 // check each entry
aguscahya 0:1f44439df816 199 while (res == SPIFFS_OK &&
aguscahya 0:1f44439df816 200 cur_entry - entry_offset < entries_per_page && cur_entry < SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
aguscahya 0:1f44439df816 201 spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
aguscahya 0:1f44439df816 202 if (obj_id == SPIFFS_OBJ_ID_FREE) {
aguscahya 0:1f44439df816 203 } else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
aguscahya 0:1f44439df816 204 dele++;
aguscahya 0:1f44439df816 205 } else {
aguscahya 0:1f44439df816 206 allo++;
aguscahya 0:1f44439df816 207 }
aguscahya 0:1f44439df816 208 cur_entry++;
aguscahya 0:1f44439df816 209 } // per entry
aguscahya 0:1f44439df816 210 obj_lookup_page++;
aguscahya 0:1f44439df816 211 } // per object lookup page
aguscahya 0:1f44439df816 212 SPIFFS_GC_DBG("gc_check: wipe pallo:%i pdele:%i\n", allo, dele);
aguscahya 0:1f44439df816 213 fs->stats_p_allocated -= allo;
aguscahya 0:1f44439df816 214 fs->stats_p_deleted -= dele;
aguscahya 0:1f44439df816 215 return res;
aguscahya 0:1f44439df816 216 }
aguscahya 0:1f44439df816 217
aguscahya 0:1f44439df816 218 // Finds block candidates to erase
aguscahya 0:1f44439df816 219 s32_t spiffs_gc_find_candidate(
aguscahya 0:1f44439df816 220 spiffs *fs,
aguscahya 0:1f44439df816 221 spiffs_block_ix **block_candidates,
aguscahya 0:1f44439df816 222 int *candidate_count) {
aguscahya 0:1f44439df816 223 s32_t res = SPIFFS_OK;
aguscahya 0:1f44439df816 224 u32_t blocks = fs->block_count;
aguscahya 0:1f44439df816 225 spiffs_block_ix cur_block = 0;
aguscahya 0:1f44439df816 226 u32_t cur_block_addr = 0;
aguscahya 0:1f44439df816 227 spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
aguscahya 0:1f44439df816 228 int cur_entry = 0;
aguscahya 0:1f44439df816 229
aguscahya 0:1f44439df816 230 // using fs->work area as sorted candidate memory, (spiffs_block_ix)cand_bix/(s32_t)score
aguscahya 0:1f44439df816 231 int max_candidates = MIN(fs->block_count, (SPIFFS_CFG_LOG_PAGE_SZ(fs)-8)/(sizeof(spiffs_block_ix) + sizeof(s32_t)));
aguscahya 0:1f44439df816 232 *candidate_count = 0;
aguscahya 0:1f44439df816 233 memset(fs->work, 0xff, SPIFFS_CFG_LOG_PAGE_SZ(fs));
aguscahya 0:1f44439df816 234
aguscahya 0:1f44439df816 235 // divide up work area into block indices and scores
aguscahya 0:1f44439df816 236 // todo alignment?
aguscahya 0:1f44439df816 237 spiffs_block_ix *cand_blocks = (spiffs_block_ix *)fs->work;
aguscahya 0:1f44439df816 238 s32_t *cand_scores = (s32_t *)(fs->work + max_candidates * sizeof(spiffs_block_ix));
aguscahya 0:1f44439df816 239
aguscahya 0:1f44439df816 240 *block_candidates = cand_blocks;
aguscahya 0:1f44439df816 241
aguscahya 0:1f44439df816 242 u32_t entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
aguscahya 0:1f44439df816 243
aguscahya 0:1f44439df816 244 // check each block
aguscahya 0:1f44439df816 245 while (res == SPIFFS_OK && blocks--) {
aguscahya 0:1f44439df816 246 u16_t deleted_pages_in_block = 0;
aguscahya 0:1f44439df816 247 u16_t used_pages_in_block = 0;
aguscahya 0:1f44439df816 248
aguscahya 0:1f44439df816 249 int obj_lookup_page = 0;
aguscahya 0:1f44439df816 250 // check each object lookup page
aguscahya 0:1f44439df816 251 while (res == SPIFFS_OK && obj_lookup_page < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
aguscahya 0:1f44439df816 252 int entry_offset = obj_lookup_page * entries_per_page;
aguscahya 0:1f44439df816 253 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
aguscahya 0:1f44439df816 254 0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
aguscahya 0:1f44439df816 255 // check each entry
aguscahya 0:1f44439df816 256 while (res == SPIFFS_OK &&
aguscahya 0:1f44439df816 257 cur_entry - entry_offset < entries_per_page && cur_entry < SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
aguscahya 0:1f44439df816 258 spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
aguscahya 0:1f44439df816 259 if (obj_id == SPIFFS_OBJ_ID_FREE) {
aguscahya 0:1f44439df816 260 // when a free entry is encountered, scan logic ensures that all following entries are free also
aguscahya 0:1f44439df816 261 break;
aguscahya 0:1f44439df816 262 } else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
aguscahya 0:1f44439df816 263 deleted_pages_in_block++;
aguscahya 0:1f44439df816 264 } else {
aguscahya 0:1f44439df816 265 used_pages_in_block++;
aguscahya 0:1f44439df816 266 }
aguscahya 0:1f44439df816 267 cur_entry++;
aguscahya 0:1f44439df816 268 } // per entry
aguscahya 0:1f44439df816 269 obj_lookup_page++;
aguscahya 0:1f44439df816 270 } // per object lookup page
aguscahya 0:1f44439df816 271
aguscahya 0:1f44439df816 272 // calculate score and insert into candidate table
aguscahya 0:1f44439df816 273 // stoneage sort, but probably not so many blocks
aguscahya 0:1f44439df816 274 if (res == SPIFFS_OK && deleted_pages_in_block > 0) {
aguscahya 0:1f44439df816 275 // read erase count
aguscahya 0:1f44439df816 276 spiffs_obj_id erase_count;
aguscahya 0:1f44439df816 277 res = _spiffs_rd(fs, SPIFFS_OP_C_READ | SPIFFS_OP_T_OBJ_LU2, 0,
aguscahya 0:1f44439df816 278 SPIFFS_ERASE_COUNT_PADDR(fs, cur_block),
aguscahya 0:1f44439df816 279 sizeof(spiffs_obj_id), (u8_t *)&erase_count);
aguscahya 0:1f44439df816 280 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 281
aguscahya 0:1f44439df816 282 spiffs_obj_id erase_age;
aguscahya 0:1f44439df816 283 if (fs->max_erase_count > erase_count) {
aguscahya 0:1f44439df816 284 erase_age = fs->max_erase_count - erase_count;
aguscahya 0:1f44439df816 285 } else {
aguscahya 0:1f44439df816 286 erase_age = SPIFFS_OBJ_ID_FREE - (erase_count - fs->max_erase_count);
aguscahya 0:1f44439df816 287 }
aguscahya 0:1f44439df816 288
aguscahya 0:1f44439df816 289 s32_t score =
aguscahya 0:1f44439df816 290 deleted_pages_in_block * SPIFFS_GC_HEUR_W_DELET +
aguscahya 0:1f44439df816 291 used_pages_in_block * SPIFFS_GC_HEUR_W_USED +
aguscahya 0:1f44439df816 292 erase_age * SPIFFS_GC_HEUR_W_ERASE_AGE;
aguscahya 0:1f44439df816 293 int cand_ix = 0;
aguscahya 0:1f44439df816 294 SPIFFS_GC_DBG("gc_check: bix:%i del:%i use:%i score:%i\n", cur_block, deleted_pages_in_block, used_pages_in_block, score);
aguscahya 0:1f44439df816 295 while (cand_ix < max_candidates) {
aguscahya 0:1f44439df816 296 if (cand_blocks[cand_ix] == (spiffs_block_ix)-1) {
aguscahya 0:1f44439df816 297 cand_blocks[cand_ix] = cur_block;
aguscahya 0:1f44439df816 298 cand_scores[cand_ix] = score;
aguscahya 0:1f44439df816 299 break;
aguscahya 0:1f44439df816 300 } else if (cand_scores[cand_ix] < score) {
aguscahya 0:1f44439df816 301 int reorder_cand_ix = max_candidates - 2;
aguscahya 0:1f44439df816 302 while (reorder_cand_ix >= cand_ix) {
aguscahya 0:1f44439df816 303 cand_blocks[reorder_cand_ix + 1] = cand_blocks[reorder_cand_ix];
aguscahya 0:1f44439df816 304 cand_scores[reorder_cand_ix + 1] = cand_scores[reorder_cand_ix];
aguscahya 0:1f44439df816 305 reorder_cand_ix--;
aguscahya 0:1f44439df816 306 }
aguscahya 0:1f44439df816 307 cand_blocks[cand_ix] = cur_block;
aguscahya 0:1f44439df816 308 cand_scores[cand_ix] = score;
aguscahya 0:1f44439df816 309 break;
aguscahya 0:1f44439df816 310 }
aguscahya 0:1f44439df816 311 cand_ix++;
aguscahya 0:1f44439df816 312 }
aguscahya 0:1f44439df816 313 (*candidate_count)++;
aguscahya 0:1f44439df816 314 }
aguscahya 0:1f44439df816 315
aguscahya 0:1f44439df816 316 cur_entry = 0;
aguscahya 0:1f44439df816 317 cur_block++;
aguscahya 0:1f44439df816 318 cur_block_addr += SPIFFS_CFG_LOG_BLOCK_SZ(fs);
aguscahya 0:1f44439df816 319 } // per block
aguscahya 0:1f44439df816 320
aguscahya 0:1f44439df816 321 return res;
aguscahya 0:1f44439df816 322 }
aguscahya 0:1f44439df816 323
aguscahya 0:1f44439df816 324 typedef enum {
aguscahya 0:1f44439df816 325 FIND_OBJ_DATA,
aguscahya 0:1f44439df816 326 MOVE_OBJ_DATA,
aguscahya 0:1f44439df816 327 MOVE_OBJ_IX,
aguscahya 0:1f44439df816 328 FINISHED
aguscahya 0:1f44439df816 329 } spiffs_gc_clean_state;
aguscahya 0:1f44439df816 330
aguscahya 0:1f44439df816 331 typedef struct {
aguscahya 0:1f44439df816 332 spiffs_gc_clean_state state;
aguscahya 0:1f44439df816 333 spiffs_obj_id cur_obj_id;
aguscahya 0:1f44439df816 334 spiffs_span_ix cur_objix_spix;
aguscahya 0:1f44439df816 335 spiffs_page_ix cur_objix_pix;
aguscahya 0:1f44439df816 336 int stored_scan_entry_index;
aguscahya 0:1f44439df816 337 u8_t obj_id_found;
aguscahya 0:1f44439df816 338 } spiffs_gc;
aguscahya 0:1f44439df816 339
aguscahya 0:1f44439df816 340 // Empties given block by moving all data into free pages of another block
aguscahya 0:1f44439df816 341 // Strategy:
aguscahya 0:1f44439df816 342 // loop:
aguscahya 0:1f44439df816 343 // scan object lookup for object data pages
aguscahya 0:1f44439df816 344 // for first found id, check spix and load corresponding object index page to memory
aguscahya 0:1f44439df816 345 // push object scan lookup entry index
aguscahya 0:1f44439df816 346 // rescan object lookup, find data pages with same id and referenced by same object index
aguscahya 0:1f44439df816 347 // move data page, update object index in memory
aguscahya 0:1f44439df816 348 // when reached end of lookup, store updated object index
aguscahya 0:1f44439df816 349 // pop object scan lookup entry index
aguscahya 0:1f44439df816 350 // repeat loop until end of object lookup
aguscahya 0:1f44439df816 351 // scan object lookup again for remaining object index pages, move to new page in other block
aguscahya 0:1f44439df816 352 //
aguscahya 0:1f44439df816 353 s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
aguscahya 0:1f44439df816 354 s32_t res = SPIFFS_OK;
aguscahya 0:1f44439df816 355 u32_t entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
aguscahya 0:1f44439df816 356 int cur_entry = 0;
aguscahya 0:1f44439df816 357 spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
aguscahya 0:1f44439df816 358 spiffs_gc gc;
aguscahya 0:1f44439df816 359 spiffs_page_ix cur_pix = 0;
aguscahya 0:1f44439df816 360 spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
aguscahya 0:1f44439df816 361 spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
aguscahya 0:1f44439df816 362
aguscahya 0:1f44439df816 363 SPIFFS_GC_DBG("gc_clean: cleaning block %i\n", bix);
aguscahya 0:1f44439df816 364
aguscahya 0:1f44439df816 365 memset(&gc, 0, sizeof(spiffs_gc));
aguscahya 0:1f44439df816 366 gc.state = FIND_OBJ_DATA;
aguscahya 0:1f44439df816 367
aguscahya 0:1f44439df816 368 if (fs->free_cursor_block_ix == bix) {
aguscahya 0:1f44439df816 369 // move free cursor to next block, cannot use free pages from the block we want to clean
aguscahya 0:1f44439df816 370 fs->free_cursor_block_ix = (bix+1)%fs->block_count;
aguscahya 0:1f44439df816 371 fs->free_cursor_obj_lu_entry = 0;
aguscahya 0:1f44439df816 372 SPIFFS_GC_DBG("gc_clean: move free cursor to block %i\n", fs->free_cursor_block_ix);
aguscahya 0:1f44439df816 373 }
aguscahya 0:1f44439df816 374
aguscahya 0:1f44439df816 375 while (res == SPIFFS_OK && gc.state != FINISHED) {
aguscahya 0:1f44439df816 376 SPIFFS_GC_DBG("gc_clean: state = %i entry:%i\n", gc.state, cur_entry);
aguscahya 0:1f44439df816 377 gc.obj_id_found = 0;
aguscahya 0:1f44439df816 378
aguscahya 0:1f44439df816 379 // scan through lookup pages
aguscahya 0:1f44439df816 380 int obj_lookup_page = cur_entry / entries_per_page;
aguscahya 0:1f44439df816 381 u8_t scan = 1;
aguscahya 0:1f44439df816 382 // check each object lookup page
aguscahya 0:1f44439df816 383 while (scan && res == SPIFFS_OK && obj_lookup_page < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
aguscahya 0:1f44439df816 384 int entry_offset = obj_lookup_page * entries_per_page;
aguscahya 0:1f44439df816 385 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
aguscahya 0:1f44439df816 386 0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page),
aguscahya 0:1f44439df816 387 SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
aguscahya 0:1f44439df816 388 // check each entry
aguscahya 0:1f44439df816 389 while (scan && res == SPIFFS_OK &&
aguscahya 0:1f44439df816 390 cur_entry - entry_offset < entries_per_page && cur_entry < SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
aguscahya 0:1f44439df816 391 spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
aguscahya 0:1f44439df816 392 cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, cur_entry);
aguscahya 0:1f44439df816 393
aguscahya 0:1f44439df816 394 // act upon object id depending on gc state
aguscahya 0:1f44439df816 395 switch (gc.state) {
aguscahya 0:1f44439df816 396 case FIND_OBJ_DATA:
aguscahya 0:1f44439df816 397 if (obj_id != SPIFFS_OBJ_ID_DELETED && obj_id != SPIFFS_OBJ_ID_FREE &&
aguscahya 0:1f44439df816 398 ((obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0)) {
aguscahya 0:1f44439df816 399 SPIFFS_GC_DBG("gc_clean: FIND_DATA state:%i - found obj id %04x\n", gc.state, obj_id);
aguscahya 0:1f44439df816 400 gc.obj_id_found = 1;
aguscahya 0:1f44439df816 401 gc.cur_obj_id = obj_id;
aguscahya 0:1f44439df816 402 scan = 0;
aguscahya 0:1f44439df816 403 }
aguscahya 0:1f44439df816 404 break;
aguscahya 0:1f44439df816 405 case MOVE_OBJ_DATA:
aguscahya 0:1f44439df816 406 if (obj_id == gc.cur_obj_id) {
aguscahya 0:1f44439df816 407 spiffs_page_header p_hdr;
aguscahya 0:1f44439df816 408 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
aguscahya 0:1f44439df816 409 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
aguscahya 0:1f44439df816 410 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 411 SPIFFS_GC_DBG("gc_clean: MOVE_DATA found data page %04x:%04x @ %04x\n", gc.cur_obj_id, p_hdr.span_ix, cur_pix);
aguscahya 0:1f44439df816 412 if (SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, p_hdr.span_ix) != gc.cur_objix_spix) {
aguscahya 0:1f44439df816 413 SPIFFS_GC_DBG("gc_clean: MOVE_DATA no objix spix match, take in another run\n");
aguscahya 0:1f44439df816 414 } else {
aguscahya 0:1f44439df816 415 spiffs_page_ix new_data_pix;
aguscahya 0:1f44439df816 416 if (p_hdr.flags & SPIFFS_PH_FLAG_DELET) {
aguscahya 0:1f44439df816 417 // move page
aguscahya 0:1f44439df816 418 res = spiffs_page_move(fs, 0, 0, obj_id, &p_hdr, cur_pix, &new_data_pix);
aguscahya 0:1f44439df816 419 SPIFFS_GC_DBG("gc_clean: MOVE_DATA move objix %04x:%04x page %04x to %04x\n", gc.cur_obj_id, p_hdr.span_ix, cur_pix, new_data_pix);
aguscahya 0:1f44439df816 420 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 421 // move wipes obj_lu, reload it
aguscahya 0:1f44439df816 422 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
aguscahya 0:1f44439df816 423 0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page),
aguscahya 0:1f44439df816 424 SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
aguscahya 0:1f44439df816 425 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 426 } else {
aguscahya 0:1f44439df816 427 // page is deleted but not deleted in lookup, scrap it
aguscahya 0:1f44439df816 428 SPIFFS_GC_DBG("gc_clean: MOVE_DATA wipe objix %04x:%04x page %04x\n", obj_id, p_hdr.span_ix, cur_pix);
aguscahya 0:1f44439df816 429 res = spiffs_page_delete(fs, cur_pix);
aguscahya 0:1f44439df816 430 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 431 new_data_pix = SPIFFS_OBJ_ID_FREE;
aguscahya 0:1f44439df816 432 }
aguscahya 0:1f44439df816 433 // update memory representation of object index page with new data page
aguscahya 0:1f44439df816 434 if (gc.cur_objix_spix == 0) {
aguscahya 0:1f44439df816 435 // update object index header page
aguscahya 0:1f44439df816 436 ((spiffs_page_ix*)((u8_t*)objix_hdr + sizeof(spiffs_page_object_ix_header)))[p_hdr.span_ix] = new_data_pix;
aguscahya 0:1f44439df816 437 SPIFFS_GC_DBG("gc_clean: MOVE_DATA wrote page %04x to objix_hdr entry %02x in mem\n", new_data_pix, SPIFFS_OBJ_IX_ENTRY(fs, p_hdr.span_ix));
aguscahya 0:1f44439df816 438 } else {
aguscahya 0:1f44439df816 439 // update object index page
aguscahya 0:1f44439df816 440 ((spiffs_page_ix*)((u8_t*)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, p_hdr.span_ix)] = new_data_pix;
aguscahya 0:1f44439df816 441 SPIFFS_GC_DBG("gc_clean: MOVE_DATA wrote page %04x to objix entry %02x in mem\n", new_data_pix, SPIFFS_OBJ_IX_ENTRY(fs, p_hdr.span_ix));
aguscahya 0:1f44439df816 442 }
aguscahya 0:1f44439df816 443 }
aguscahya 0:1f44439df816 444 }
aguscahya 0:1f44439df816 445 break;
aguscahya 0:1f44439df816 446 case MOVE_OBJ_IX:
aguscahya 0:1f44439df816 447 if (obj_id != SPIFFS_OBJ_ID_DELETED && obj_id != SPIFFS_OBJ_ID_FREE &&
aguscahya 0:1f44439df816 448 (obj_id & SPIFFS_OBJ_ID_IX_FLAG)) {
aguscahya 0:1f44439df816 449 // found an index object id
aguscahya 0:1f44439df816 450 spiffs_page_header p_hdr;
aguscahya 0:1f44439df816 451 spiffs_page_ix new_pix;
aguscahya 0:1f44439df816 452 // load header
aguscahya 0:1f44439df816 453 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
aguscahya 0:1f44439df816 454 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
aguscahya 0:1f44439df816 455 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 456 if (p_hdr.flags & SPIFFS_PH_FLAG_DELET) {
aguscahya 0:1f44439df816 457 // move page
aguscahya 0:1f44439df816 458 res = spiffs_page_move(fs, 0, 0, obj_id, &p_hdr, cur_pix, &new_pix);
aguscahya 0:1f44439df816 459 SPIFFS_GC_DBG("gc_clean: MOVE_OBJIX move objix %04x:%04x page %04x to %04x\n", obj_id, p_hdr.span_ix, cur_pix, new_pix);
aguscahya 0:1f44439df816 460 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 461 spiffs_cb_object_event(fs, 0, SPIFFS_EV_IX_UPD, obj_id, p_hdr.span_ix, new_pix, 0);
aguscahya 0:1f44439df816 462 // move wipes obj_lu, reload it
aguscahya 0:1f44439df816 463 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
aguscahya 0:1f44439df816 464 0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page),
aguscahya 0:1f44439df816 465 SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
aguscahya 0:1f44439df816 466 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 467 } else {
aguscahya 0:1f44439df816 468 // page is deleted but not deleted in lookup, scrap it
aguscahya 0:1f44439df816 469 SPIFFS_GC_DBG("gc_clean: MOVE_OBJIX wipe objix %04x:%04x page %04x\n", obj_id, p_hdr.span_ix, cur_pix);
aguscahya 0:1f44439df816 470 res = spiffs_page_delete(fs, cur_pix);
aguscahya 0:1f44439df816 471 if (res == SPIFFS_OK) {
aguscahya 0:1f44439df816 472 spiffs_cb_object_event(fs, 0, SPIFFS_EV_IX_DEL, obj_id, p_hdr.span_ix, cur_pix, 0);
aguscahya 0:1f44439df816 473 }
aguscahya 0:1f44439df816 474 }
aguscahya 0:1f44439df816 475 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 476 }
aguscahya 0:1f44439df816 477 break;
aguscahya 0:1f44439df816 478 default:
aguscahya 0:1f44439df816 479 scan = 0;
aguscahya 0:1f44439df816 480 break;
aguscahya 0:1f44439df816 481 }
aguscahya 0:1f44439df816 482 cur_entry++;
aguscahya 0:1f44439df816 483 } // per entry
aguscahya 0:1f44439df816 484 obj_lookup_page++;
aguscahya 0:1f44439df816 485 } // per object lookup page
aguscahya 0:1f44439df816 486
aguscahya 0:1f44439df816 487 if (res != SPIFFS_OK) break;
aguscahya 0:1f44439df816 488
aguscahya 0:1f44439df816 489 // state finalization and switch
aguscahya 0:1f44439df816 490 switch (gc.state) {
aguscahya 0:1f44439df816 491 case FIND_OBJ_DATA:
aguscahya 0:1f44439df816 492 if (gc.obj_id_found) {
aguscahya 0:1f44439df816 493 // find out corresponding obj ix page and load it to memory
aguscahya 0:1f44439df816 494 spiffs_page_header p_hdr;
aguscahya 0:1f44439df816 495 spiffs_page_ix objix_pix;
aguscahya 0:1f44439df816 496 gc.stored_scan_entry_index = cur_entry;
aguscahya 0:1f44439df816 497 cur_entry = 0;
aguscahya 0:1f44439df816 498 gc.state = MOVE_OBJ_DATA;
aguscahya 0:1f44439df816 499 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
aguscahya 0:1f44439df816 500 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
aguscahya 0:1f44439df816 501 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 502 gc.cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, p_hdr.span_ix);
aguscahya 0:1f44439df816 503 SPIFFS_GC_DBG("gc_clean: FIND_DATA find objix span_ix:%04x\n", gc.cur_objix_spix);
aguscahya 0:1f44439df816 504 res = spiffs_obj_lu_find_id_and_span(fs, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, gc.cur_objix_spix, 0, &objix_pix);
aguscahya 0:1f44439df816 505 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 506 SPIFFS_GC_DBG("gc_clean: FIND_DATA found object index at page %04x\n", objix_pix);
aguscahya 0:1f44439df816 507 res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
aguscahya 0:1f44439df816 508 0, SPIFFS_PAGE_TO_PADDR(fs, objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
aguscahya 0:1f44439df816 509 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 510 SPIFFS_VALIDATE_OBJIX(objix->p_hdr, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, gc.cur_objix_spix);
aguscahya 0:1f44439df816 511 gc.cur_objix_pix = objix_pix;
aguscahya 0:1f44439df816 512 } else {
aguscahya 0:1f44439df816 513 gc.state = MOVE_OBJ_IX;
aguscahya 0:1f44439df816 514 cur_entry = 0; // restart entry scan index
aguscahya 0:1f44439df816 515 }
aguscahya 0:1f44439df816 516 break;
aguscahya 0:1f44439df816 517 case MOVE_OBJ_DATA: {
aguscahya 0:1f44439df816 518 // store modified objix (hdr) page
aguscahya 0:1f44439df816 519 spiffs_page_ix new_objix_pix;
aguscahya 0:1f44439df816 520 gc.state = FIND_OBJ_DATA;
aguscahya 0:1f44439df816 521 cur_entry = gc.stored_scan_entry_index;
aguscahya 0:1f44439df816 522 if (gc.cur_objix_spix == 0) {
aguscahya 0:1f44439df816 523 // store object index header page
aguscahya 0:1f44439df816 524 res = spiffs_object_update_index_hdr(fs, 0, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, gc.cur_objix_pix, fs->work, 0, 0, &new_objix_pix);
aguscahya 0:1f44439df816 525 SPIFFS_GC_DBG("gc_clean: MOVE_DATA store modified objix_hdr page, %04x:%04x\n", new_objix_pix, 0);
aguscahya 0:1f44439df816 526 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 527 } else {
aguscahya 0:1f44439df816 528 // store object index page
aguscahya 0:1f44439df816 529 spiffs_page_ix new_objix_pix;
aguscahya 0:1f44439df816 530 res = spiffs_page_move(fs, 0, fs->work, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, gc.cur_objix_pix, &new_objix_pix);
aguscahya 0:1f44439df816 531 SPIFFS_GC_DBG("gc_clean: MOVE_DATA store modified objix page, %04x:%04x\n", new_objix_pix, objix->p_hdr.span_ix);
aguscahya 0:1f44439df816 532 SPIFFS_CHECK_RES(res);
aguscahya 0:1f44439df816 533 spiffs_cb_object_event(fs, 0, SPIFFS_EV_IX_UPD, gc.cur_obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
aguscahya 0:1f44439df816 534 }
aguscahya 0:1f44439df816 535 }
aguscahya 0:1f44439df816 536 break;
aguscahya 0:1f44439df816 537 case MOVE_OBJ_IX:
aguscahya 0:1f44439df816 538 gc.state = FINISHED;
aguscahya 0:1f44439df816 539 break;
aguscahya 0:1f44439df816 540 default:
aguscahya 0:1f44439df816 541 cur_entry = 0;
aguscahya 0:1f44439df816 542 break;
aguscahya 0:1f44439df816 543 }
aguscahya 0:1f44439df816 544 SPIFFS_GC_DBG("gc_clean: state-> %i\n", gc.state);
aguscahya 0:1f44439df816 545 } // while state != FINISHED
aguscahya 0:1f44439df816 546
aguscahya 0:1f44439df816 547
aguscahya 0:1f44439df816 548 return res;
aguscahya 0:1f44439df816 549 }