Filesystem library designed for flash devices

Dependents:   flash-fs-example Dragonfly_Filesystem_Example STM32F407VET6_SPIFlash Dragonfly_Filesystem_Example_mbed_5

Committer:
Leon Lindenfelser
Date:
Fri Jun 26 14:21:17 2020 -0500
Revision:
4:7a3c79b0d570
Parent:
2:de478b250060
Update to latest from Multitech git repo

1. Change "errno" to "err_code" to address ARM compiler errors
2. Feature: add move file support

Who changed what in which revision?

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