Filesystem library designed for flash devices
Dependents: flash-fs-example Dragonfly_Filesystem_Example STM32F407VET6_SPIFlash Dragonfly_Filesystem_Example_mbed_5
spiffs_check.c@0:bb4e812f7c97, 2014-12-16 (annotated)
- Committer:
- mfiore
- Date:
- Tue Dec 16 15:13:10 2014 +0000
- Revision:
- 0:bb4e812f7c97
- Child:
- 2:de478b250060
first commit
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
mfiore | 0:bb4e812f7c97 | 1 | /* |
mfiore | 0:bb4e812f7c97 | 2 | * spiffs_check.c |
mfiore | 0:bb4e812f7c97 | 3 | * |
mfiore | 0:bb4e812f7c97 | 4 | * Contains functionality for checking file system consistency |
mfiore | 0:bb4e812f7c97 | 5 | * and mending problems. |
mfiore | 0:bb4e812f7c97 | 6 | * Three levels of consistency checks are implemented: |
mfiore | 0:bb4e812f7c97 | 7 | * |
mfiore | 0:bb4e812f7c97 | 8 | * Look up consistency |
mfiore | 0:bb4e812f7c97 | 9 | * Checks if indices in lookup pages are coherent with page headers |
mfiore | 0:bb4e812f7c97 | 10 | * Object index consistency |
mfiore | 0:bb4e812f7c97 | 11 | * Checks if there are any orphaned object indices (missing object index headers). |
mfiore | 0:bb4e812f7c97 | 12 | * If an object index is found but not its header, the object index is deleted. |
mfiore | 0:bb4e812f7c97 | 13 | * This is critical for the following page consistency check. |
mfiore | 0:bb4e812f7c97 | 14 | * Page consistency |
mfiore | 0:bb4e812f7c97 | 15 | * Checks for pages that ought to be indexed, ought not to be indexed, are multiple indexed |
mfiore | 0:bb4e812f7c97 | 16 | * |
mfiore | 0:bb4e812f7c97 | 17 | * |
mfiore | 0:bb4e812f7c97 | 18 | * Created on: Jul 7, 2013 |
mfiore | 0:bb4e812f7c97 | 19 | * Author: petera |
mfiore | 0:bb4e812f7c97 | 20 | */ |
mfiore | 0:bb4e812f7c97 | 21 | |
mfiore | 0:bb4e812f7c97 | 22 | #include "spiffs.h" |
mfiore | 0:bb4e812f7c97 | 23 | #include "spiffs_nucleus.h" |
mfiore | 0:bb4e812f7c97 | 24 | |
mfiore | 0:bb4e812f7c97 | 25 | //--------------------------------------- |
mfiore | 0:bb4e812f7c97 | 26 | // Look up consistency |
mfiore | 0:bb4e812f7c97 | 27 | |
mfiore | 0:bb4e812f7c97 | 28 | // searches in the object indices and returns the referenced page index given |
mfiore | 0:bb4e812f7c97 | 29 | // the object id and the data span index |
mfiore | 0:bb4e812f7c97 | 30 | // destroys fs->lu_work |
mfiore | 0:bb4e812f7c97 | 31 | static s32_t spiffs_object_get_data_page_index_reference( |
mfiore | 0:bb4e812f7c97 | 32 | spiffs *fs, |
mfiore | 0:bb4e812f7c97 | 33 | spiffs_obj_id obj_id, |
mfiore | 0:bb4e812f7c97 | 34 | spiffs_span_ix data_spix, |
mfiore | 0:bb4e812f7c97 | 35 | spiffs_page_ix *pix, |
mfiore | 0:bb4e812f7c97 | 36 | spiffs_page_ix *objix_pix) { |
mfiore | 0:bb4e812f7c97 | 37 | s32_t res; |
mfiore | 0:bb4e812f7c97 | 38 | |
mfiore | 0:bb4e812f7c97 | 39 | // calculate object index span index for given data page span index |
mfiore | 0:bb4e812f7c97 | 40 | spiffs_span_ix objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix); |
mfiore | 0:bb4e812f7c97 | 41 | |
mfiore | 0:bb4e812f7c97 | 42 | // find obj index for obj id and span index |
mfiore | 0:bb4e812f7c97 | 43 | res = spiffs_obj_lu_find_id_and_span(fs, obj_id | SPIFFS_OBJ_ID_IX_FLAG, objix_spix, 0, objix_pix); |
mfiore | 0:bb4e812f7c97 | 44 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 45 | |
mfiore | 0:bb4e812f7c97 | 46 | // load obj index entry |
mfiore | 0:bb4e812f7c97 | 47 | u32_t addr = SPIFFS_PAGE_TO_PADDR(fs, *objix_pix); |
mfiore | 0:bb4e812f7c97 | 48 | if (objix_spix == 0) { |
mfiore | 0:bb4e812f7c97 | 49 | // get referenced page from object index header |
mfiore | 0:bb4e812f7c97 | 50 | addr += sizeof(spiffs_page_object_ix_header) + data_spix * sizeof(spiffs_page_ix); |
mfiore | 0:bb4e812f7c97 | 51 | } else { |
mfiore | 0:bb4e812f7c97 | 52 | // get referenced page from object index |
mfiore | 0:bb4e812f7c97 | 53 | addr += sizeof(spiffs_page_object_ix) + SPIFFS_OBJ_IX_ENTRY(fs, data_spix) * sizeof(spiffs_page_ix); |
mfiore | 0:bb4e812f7c97 | 54 | } |
mfiore | 0:bb4e812f7c97 | 55 | |
mfiore | 0:bb4e812f7c97 | 56 | res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, 0, addr, sizeof(spiffs_page_ix), (u8_t *)pix); |
mfiore | 0:bb4e812f7c97 | 57 | |
mfiore | 0:bb4e812f7c97 | 58 | return res; |
mfiore | 0:bb4e812f7c97 | 59 | } |
mfiore | 0:bb4e812f7c97 | 60 | |
mfiore | 0:bb4e812f7c97 | 61 | // copies page contents to a new page |
mfiore | 0:bb4e812f7c97 | 62 | static s32_t spiffs_rewrite_page(spiffs *fs, spiffs_page_ix cur_pix, spiffs_page_header *p_hdr, spiffs_page_ix *new_pix) { |
mfiore | 0:bb4e812f7c97 | 63 | s32_t res; |
mfiore | 0:bb4e812f7c97 | 64 | res = spiffs_page_allocate_data(fs, p_hdr->obj_id, p_hdr, 0,0,0,0, new_pix); |
mfiore | 0:bb4e812f7c97 | 65 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 66 | res = spiffs_phys_cpy(fs, 0, |
mfiore | 0:bb4e812f7c97 | 67 | SPIFFS_PAGE_TO_PADDR(fs, *new_pix) + sizeof(spiffs_page_header), |
mfiore | 0:bb4e812f7c97 | 68 | SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + sizeof(spiffs_page_header), |
mfiore | 0:bb4e812f7c97 | 69 | SPIFFS_DATA_PAGE_SIZE(fs)); |
mfiore | 0:bb4e812f7c97 | 70 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 71 | return res; |
mfiore | 0:bb4e812f7c97 | 72 | } |
mfiore | 0:bb4e812f7c97 | 73 | |
mfiore | 0:bb4e812f7c97 | 74 | // rewrites the object index for given object id and replaces the |
mfiore | 0:bb4e812f7c97 | 75 | // data page index to a new page index |
mfiore | 0:bb4e812f7c97 | 76 | static s32_t spiffs_rewrite_index(spiffs *fs, spiffs_obj_id obj_id, spiffs_span_ix data_spix, spiffs_page_ix new_data_pix, spiffs_page_ix objix_pix) { |
mfiore | 0:bb4e812f7c97 | 77 | s32_t res; |
mfiore | 0:bb4e812f7c97 | 78 | spiffs_block_ix bix; |
mfiore | 0:bb4e812f7c97 | 79 | int entry; |
mfiore | 0:bb4e812f7c97 | 80 | spiffs_page_ix free_pix; |
mfiore | 0:bb4e812f7c97 | 81 | obj_id |= SPIFFS_OBJ_ID_IX_FLAG; |
mfiore | 0:bb4e812f7c97 | 82 | |
mfiore | 0:bb4e812f7c97 | 83 | // find free entry |
mfiore | 0:bb4e812f7c97 | 84 | res = spiffs_obj_lu_find_free(fs, fs->free_cursor_block_ix, fs->free_cursor_obj_lu_entry, &bix, &entry); |
mfiore | 0:bb4e812f7c97 | 85 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 86 | free_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry); |
mfiore | 0:bb4e812f7c97 | 87 | |
mfiore | 0:bb4e812f7c97 | 88 | // calculate object index span index for given data page span index |
mfiore | 0:bb4e812f7c97 | 89 | spiffs_span_ix objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix); |
mfiore | 0:bb4e812f7c97 | 90 | if (objix_spix == 0) { |
mfiore | 0:bb4e812f7c97 | 91 | // calc index in index header |
mfiore | 0:bb4e812f7c97 | 92 | entry = data_spix; |
mfiore | 0:bb4e812f7c97 | 93 | } else { |
mfiore | 0:bb4e812f7c97 | 94 | // calc entry in index |
mfiore | 0:bb4e812f7c97 | 95 | entry = SPIFFS_OBJ_IX_ENTRY(fs, data_spix); |
mfiore | 0:bb4e812f7c97 | 96 | } |
mfiore | 0:bb4e812f7c97 | 97 | // load index |
mfiore | 0:bb4e812f7c97 | 98 | res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, |
mfiore | 0:bb4e812f7c97 | 99 | 0, SPIFFS_PAGE_TO_PADDR(fs, objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work); |
mfiore | 0:bb4e812f7c97 | 100 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 101 | spiffs_page_header *objix_p_hdr = (spiffs_page_header *)fs->lu_work; |
mfiore | 0:bb4e812f7c97 | 102 | |
mfiore | 0:bb4e812f7c97 | 103 | // be ultra safe, double check header against provided data |
mfiore | 0:bb4e812f7c97 | 104 | if (objix_p_hdr->obj_id != obj_id) { |
mfiore | 0:bb4e812f7c97 | 105 | spiffs_page_delete(fs, free_pix); |
mfiore | 0:bb4e812f7c97 | 106 | return SPIFFS_ERR_CHECK_OBJ_ID_MISM; |
mfiore | 0:bb4e812f7c97 | 107 | } |
mfiore | 0:bb4e812f7c97 | 108 | if (objix_p_hdr->span_ix != objix_spix) { |
mfiore | 0:bb4e812f7c97 | 109 | spiffs_page_delete(fs, free_pix); |
mfiore | 0:bb4e812f7c97 | 110 | return SPIFFS_ERR_CHECK_SPIX_MISM; |
mfiore | 0:bb4e812f7c97 | 111 | } |
mfiore | 0:bb4e812f7c97 | 112 | if ((objix_p_hdr->flags & (SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_IXDELE | SPIFFS_PH_FLAG_INDEX | |
mfiore | 0:bb4e812f7c97 | 113 | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET)) != |
mfiore | 0:bb4e812f7c97 | 114 | (SPIFFS_PH_FLAG_IXDELE | SPIFFS_PH_FLAG_DELET)) { |
mfiore | 0:bb4e812f7c97 | 115 | spiffs_page_delete(fs, free_pix); |
mfiore | 0:bb4e812f7c97 | 116 | return SPIFFS_ERR_CHECK_FLAGS_BAD; |
mfiore | 0:bb4e812f7c97 | 117 | } |
mfiore | 0:bb4e812f7c97 | 118 | |
mfiore | 0:bb4e812f7c97 | 119 | // rewrite in mem |
mfiore | 0:bb4e812f7c97 | 120 | if (objix_spix == 0) { |
mfiore | 0:bb4e812f7c97 | 121 | ((spiffs_page_ix*)((void*)fs->lu_work + sizeof(spiffs_page_object_ix_header)))[data_spix] = new_data_pix; |
mfiore | 0:bb4e812f7c97 | 122 | } else { |
mfiore | 0:bb4e812f7c97 | 123 | ((spiffs_page_ix*)((void*)fs->lu_work + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, data_spix)] = new_data_pix; |
mfiore | 0:bb4e812f7c97 | 124 | } |
mfiore | 0:bb4e812f7c97 | 125 | |
mfiore | 0:bb4e812f7c97 | 126 | res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT, |
mfiore | 0:bb4e812f7c97 | 127 | 0, SPIFFS_PAGE_TO_PADDR(fs, free_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work); |
mfiore | 0:bb4e812f7c97 | 128 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 129 | res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT, |
mfiore | 0:bb4e812f7c97 | 130 | 0, SPIFFS_BLOCK_TO_PADDR(fs, SPIFFS_BLOCK_FOR_PAGE(fs, free_pix)) + SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, free_pix) * sizeof(spiffs_page_ix), |
mfiore | 0:bb4e812f7c97 | 131 | sizeof(spiffs_obj_id), |
mfiore | 0:bb4e812f7c97 | 132 | (u8_t *)&obj_id); |
mfiore | 0:bb4e812f7c97 | 133 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 134 | res = spiffs_page_delete(fs, objix_pix); |
mfiore | 0:bb4e812f7c97 | 135 | |
mfiore | 0:bb4e812f7c97 | 136 | return res; |
mfiore | 0:bb4e812f7c97 | 137 | } |
mfiore | 0:bb4e812f7c97 | 138 | |
mfiore | 0:bb4e812f7c97 | 139 | // deletes an object just by marking object index header as deleted |
mfiore | 0:bb4e812f7c97 | 140 | static s32_t spiffs_delete_obj_lazy(spiffs *fs, spiffs_obj_id obj_id) { |
mfiore | 0:bb4e812f7c97 | 141 | spiffs_page_ix objix_hdr_pix; |
mfiore | 0:bb4e812f7c97 | 142 | s32_t res; |
mfiore | 0:bb4e812f7c97 | 143 | res = spiffs_obj_lu_find_id_and_span(fs, obj_id, 0, 0, &objix_hdr_pix); |
mfiore | 0:bb4e812f7c97 | 144 | if (res == SPIFFS_ERR_NOT_FOUND) { |
mfiore | 0:bb4e812f7c97 | 145 | return SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 146 | } |
mfiore | 0:bb4e812f7c97 | 147 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 148 | u8_t flags = 0xff & ~SPIFFS_PH_FLAG_IXDELE; |
mfiore | 0:bb4e812f7c97 | 149 | res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT, |
mfiore | 0:bb4e812f7c97 | 150 | 0, SPIFFS_PAGE_TO_PADDR(fs, objix_hdr_pix) + offsetof(spiffs_page_header, flags), |
mfiore | 0:bb4e812f7c97 | 151 | sizeof(u8_t), |
mfiore | 0:bb4e812f7c97 | 152 | (u8_t *)&flags); |
mfiore | 0:bb4e812f7c97 | 153 | return res; |
mfiore | 0:bb4e812f7c97 | 154 | } |
mfiore | 0:bb4e812f7c97 | 155 | |
mfiore | 0:bb4e812f7c97 | 156 | // validates the given look up entry |
mfiore | 0:bb4e812f7c97 | 157 | static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, spiffs_page_header *p_hdr, |
mfiore | 0:bb4e812f7c97 | 158 | spiffs_page_ix cur_pix, spiffs_block_ix cur_block, int cur_entry, int *reload_lu) { |
mfiore | 0:bb4e812f7c97 | 159 | u8_t delete_page = 0; |
mfiore | 0:bb4e812f7c97 | 160 | s32_t res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 161 | spiffs_page_ix objix_pix; |
mfiore | 0:bb4e812f7c97 | 162 | spiffs_page_ix ref_pix; |
mfiore | 0:bb4e812f7c97 | 163 | // check validity, take actions |
mfiore | 0:bb4e812f7c97 | 164 | if (((lu_obj_id == SPIFFS_OBJ_ID_DELETED) && (p_hdr->flags & SPIFFS_PH_FLAG_DELET)) || |
mfiore | 0:bb4e812f7c97 | 165 | ((lu_obj_id == SPIFFS_OBJ_ID_FREE) && (p_hdr->flags & SPIFFS_PH_FLAG_USED) == 0)) { |
mfiore | 0:bb4e812f7c97 | 166 | // look up entry deleted / free but used in page header |
mfiore | 0:bb4e812f7c97 | 167 | SPIFFS_CHECK_DBG("LU: pix %04x deleted/free in lu but not on page\n", cur_pix); |
mfiore | 0:bb4e812f7c97 | 168 | *reload_lu = 1; |
mfiore | 0:bb4e812f7c97 | 169 | delete_page = 1; |
mfiore | 0:bb4e812f7c97 | 170 | if (p_hdr->flags & SPIFFS_PH_FLAG_INDEX) { |
mfiore | 0:bb4e812f7c97 | 171 | // header says data page |
mfiore | 0:bb4e812f7c97 | 172 | // data page can be removed if not referenced by some object index |
mfiore | 0:bb4e812f7c97 | 173 | res = spiffs_object_get_data_page_index_reference(fs, p_hdr->obj_id, p_hdr->span_ix, &ref_pix, &objix_pix); |
mfiore | 0:bb4e812f7c97 | 174 | if (res == SPIFFS_ERR_NOT_FOUND) { |
mfiore | 0:bb4e812f7c97 | 175 | // no object with this id, so remove page safely |
mfiore | 0:bb4e812f7c97 | 176 | res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 177 | } else { |
mfiore | 0:bb4e812f7c97 | 178 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 179 | if (ref_pix == cur_pix) { |
mfiore | 0:bb4e812f7c97 | 180 | // data page referenced by object index but deleted in lu |
mfiore | 0:bb4e812f7c97 | 181 | // copy page to new place and re-write the object index to new place |
mfiore | 0:bb4e812f7c97 | 182 | spiffs_page_ix new_pix; |
mfiore | 0:bb4e812f7c97 | 183 | res = spiffs_rewrite_page(fs, cur_pix, p_hdr, &new_pix); |
mfiore | 0:bb4e812f7c97 | 184 | SPIFFS_CHECK_DBG("LU: FIXUP: data page not found elsewhere, rewriting %04x to new page %04x\n", cur_pix, new_pix); |
mfiore | 0:bb4e812f7c97 | 185 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 186 | *reload_lu = 1; |
mfiore | 0:bb4e812f7c97 | 187 | SPIFFS_CHECK_DBG("LU: FIXUP: %04x rewritten to %04x, affected objix_pix %04x\n", cur_pix, new_pix, objix_pix); |
mfiore | 0:bb4e812f7c97 | 188 | res = spiffs_rewrite_index(fs, p_hdr->obj_id, p_hdr->span_ix, new_pix, objix_pix); |
mfiore | 0:bb4e812f7c97 | 189 | if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) { |
mfiore | 0:bb4e812f7c97 | 190 | // index bad also, cannot mend this file |
mfiore | 0:bb4e812f7c97 | 191 | SPIFFS_CHECK_DBG("LU: FIXUP: index bad %i, cannot mend!\n", res); |
mfiore | 0:bb4e812f7c97 | 192 | res = spiffs_page_delete(fs, new_pix); |
mfiore | 0:bb4e812f7c97 | 193 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 194 | res = spiffs_delete_obj_lazy(fs, p_hdr->obj_id); |
mfiore | 0:bb4e812f7c97 | 195 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr->obj_id, 0); |
mfiore | 0:bb4e812f7c97 | 196 | } else { |
mfiore | 0:bb4e812f7c97 | 197 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, p_hdr->obj_id, p_hdr->span_ix); |
mfiore | 0:bb4e812f7c97 | 198 | } |
mfiore | 0:bb4e812f7c97 | 199 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 200 | } |
mfiore | 0:bb4e812f7c97 | 201 | } |
mfiore | 0:bb4e812f7c97 | 202 | } else { |
mfiore | 0:bb4e812f7c97 | 203 | // header says index page |
mfiore | 0:bb4e812f7c97 | 204 | // index page can be removed if other index with same obj_id and spanix is found |
mfiore | 0:bb4e812f7c97 | 205 | res = spiffs_obj_lu_find_id_and_span(fs, p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, cur_pix, 0); |
mfiore | 0:bb4e812f7c97 | 206 | if (res == SPIFFS_ERR_NOT_FOUND) { |
mfiore | 0:bb4e812f7c97 | 207 | // no such index page found, check for a data page amongst page headers |
mfiore | 0:bb4e812f7c97 | 208 | // lu cannot be trusted |
mfiore | 0:bb4e812f7c97 | 209 | res = spiffs_obj_lu_find_id_and_span_by_phdr(fs, p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, 0); |
mfiore | 0:bb4e812f7c97 | 210 | if (res == SPIFFS_OK) { // ignore other errors |
mfiore | 0:bb4e812f7c97 | 211 | // got a data page also, assume lu corruption only, rewrite to new page |
mfiore | 0:bb4e812f7c97 | 212 | spiffs_page_ix new_pix; |
mfiore | 0:bb4e812f7c97 | 213 | res = spiffs_rewrite_page(fs, cur_pix, p_hdr, &new_pix); |
mfiore | 0:bb4e812f7c97 | 214 | SPIFFS_CHECK_DBG("LU: FIXUP: ix page with data not found elsewhere, rewriting %04x to new page %04x\n", cur_pix, new_pix); |
mfiore | 0:bb4e812f7c97 | 215 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 216 | *reload_lu = 1; |
mfiore | 0:bb4e812f7c97 | 217 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix); |
mfiore | 0:bb4e812f7c97 | 218 | } |
mfiore | 0:bb4e812f7c97 | 219 | } else { |
mfiore | 0:bb4e812f7c97 | 220 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 221 | } |
mfiore | 0:bb4e812f7c97 | 222 | } |
mfiore | 0:bb4e812f7c97 | 223 | } |
mfiore | 0:bb4e812f7c97 | 224 | if (lu_obj_id != SPIFFS_OBJ_ID_FREE && lu_obj_id != SPIFFS_OBJ_ID_DELETED) { |
mfiore | 0:bb4e812f7c97 | 225 | // look up entry used |
mfiore | 0:bb4e812f7c97 | 226 | if ((p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG) != (lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG)) { |
mfiore | 0:bb4e812f7c97 | 227 | SPIFFS_CHECK_DBG("LU: pix %04x differ in obj_id lu:%04x ph:%04x\n", cur_pix, lu_obj_id, p_hdr->obj_id); |
mfiore | 0:bb4e812f7c97 | 228 | delete_page = 1; |
mfiore | 0:bb4e812f7c97 | 229 | if ((p_hdr->flags & SPIFFS_PH_FLAG_DELET) == 0 || |
mfiore | 0:bb4e812f7c97 | 230 | (p_hdr->flags & SPIFFS_PH_FLAG_FINAL) || |
mfiore | 0:bb4e812f7c97 | 231 | (p_hdr->flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_IXDELE)) == 0) { |
mfiore | 0:bb4e812f7c97 | 232 | // page deleted or not finalized, just remove it |
mfiore | 0:bb4e812f7c97 | 233 | } else { |
mfiore | 0:bb4e812f7c97 | 234 | if (p_hdr->flags & SPIFFS_PH_FLAG_INDEX) { |
mfiore | 0:bb4e812f7c97 | 235 | // if data page, check for reference to this page |
mfiore | 0:bb4e812f7c97 | 236 | res = spiffs_object_get_data_page_index_reference(fs, p_hdr->obj_id, p_hdr->span_ix, &ref_pix, &objix_pix); |
mfiore | 0:bb4e812f7c97 | 237 | if (res == SPIFFS_ERR_NOT_FOUND) { |
mfiore | 0:bb4e812f7c97 | 238 | // no object with this id, so remove page safely |
mfiore | 0:bb4e812f7c97 | 239 | res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 240 | } else { |
mfiore | 0:bb4e812f7c97 | 241 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 242 | // if found, rewrite page with object id, update index, and delete current |
mfiore | 0:bb4e812f7c97 | 243 | if (ref_pix == cur_pix) { |
mfiore | 0:bb4e812f7c97 | 244 | spiffs_page_ix new_pix; |
mfiore | 0:bb4e812f7c97 | 245 | res = spiffs_rewrite_page(fs, cur_pix, p_hdr, &new_pix); |
mfiore | 0:bb4e812f7c97 | 246 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 247 | res = spiffs_rewrite_index(fs, p_hdr->obj_id, p_hdr->span_ix, new_pix, objix_pix); |
mfiore | 0:bb4e812f7c97 | 248 | if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) { |
mfiore | 0:bb4e812f7c97 | 249 | // index bad also, cannot mend this file |
mfiore | 0:bb4e812f7c97 | 250 | SPIFFS_CHECK_DBG("LU: FIXUP: index bad %i, cannot mend!\n", res); |
mfiore | 0:bb4e812f7c97 | 251 | res = spiffs_page_delete(fs, new_pix); |
mfiore | 0:bb4e812f7c97 | 252 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 253 | res = spiffs_delete_obj_lazy(fs, p_hdr->obj_id); |
mfiore | 0:bb4e812f7c97 | 254 | *reload_lu = 1; |
mfiore | 0:bb4e812f7c97 | 255 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr->obj_id, 0); |
mfiore | 0:bb4e812f7c97 | 256 | } |
mfiore | 0:bb4e812f7c97 | 257 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 258 | } |
mfiore | 0:bb4e812f7c97 | 259 | } |
mfiore | 0:bb4e812f7c97 | 260 | } else { |
mfiore | 0:bb4e812f7c97 | 261 | // else if index, check for other pages with both obj_id's and spanix |
mfiore | 0:bb4e812f7c97 | 262 | spiffs_page_ix objix_pix_lu, objix_pix_ph; |
mfiore | 0:bb4e812f7c97 | 263 | // see if other object index page exists for lookup obj id and span index |
mfiore | 0:bb4e812f7c97 | 264 | res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, 0, &objix_pix_lu); |
mfiore | 0:bb4e812f7c97 | 265 | if (res == SPIFFS_ERR_NOT_FOUND) { |
mfiore | 0:bb4e812f7c97 | 266 | res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 267 | objix_pix_lu = 0; |
mfiore | 0:bb4e812f7c97 | 268 | } |
mfiore | 0:bb4e812f7c97 | 269 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 270 | // see if other object index exists for page header obj id and span index |
mfiore | 0:bb4e812f7c97 | 271 | res = spiffs_obj_lu_find_id_and_span(fs, p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, 0, &objix_pix_ph); |
mfiore | 0:bb4e812f7c97 | 272 | if (res == SPIFFS_ERR_NOT_FOUND) { |
mfiore | 0:bb4e812f7c97 | 273 | res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 274 | objix_pix_ph = 0; |
mfiore | 0:bb4e812f7c97 | 275 | } |
mfiore | 0:bb4e812f7c97 | 276 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 277 | // if both obj_id's found, just delete current |
mfiore | 0:bb4e812f7c97 | 278 | if (objix_pix_ph == 0 || objix_pix_lu == 0) { |
mfiore | 0:bb4e812f7c97 | 279 | // otherwise try finding first corresponding data pages |
mfiore | 0:bb4e812f7c97 | 280 | spiffs_page_ix data_pix_lu, data_pix_ph; |
mfiore | 0:bb4e812f7c97 | 281 | // see if other data page exists for look up obj id and span index |
mfiore | 0:bb4e812f7c97 | 282 | res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &data_pix_lu); |
mfiore | 0:bb4e812f7c97 | 283 | if (res == SPIFFS_ERR_NOT_FOUND) { |
mfiore | 0:bb4e812f7c97 | 284 | res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 285 | objix_pix_lu = 0; |
mfiore | 0:bb4e812f7c97 | 286 | } |
mfiore | 0:bb4e812f7c97 | 287 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 288 | // see if other data page exists for page header obj id and span index |
mfiore | 0:bb4e812f7c97 | 289 | res = spiffs_obj_lu_find_id_and_span(fs, p_hdr->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &data_pix_ph); |
mfiore | 0:bb4e812f7c97 | 290 | if (res == SPIFFS_ERR_NOT_FOUND) { |
mfiore | 0:bb4e812f7c97 | 291 | res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 292 | objix_pix_ph = 0; |
mfiore | 0:bb4e812f7c97 | 293 | } |
mfiore | 0:bb4e812f7c97 | 294 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 295 | |
mfiore | 0:bb4e812f7c97 | 296 | spiffs_page_header new_ph; |
mfiore | 0:bb4e812f7c97 | 297 | new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL); |
mfiore | 0:bb4e812f7c97 | 298 | new_ph.span_ix = p_hdr->span_ix; |
mfiore | 0:bb4e812f7c97 | 299 | spiffs_page_ix new_pix; |
mfiore | 0:bb4e812f7c97 | 300 | if ((objix_pix_lu && data_pix_lu && data_pix_ph && objix_pix_ph == 0) || |
mfiore | 0:bb4e812f7c97 | 301 | (objix_pix_lu == 0 && data_pix_ph && objix_pix_ph == 0)) { |
mfiore | 0:bb4e812f7c97 | 302 | // got a data page for page header obj id |
mfiore | 0:bb4e812f7c97 | 303 | // rewrite as obj_id_ph |
mfiore | 0:bb4e812f7c97 | 304 | new_ph.obj_id = p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG; |
mfiore | 0:bb4e812f7c97 | 305 | res = spiffs_rewrite_page(fs, cur_pix, &new_ph, &new_pix); |
mfiore | 0:bb4e812f7c97 | 306 | SPIFFS_CHECK_DBG("LU: FIXUP: rewrite page %04x as %04x to pix %04x\n", cur_pix, new_ph.obj_id, new_pix); |
mfiore | 0:bb4e812f7c97 | 307 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix); |
mfiore | 0:bb4e812f7c97 | 308 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 309 | *reload_lu = 1; |
mfiore | 0:bb4e812f7c97 | 310 | } else if ((objix_pix_ph && data_pix_ph && data_pix_lu && objix_pix_lu == 0) || |
mfiore | 0:bb4e812f7c97 | 311 | (objix_pix_ph == 0 && data_pix_lu && objix_pix_lu == 0)) { |
mfiore | 0:bb4e812f7c97 | 312 | // got a data page for look up obj id |
mfiore | 0:bb4e812f7c97 | 313 | // rewrite as obj_id_lu |
mfiore | 0:bb4e812f7c97 | 314 | new_ph.obj_id = lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG; |
mfiore | 0:bb4e812f7c97 | 315 | SPIFFS_CHECK_DBG("LU: FIXUP: rewrite page %04x as %04x\n", cur_pix, new_ph.obj_id); |
mfiore | 0:bb4e812f7c97 | 316 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix); |
mfiore | 0:bb4e812f7c97 | 317 | res = spiffs_rewrite_page(fs, cur_pix, &new_ph, &new_pix); |
mfiore | 0:bb4e812f7c97 | 318 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 319 | *reload_lu = 1; |
mfiore | 0:bb4e812f7c97 | 320 | } else { |
mfiore | 0:bb4e812f7c97 | 321 | // cannot safely do anything |
mfiore | 0:bb4e812f7c97 | 322 | SPIFFS_CHECK_DBG("LU: FIXUP: nothing to do, just delete\n"); |
mfiore | 0:bb4e812f7c97 | 323 | } |
mfiore | 0:bb4e812f7c97 | 324 | } |
mfiore | 0:bb4e812f7c97 | 325 | } |
mfiore | 0:bb4e812f7c97 | 326 | } |
mfiore | 0:bb4e812f7c97 | 327 | } else if (((lu_obj_id & SPIFFS_OBJ_ID_IX_FLAG) && (p_hdr->flags & SPIFFS_PH_FLAG_INDEX)) || |
mfiore | 0:bb4e812f7c97 | 328 | ((lu_obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0 && (p_hdr->flags & SPIFFS_PH_FLAG_INDEX) == 0)) { |
mfiore | 0:bb4e812f7c97 | 329 | SPIFFS_CHECK_DBG("LU: %04x lu/page index marking differ\n", cur_pix); |
mfiore | 0:bb4e812f7c97 | 330 | spiffs_page_ix data_pix, objix_pix; |
mfiore | 0:bb4e812f7c97 | 331 | // see if other data page exists for given obj id and span index |
mfiore | 0:bb4e812f7c97 | 332 | res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, cur_pix, &data_pix); |
mfiore | 0:bb4e812f7c97 | 333 | if (res == SPIFFS_ERR_NOT_FOUND) { |
mfiore | 0:bb4e812f7c97 | 334 | res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 335 | data_pix = 0; |
mfiore | 0:bb4e812f7c97 | 336 | } |
mfiore | 0:bb4e812f7c97 | 337 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 338 | // see if other object index exists for given obj id and span index |
mfiore | 0:bb4e812f7c97 | 339 | res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, cur_pix, &objix_pix); |
mfiore | 0:bb4e812f7c97 | 340 | if (res == SPIFFS_ERR_NOT_FOUND) { |
mfiore | 0:bb4e812f7c97 | 341 | res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 342 | objix_pix = 0; |
mfiore | 0:bb4e812f7c97 | 343 | } |
mfiore | 0:bb4e812f7c97 | 344 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 345 | |
mfiore | 0:bb4e812f7c97 | 346 | delete_page = 1; |
mfiore | 0:bb4e812f7c97 | 347 | // if other data page exists and object index exists, just delete page |
mfiore | 0:bb4e812f7c97 | 348 | if (data_pix && objix_pix) { |
mfiore | 0:bb4e812f7c97 | 349 | SPIFFS_CHECK_DBG("LU: FIXUP: other index and data page exists, simply remove\n"); |
mfiore | 0:bb4e812f7c97 | 350 | } else |
mfiore | 0:bb4e812f7c97 | 351 | // if only data page exists, make this page index |
mfiore | 0:bb4e812f7c97 | 352 | if (data_pix && objix_pix == 0) { |
mfiore | 0:bb4e812f7c97 | 353 | SPIFFS_CHECK_DBG("LU: FIXUP: other data page exists, make this index\n"); |
mfiore | 0:bb4e812f7c97 | 354 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, lu_obj_id, p_hdr->span_ix); |
mfiore | 0:bb4e812f7c97 | 355 | spiffs_page_header new_ph; |
mfiore | 0:bb4e812f7c97 | 356 | spiffs_page_ix new_pix; |
mfiore | 0:bb4e812f7c97 | 357 | new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX); |
mfiore | 0:bb4e812f7c97 | 358 | new_ph.obj_id = lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG; |
mfiore | 0:bb4e812f7c97 | 359 | new_ph.span_ix = p_hdr->span_ix; |
mfiore | 0:bb4e812f7c97 | 360 | res = spiffs_page_allocate_data(fs, new_ph.obj_id, &new_ph, 0, 0, 0, 1, &new_pix); |
mfiore | 0:bb4e812f7c97 | 361 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 362 | res = spiffs_phys_cpy(fs, 0, SPIFFS_PAGE_TO_PADDR(fs, new_pix) + sizeof(spiffs_page_header), |
mfiore | 0:bb4e812f7c97 | 363 | SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + sizeof(spiffs_page_header), |
mfiore | 0:bb4e812f7c97 | 364 | SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header)); |
mfiore | 0:bb4e812f7c97 | 365 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 366 | } else |
mfiore | 0:bb4e812f7c97 | 367 | // if only index exists, make data page |
mfiore | 0:bb4e812f7c97 | 368 | if (data_pix == 0 && objix_pix) { |
mfiore | 0:bb4e812f7c97 | 369 | SPIFFS_CHECK_DBG("LU: FIXUP: other index page exists, make this data\n"); |
mfiore | 0:bb4e812f7c97 | 370 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, lu_obj_id, p_hdr->span_ix); |
mfiore | 0:bb4e812f7c97 | 371 | spiffs_page_header new_ph; |
mfiore | 0:bb4e812f7c97 | 372 | spiffs_page_ix new_pix; |
mfiore | 0:bb4e812f7c97 | 373 | new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL); |
mfiore | 0:bb4e812f7c97 | 374 | new_ph.obj_id = lu_obj_id & ~SPIFFS_OBJ_ID_IX_FLAG; |
mfiore | 0:bb4e812f7c97 | 375 | new_ph.span_ix = p_hdr->span_ix; |
mfiore | 0:bb4e812f7c97 | 376 | res = spiffs_page_allocate_data(fs, new_ph.obj_id, &new_ph, 0, 0, 0, 1, &new_pix); |
mfiore | 0:bb4e812f7c97 | 377 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 378 | res = spiffs_phys_cpy(fs, 0, SPIFFS_PAGE_TO_PADDR(fs, new_pix) + sizeof(spiffs_page_header), |
mfiore | 0:bb4e812f7c97 | 379 | SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + sizeof(spiffs_page_header), |
mfiore | 0:bb4e812f7c97 | 380 | SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header)); |
mfiore | 0:bb4e812f7c97 | 381 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 382 | } else { |
mfiore | 0:bb4e812f7c97 | 383 | // if nothing exists, we cannot safely make a decision - delete |
mfiore | 0:bb4e812f7c97 | 384 | } |
mfiore | 0:bb4e812f7c97 | 385 | } |
mfiore | 0:bb4e812f7c97 | 386 | else if ((p_hdr->flags & SPIFFS_PH_FLAG_DELET) == 0) { |
mfiore | 0:bb4e812f7c97 | 387 | SPIFFS_CHECK_DBG("LU: pix %04x busy in lu but deleted on page\n", cur_pix); |
mfiore | 0:bb4e812f7c97 | 388 | delete_page = 1; |
mfiore | 0:bb4e812f7c97 | 389 | } else if ((p_hdr->flags & SPIFFS_PH_FLAG_FINAL)) { |
mfiore | 0:bb4e812f7c97 | 390 | SPIFFS_CHECK_DBG("LU: pix %04x busy but not final\n", cur_pix); |
mfiore | 0:bb4e812f7c97 | 391 | // page can be removed if not referenced by object index |
mfiore | 0:bb4e812f7c97 | 392 | *reload_lu = 1; |
mfiore | 0:bb4e812f7c97 | 393 | res = spiffs_object_get_data_page_index_reference(fs, lu_obj_id, p_hdr->span_ix, &ref_pix, &objix_pix); |
mfiore | 0:bb4e812f7c97 | 394 | if (res == SPIFFS_ERR_NOT_FOUND) { |
mfiore | 0:bb4e812f7c97 | 395 | // no object with this id, so remove page safely |
mfiore | 0:bb4e812f7c97 | 396 | res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 397 | delete_page = 1; |
mfiore | 0:bb4e812f7c97 | 398 | } else { |
mfiore | 0:bb4e812f7c97 | 399 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 400 | if (ref_pix != cur_pix) { |
mfiore | 0:bb4e812f7c97 | 401 | SPIFFS_CHECK_DBG("LU: FIXUP: other finalized page is referred, just delete\n"); |
mfiore | 0:bb4e812f7c97 | 402 | delete_page = 1; |
mfiore | 0:bb4e812f7c97 | 403 | } else { |
mfiore | 0:bb4e812f7c97 | 404 | // page referenced by object index but not final |
mfiore | 0:bb4e812f7c97 | 405 | // just finalize |
mfiore | 0:bb4e812f7c97 | 406 | SPIFFS_CHECK_DBG("LU: FIXUP: unfinalized page is referred, finalizing\n"); |
mfiore | 0:bb4e812f7c97 | 407 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix); |
mfiore | 0:bb4e812f7c97 | 408 | u8_t flags = 0xff & ~SPIFFS_PH_FLAG_FINAL; |
mfiore | 0:bb4e812f7c97 | 409 | res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT, |
mfiore | 0:bb4e812f7c97 | 410 | 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + offsetof(spiffs_page_header, flags), |
mfiore | 0:bb4e812f7c97 | 411 | sizeof(u8_t), (u8_t*)&flags); |
mfiore | 0:bb4e812f7c97 | 412 | } |
mfiore | 0:bb4e812f7c97 | 413 | } |
mfiore | 0:bb4e812f7c97 | 414 | } |
mfiore | 0:bb4e812f7c97 | 415 | } |
mfiore | 0:bb4e812f7c97 | 416 | |
mfiore | 0:bb4e812f7c97 | 417 | if (delete_page) { |
mfiore | 0:bb4e812f7c97 | 418 | SPIFFS_CHECK_DBG("LU: FIXUP: deleting page %04x\n", cur_pix); |
mfiore | 0:bb4e812f7c97 | 419 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_PAGE, cur_pix, 0); |
mfiore | 0:bb4e812f7c97 | 420 | res = spiffs_page_delete(fs, cur_pix); |
mfiore | 0:bb4e812f7c97 | 421 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 422 | } |
mfiore | 0:bb4e812f7c97 | 423 | |
mfiore | 0:bb4e812f7c97 | 424 | return res; |
mfiore | 0:bb4e812f7c97 | 425 | } |
mfiore | 0:bb4e812f7c97 | 426 | |
mfiore | 0:bb4e812f7c97 | 427 | static s32_t spiffs_lookup_check_v(spiffs *fs, spiffs_obj_id obj_id, spiffs_block_ix cur_block, int cur_entry, |
mfiore | 0:bb4e812f7c97 | 428 | u32_t user_data, void *user_p) { |
mfiore | 0:bb4e812f7c97 | 429 | s32_t res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 430 | spiffs_page_header p_hdr; |
mfiore | 0:bb4e812f7c97 | 431 | spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, cur_block, cur_entry); |
mfiore | 0:bb4e812f7c97 | 432 | |
mfiore | 0:bb4e812f7c97 | 433 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, |
mfiore | 0:bb4e812f7c97 | 434 | (cur_block * 256)/fs->block_count, 0); |
mfiore | 0:bb4e812f7c97 | 435 | |
mfiore | 0:bb4e812f7c97 | 436 | // load header |
mfiore | 0:bb4e812f7c97 | 437 | res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, |
mfiore | 0:bb4e812f7c97 | 438 | 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr); |
mfiore | 0:bb4e812f7c97 | 439 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 440 | |
mfiore | 0:bb4e812f7c97 | 441 | int reload_lu = 0; |
mfiore | 0:bb4e812f7c97 | 442 | |
mfiore | 0:bb4e812f7c97 | 443 | res = spiffs_lookup_check_validate(fs, obj_id, &p_hdr, cur_pix, cur_block, cur_entry, &reload_lu); |
mfiore | 0:bb4e812f7c97 | 444 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 445 | |
mfiore | 0:bb4e812f7c97 | 446 | if (res == SPIFFS_OK) { |
mfiore | 0:bb4e812f7c97 | 447 | return reload_lu ? SPIFFS_VIS_COUNTINUE_RELOAD : SPIFFS_VIS_COUNTINUE; |
mfiore | 0:bb4e812f7c97 | 448 | } |
mfiore | 0:bb4e812f7c97 | 449 | return res; |
mfiore | 0:bb4e812f7c97 | 450 | } |
mfiore | 0:bb4e812f7c97 | 451 | |
mfiore | 0:bb4e812f7c97 | 452 | |
mfiore | 0:bb4e812f7c97 | 453 | // Scans all object look up. For each entry, corresponding page header is checked for validity. |
mfiore | 0:bb4e812f7c97 | 454 | // If an object index header page is found, this is also checked |
mfiore | 0:bb4e812f7c97 | 455 | s32_t spiffs_lookup_consistency_check(spiffs *fs, u8_t check_all_objects) { |
mfiore | 0:bb4e812f7c97 | 456 | s32_t res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 457 | |
mfiore | 0:bb4e812f7c97 | 458 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 0, 0); |
mfiore | 0:bb4e812f7c97 | 459 | |
mfiore | 0:bb4e812f7c97 | 460 | res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_lookup_check_v, 0, 0, 0, 0); |
mfiore | 0:bb4e812f7c97 | 461 | |
mfiore | 0:bb4e812f7c97 | 462 | if (res == SPIFFS_VIS_END) { |
mfiore | 0:bb4e812f7c97 | 463 | res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 464 | } |
mfiore | 0:bb4e812f7c97 | 465 | |
mfiore | 0:bb4e812f7c97 | 466 | if (res != SPIFFS_OK) { |
mfiore | 0:bb4e812f7c97 | 467 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_ERROR, res, 0); |
mfiore | 0:bb4e812f7c97 | 468 | } |
mfiore | 0:bb4e812f7c97 | 469 | |
mfiore | 0:bb4e812f7c97 | 470 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 256, 0); |
mfiore | 0:bb4e812f7c97 | 471 | |
mfiore | 0:bb4e812f7c97 | 472 | return res; |
mfiore | 0:bb4e812f7c97 | 473 | } |
mfiore | 0:bb4e812f7c97 | 474 | |
mfiore | 0:bb4e812f7c97 | 475 | //--------------------------------------- |
mfiore | 0:bb4e812f7c97 | 476 | // Page consistency |
mfiore | 0:bb4e812f7c97 | 477 | |
mfiore | 0:bb4e812f7c97 | 478 | // Scans all pages (except lu pages), reserves 4 bits in working memory for each page |
mfiore | 0:bb4e812f7c97 | 479 | // bit 0: 0 == FREE|DELETED, 1 == USED |
mfiore | 0:bb4e812f7c97 | 480 | // bit 1: 0 == UNREFERENCED, 1 == REFERENCED |
mfiore | 0:bb4e812f7c97 | 481 | // bit 2: 0 == NOT_INDEX, 1 == INDEX |
mfiore | 0:bb4e812f7c97 | 482 | // bit 3: unused |
mfiore | 0:bb4e812f7c97 | 483 | // A consistent file system will have only pages being |
mfiore | 0:bb4e812f7c97 | 484 | // * x000 free, unreferenced, not index |
mfiore | 0:bb4e812f7c97 | 485 | // * x011 used, referenced only once, not index |
mfiore | 0:bb4e812f7c97 | 486 | // * x101 used, unreferenced, index |
mfiore | 0:bb4e812f7c97 | 487 | // The working memory might not fit all pages so several scans might be needed |
mfiore | 0:bb4e812f7c97 | 488 | static s32_t spiffs_page_consistency_check_i(spiffs *fs) { |
mfiore | 0:bb4e812f7c97 | 489 | const u32_t bits = 4; |
mfiore | 0:bb4e812f7c97 | 490 | const spiffs_page_ix pages_per_scan = SPIFFS_CFG_LOG_PAGE_SZ(fs) * 8 / bits; |
mfiore | 0:bb4e812f7c97 | 491 | |
mfiore | 0:bb4e812f7c97 | 492 | s32_t res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 493 | spiffs_page_ix pix_offset = 0; |
mfiore | 0:bb4e812f7c97 | 494 | |
mfiore | 0:bb4e812f7c97 | 495 | // for each range of pages fitting into work memory |
mfiore | 0:bb4e812f7c97 | 496 | while (pix_offset < SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count) { |
mfiore | 0:bb4e812f7c97 | 497 | // set this flag to abort all checks and rescan the page range |
mfiore | 0:bb4e812f7c97 | 498 | u8_t restart = 0; |
mfiore | 0:bb4e812f7c97 | 499 | memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs)); |
mfiore | 0:bb4e812f7c97 | 500 | |
mfiore | 0:bb4e812f7c97 | 501 | spiffs_block_ix cur_block = 0; |
mfiore | 0:bb4e812f7c97 | 502 | // build consistency bitmap for id range traversing all blocks |
mfiore | 0:bb4e812f7c97 | 503 | while (!restart && cur_block < fs->block_count) { |
mfiore | 0:bb4e812f7c97 | 504 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, |
mfiore | 0:bb4e812f7c97 | 505 | (pix_offset*256)/(SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count) + |
mfiore | 0:bb4e812f7c97 | 506 | ((((cur_block * pages_per_scan * 256)/ (SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count))) / fs->block_count), |
mfiore | 0:bb4e812f7c97 | 507 | 0); |
mfiore | 0:bb4e812f7c97 | 508 | |
mfiore | 0:bb4e812f7c97 | 509 | // traverse each page except for lookup pages |
mfiore | 0:bb4e812f7c97 | 510 | spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_PAGES(fs) + SPIFFS_PAGES_PER_BLOCK(fs) * cur_block; |
mfiore | 0:bb4e812f7c97 | 511 | while (!restart && cur_pix < SPIFFS_PAGES_PER_BLOCK(fs) * (cur_block+1)) { |
mfiore | 0:bb4e812f7c97 | 512 | // read header |
mfiore | 0:bb4e812f7c97 | 513 | spiffs_page_header p_hdr; |
mfiore | 0:bb4e812f7c97 | 514 | res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, |
mfiore | 0:bb4e812f7c97 | 515 | 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr); |
mfiore | 0:bb4e812f7c97 | 516 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 517 | |
mfiore | 0:bb4e812f7c97 | 518 | u8_t within_range = (cur_pix >= pix_offset && cur_pix < pix_offset + pages_per_scan); |
mfiore | 0:bb4e812f7c97 | 519 | const u32_t pix_byte_ix = (cur_pix - pix_offset) / (8/bits); |
mfiore | 0:bb4e812f7c97 | 520 | const u8_t pix_bit_ix = (cur_pix & ((8/bits)-1)) * bits; |
mfiore | 0:bb4e812f7c97 | 521 | |
mfiore | 0:bb4e812f7c97 | 522 | if (within_range && |
mfiore | 0:bb4e812f7c97 | 523 | (p_hdr.flags & SPIFFS_PH_FLAG_DELET) && (p_hdr.flags & SPIFFS_PH_FLAG_USED) == 0) { |
mfiore | 0:bb4e812f7c97 | 524 | // used |
mfiore | 0:bb4e812f7c97 | 525 | fs->work[pix_byte_ix] |= (1<<(pix_bit_ix + 0)); |
mfiore | 0:bb4e812f7c97 | 526 | } |
mfiore | 0:bb4e812f7c97 | 527 | if ((p_hdr.flags & SPIFFS_PH_FLAG_DELET) && |
mfiore | 0:bb4e812f7c97 | 528 | (p_hdr.flags & SPIFFS_PH_FLAG_IXDELE) && |
mfiore | 0:bb4e812f7c97 | 529 | (p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_USED)) == 0) { |
mfiore | 0:bb4e812f7c97 | 530 | // found non-deleted index |
mfiore | 0:bb4e812f7c97 | 531 | if (within_range) { |
mfiore | 0:bb4e812f7c97 | 532 | fs->work[pix_byte_ix] |= (1<<(pix_bit_ix + 2)); |
mfiore | 0:bb4e812f7c97 | 533 | } |
mfiore | 0:bb4e812f7c97 | 534 | |
mfiore | 0:bb4e812f7c97 | 535 | // load non-deleted index |
mfiore | 0:bb4e812f7c97 | 536 | res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, |
mfiore | 0:bb4e812f7c97 | 537 | 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work); |
mfiore | 0:bb4e812f7c97 | 538 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 539 | |
mfiore | 0:bb4e812f7c97 | 540 | // traverse index for referenced pages |
mfiore | 0:bb4e812f7c97 | 541 | spiffs_page_ix *object_page_index; |
mfiore | 0:bb4e812f7c97 | 542 | spiffs_page_header *objix_p_hdr = (spiffs_page_header *)fs->lu_work; |
mfiore | 0:bb4e812f7c97 | 543 | |
mfiore | 0:bb4e812f7c97 | 544 | int entries; |
mfiore | 0:bb4e812f7c97 | 545 | int i; |
mfiore | 0:bb4e812f7c97 | 546 | spiffs_span_ix data_spix_offset; |
mfiore | 0:bb4e812f7c97 | 547 | if (p_hdr.span_ix == 0) { |
mfiore | 0:bb4e812f7c97 | 548 | // object header page index |
mfiore | 0:bb4e812f7c97 | 549 | entries = SPIFFS_OBJ_HDR_IX_LEN(fs); |
mfiore | 0:bb4e812f7c97 | 550 | data_spix_offset = 0; |
mfiore | 0:bb4e812f7c97 | 551 | object_page_index = (spiffs_page_ix *)((void*)fs->lu_work + sizeof(spiffs_page_object_ix_header)); |
mfiore | 0:bb4e812f7c97 | 552 | } else { |
mfiore | 0:bb4e812f7c97 | 553 | // object page index |
mfiore | 0:bb4e812f7c97 | 554 | entries = SPIFFS_OBJ_IX_LEN(fs); |
mfiore | 0:bb4e812f7c97 | 555 | data_spix_offset = SPIFFS_OBJ_HDR_IX_LEN(fs) + SPIFFS_OBJ_IX_LEN(fs) * (p_hdr.span_ix - 1); |
mfiore | 0:bb4e812f7c97 | 556 | object_page_index = (spiffs_page_ix *)((void*)fs->lu_work + sizeof(spiffs_page_object_ix)); |
mfiore | 0:bb4e812f7c97 | 557 | } |
mfiore | 0:bb4e812f7c97 | 558 | |
mfiore | 0:bb4e812f7c97 | 559 | // for all entries in index |
mfiore | 0:bb4e812f7c97 | 560 | for (i = 0; !restart && i < entries; i++) { |
mfiore | 0:bb4e812f7c97 | 561 | spiffs_page_ix rpix = object_page_index[i]; |
mfiore | 0:bb4e812f7c97 | 562 | u8_t rpix_within_range = rpix >= pix_offset && rpix < pix_offset + pages_per_scan; |
mfiore | 0:bb4e812f7c97 | 563 | |
mfiore | 0:bb4e812f7c97 | 564 | if ((rpix != (spiffs_page_ix)-1 && rpix > SPIFFS_MAX_PAGES(fs)) |
mfiore | 0:bb4e812f7c97 | 565 | || (rpix_within_range && SPIFFS_IS_LOOKUP_PAGE(fs, rpix))) { |
mfiore | 0:bb4e812f7c97 | 566 | |
mfiore | 0:bb4e812f7c97 | 567 | // bad reference |
mfiore | 0:bb4e812f7c97 | 568 | SPIFFS_CHECK_DBG("PA: pix %04x bad pix / LU referenced from page %04x\n", |
mfiore | 0:bb4e812f7c97 | 569 | rpix, cur_pix); |
mfiore | 0:bb4e812f7c97 | 570 | // check for data page elsewhere |
mfiore | 0:bb4e812f7c97 | 571 | spiffs_page_ix data_pix; |
mfiore | 0:bb4e812f7c97 | 572 | res = spiffs_obj_lu_find_id_and_span(fs, objix_p_hdr->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, |
mfiore | 0:bb4e812f7c97 | 573 | data_spix_offset + i, 0, &data_pix); |
mfiore | 0:bb4e812f7c97 | 574 | if (res == SPIFFS_ERR_NOT_FOUND) { |
mfiore | 0:bb4e812f7c97 | 575 | res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 576 | data_pix = 0; |
mfiore | 0:bb4e812f7c97 | 577 | } |
mfiore | 0:bb4e812f7c97 | 578 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 579 | if (data_pix == 0) { |
mfiore | 0:bb4e812f7c97 | 580 | // if not, allocate free page |
mfiore | 0:bb4e812f7c97 | 581 | spiffs_page_header new_ph; |
mfiore | 0:bb4e812f7c97 | 582 | new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL); |
mfiore | 0:bb4e812f7c97 | 583 | new_ph.obj_id = objix_p_hdr->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG; |
mfiore | 0:bb4e812f7c97 | 584 | new_ph.span_ix = data_spix_offset + i; |
mfiore | 0:bb4e812f7c97 | 585 | res = spiffs_page_allocate_data(fs, new_ph.obj_id, &new_ph, 0, 0, 0, 1, &data_pix); |
mfiore | 0:bb4e812f7c97 | 586 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 587 | SPIFFS_CHECK_DBG("PA: FIXUP: found no existing data page, created new @ %04x\n", data_pix); |
mfiore | 0:bb4e812f7c97 | 588 | } |
mfiore | 0:bb4e812f7c97 | 589 | // remap index |
mfiore | 0:bb4e812f7c97 | 590 | SPIFFS_CHECK_DBG("PA: FIXUP: rewriting index pix %04x\n", cur_pix); |
mfiore | 0:bb4e812f7c97 | 591 | res = spiffs_rewrite_index(fs, objix_p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG, |
mfiore | 0:bb4e812f7c97 | 592 | data_spix_offset + i, data_pix, cur_pix); |
mfiore | 0:bb4e812f7c97 | 593 | if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) { |
mfiore | 0:bb4e812f7c97 | 594 | // index bad also, cannot mend this file |
mfiore | 0:bb4e812f7c97 | 595 | SPIFFS_CHECK_DBG("PA: FIXUP: index bad %i, cannot mend - delete object\n", res); |
mfiore | 0:bb4e812f7c97 | 596 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, objix_p_hdr->obj_id, 0); |
mfiore | 0:bb4e812f7c97 | 597 | // delete file |
mfiore | 0:bb4e812f7c97 | 598 | res = spiffs_page_delete(fs, cur_pix); |
mfiore | 0:bb4e812f7c97 | 599 | } else { |
mfiore | 0:bb4e812f7c97 | 600 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, objix_p_hdr->obj_id, objix_p_hdr->span_ix); |
mfiore | 0:bb4e812f7c97 | 601 | } |
mfiore | 0:bb4e812f7c97 | 602 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 603 | restart = 1; |
mfiore | 0:bb4e812f7c97 | 604 | |
mfiore | 0:bb4e812f7c97 | 605 | } else if (rpix_within_range) { |
mfiore | 0:bb4e812f7c97 | 606 | |
mfiore | 0:bb4e812f7c97 | 607 | // valid reference |
mfiore | 0:bb4e812f7c97 | 608 | // read referenced page header |
mfiore | 0:bb4e812f7c97 | 609 | spiffs_page_header rp_hdr; |
mfiore | 0:bb4e812f7c97 | 610 | res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, |
mfiore | 0:bb4e812f7c97 | 611 | 0, SPIFFS_PAGE_TO_PADDR(fs, rpix), sizeof(spiffs_page_header), (u8_t*)&rp_hdr); |
mfiore | 0:bb4e812f7c97 | 612 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 613 | |
mfiore | 0:bb4e812f7c97 | 614 | // cross reference page header check |
mfiore | 0:bb4e812f7c97 | 615 | if (rp_hdr.obj_id != (p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) || |
mfiore | 0:bb4e812f7c97 | 616 | rp_hdr.span_ix != data_spix_offset + i || |
mfiore | 0:bb4e812f7c97 | 617 | (rp_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_USED)) != |
mfiore | 0:bb4e812f7c97 | 618 | (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_INDEX)) { |
mfiore | 0:bb4e812f7c97 | 619 | SPIFFS_CHECK_DBG("PA: pix %04x has inconsistent page header ix id/span:%04x/%04x, ref id/span:%04x/%04x flags:%02x\n", |
mfiore | 0:bb4e812f7c97 | 620 | rpix, p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, data_spix_offset + i, |
mfiore | 0:bb4e812f7c97 | 621 | rp_hdr.obj_id, rp_hdr.span_ix, rp_hdr.flags); |
mfiore | 0:bb4e812f7c97 | 622 | // try finding correct page |
mfiore | 0:bb4e812f7c97 | 623 | spiffs_page_ix data_pix; |
mfiore | 0:bb4e812f7c97 | 624 | res = spiffs_obj_lu_find_id_and_span(fs, p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, |
mfiore | 0:bb4e812f7c97 | 625 | data_spix_offset + i, rpix, &data_pix); |
mfiore | 0:bb4e812f7c97 | 626 | if (res == SPIFFS_ERR_NOT_FOUND) { |
mfiore | 0:bb4e812f7c97 | 627 | res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 628 | data_pix = 0; |
mfiore | 0:bb4e812f7c97 | 629 | } |
mfiore | 0:bb4e812f7c97 | 630 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 631 | if (data_pix == 0) { |
mfiore | 0:bb4e812f7c97 | 632 | // not found, this index is badly borked |
mfiore | 0:bb4e812f7c97 | 633 | SPIFFS_CHECK_DBG("PA: FIXUP: index bad, delete object id %04x\n", p_hdr.obj_id); |
mfiore | 0:bb4e812f7c97 | 634 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0); |
mfiore | 0:bb4e812f7c97 | 635 | res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id); |
mfiore | 0:bb4e812f7c97 | 636 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 637 | break; |
mfiore | 0:bb4e812f7c97 | 638 | } else { |
mfiore | 0:bb4e812f7c97 | 639 | // found it, so rewrite index |
mfiore | 0:bb4e812f7c97 | 640 | SPIFFS_CHECK_DBG("PA: FIXUP: found correct data pix %04x, rewrite ix pix %04x id %04x\n", |
mfiore | 0:bb4e812f7c97 | 641 | data_pix, cur_pix, p_hdr.obj_id); |
mfiore | 0:bb4e812f7c97 | 642 | res = spiffs_rewrite_index(fs, p_hdr.obj_id, data_spix_offset + i, data_pix, cur_pix); |
mfiore | 0:bb4e812f7c97 | 643 | if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) { |
mfiore | 0:bb4e812f7c97 | 644 | // index bad also, cannot mend this file |
mfiore | 0:bb4e812f7c97 | 645 | SPIFFS_CHECK_DBG("PA: FIXUP: index bad %i, cannot mend!\n", res); |
mfiore | 0:bb4e812f7c97 | 646 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0); |
mfiore | 0:bb4e812f7c97 | 647 | res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id); |
mfiore | 0:bb4e812f7c97 | 648 | } else { |
mfiore | 0:bb4e812f7c97 | 649 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, p_hdr.obj_id, p_hdr.span_ix); |
mfiore | 0:bb4e812f7c97 | 650 | } |
mfiore | 0:bb4e812f7c97 | 651 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 652 | restart = 1; |
mfiore | 0:bb4e812f7c97 | 653 | } |
mfiore | 0:bb4e812f7c97 | 654 | } |
mfiore | 0:bb4e812f7c97 | 655 | else { |
mfiore | 0:bb4e812f7c97 | 656 | // mark rpix as referenced |
mfiore | 0:bb4e812f7c97 | 657 | const u32_t rpix_byte_ix = (rpix - pix_offset) / (8/bits); |
mfiore | 0:bb4e812f7c97 | 658 | const u8_t rpix_bit_ix = (rpix & ((8/bits)-1)) * bits; |
mfiore | 0:bb4e812f7c97 | 659 | if (fs->work[rpix_byte_ix] & (1<<(rpix_bit_ix + 1))) { |
mfiore | 0:bb4e812f7c97 | 660 | SPIFFS_CHECK_DBG("PA: pix %04x multiple referenced from page %04x\n", |
mfiore | 0:bb4e812f7c97 | 661 | rpix, cur_pix); |
mfiore | 0:bb4e812f7c97 | 662 | // Here, we should have fixed all broken references - getting this means there |
mfiore | 0:bb4e812f7c97 | 663 | // must be multiple files with same object id. Only solution is to delete |
mfiore | 0:bb4e812f7c97 | 664 | // the object which is referring to this page |
mfiore | 0:bb4e812f7c97 | 665 | SPIFFS_CHECK_DBG("PA: FIXUP: removing object %04x and page %04x\n", |
mfiore | 0:bb4e812f7c97 | 666 | p_hdr.obj_id, cur_pix); |
mfiore | 0:bb4e812f7c97 | 667 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0); |
mfiore | 0:bb4e812f7c97 | 668 | res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id); |
mfiore | 0:bb4e812f7c97 | 669 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 670 | // extra precaution, delete this page also |
mfiore | 0:bb4e812f7c97 | 671 | res = spiffs_page_delete(fs, cur_pix); |
mfiore | 0:bb4e812f7c97 | 672 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 673 | restart = 1; |
mfiore | 0:bb4e812f7c97 | 674 | } |
mfiore | 0:bb4e812f7c97 | 675 | fs->work[rpix_byte_ix] |= (1<<(rpix_bit_ix + 1)); |
mfiore | 0:bb4e812f7c97 | 676 | } |
mfiore | 0:bb4e812f7c97 | 677 | } |
mfiore | 0:bb4e812f7c97 | 678 | } // for all index entries |
mfiore | 0:bb4e812f7c97 | 679 | } // found index |
mfiore | 0:bb4e812f7c97 | 680 | |
mfiore | 0:bb4e812f7c97 | 681 | // next page |
mfiore | 0:bb4e812f7c97 | 682 | cur_pix++; |
mfiore | 0:bb4e812f7c97 | 683 | } |
mfiore | 0:bb4e812f7c97 | 684 | // next block |
mfiore | 0:bb4e812f7c97 | 685 | cur_block++; |
mfiore | 0:bb4e812f7c97 | 686 | } |
mfiore | 0:bb4e812f7c97 | 687 | // check consistency bitmap |
mfiore | 0:bb4e812f7c97 | 688 | if (!restart) { |
mfiore | 0:bb4e812f7c97 | 689 | spiffs_page_ix objix_pix; |
mfiore | 0:bb4e812f7c97 | 690 | spiffs_page_ix rpix; |
mfiore | 0:bb4e812f7c97 | 691 | |
mfiore | 0:bb4e812f7c97 | 692 | int byte_ix; |
mfiore | 0:bb4e812f7c97 | 693 | int bit_ix; |
mfiore | 0:bb4e812f7c97 | 694 | for (byte_ix = 0; !restart && byte_ix < SPIFFS_CFG_LOG_PAGE_SZ(fs); byte_ix++) { |
mfiore | 0:bb4e812f7c97 | 695 | for (bit_ix = 0; !restart && bit_ix < 8/bits; bit_ix ++) { |
mfiore | 0:bb4e812f7c97 | 696 | u8_t bitmask = (fs->work[byte_ix] >> (bit_ix * bits)) & 0x7; |
mfiore | 0:bb4e812f7c97 | 697 | spiffs_page_ix cur_pix = pix_offset + byte_ix * (8/bits) + bit_ix; |
mfiore | 0:bb4e812f7c97 | 698 | |
mfiore | 0:bb4e812f7c97 | 699 | // 000 ok - free, unreferenced, not index |
mfiore | 0:bb4e812f7c97 | 700 | |
mfiore | 0:bb4e812f7c97 | 701 | if (bitmask == 0x1) { |
mfiore | 0:bb4e812f7c97 | 702 | |
mfiore | 0:bb4e812f7c97 | 703 | // 001 |
mfiore | 0:bb4e812f7c97 | 704 | SPIFFS_CHECK_DBG("PA: pix %04x USED, UNREFERENCED, not index\n", cur_pix); |
mfiore | 0:bb4e812f7c97 | 705 | |
mfiore | 0:bb4e812f7c97 | 706 | u8_t rewrite_ix_to_this = 0; |
mfiore | 0:bb4e812f7c97 | 707 | u8_t delete_page = 0; |
mfiore | 0:bb4e812f7c97 | 708 | // check corresponding object index entry |
mfiore | 0:bb4e812f7c97 | 709 | spiffs_page_header p_hdr; |
mfiore | 0:bb4e812f7c97 | 710 | res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, |
mfiore | 0:bb4e812f7c97 | 711 | 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr); |
mfiore | 0:bb4e812f7c97 | 712 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 713 | |
mfiore | 0:bb4e812f7c97 | 714 | res = spiffs_object_get_data_page_index_reference(fs, p_hdr.obj_id, p_hdr.span_ix, |
mfiore | 0:bb4e812f7c97 | 715 | &rpix, &objix_pix); |
mfiore | 0:bb4e812f7c97 | 716 | if (res == SPIFFS_OK) { |
mfiore | 0:bb4e812f7c97 | 717 | if (((rpix == (spiffs_page_ix)-1 || rpix > SPIFFS_MAX_PAGES(fs)) || (SPIFFS_IS_LOOKUP_PAGE(fs, rpix)))) { |
mfiore | 0:bb4e812f7c97 | 718 | // pointing to a bad page altogether, rewrite index to this |
mfiore | 0:bb4e812f7c97 | 719 | rewrite_ix_to_this = 1; |
mfiore | 0:bb4e812f7c97 | 720 | SPIFFS_CHECK_DBG("PA: corresponding ref is bad: %04x, rewrite to this %04x\n", rpix, cur_pix); |
mfiore | 0:bb4e812f7c97 | 721 | } else { |
mfiore | 0:bb4e812f7c97 | 722 | // pointing to something else, check what |
mfiore | 0:bb4e812f7c97 | 723 | spiffs_page_header rp_hdr; |
mfiore | 0:bb4e812f7c97 | 724 | res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, |
mfiore | 0:bb4e812f7c97 | 725 | 0, SPIFFS_PAGE_TO_PADDR(fs, rpix), sizeof(spiffs_page_header), (u8_t*)&rp_hdr); |
mfiore | 0:bb4e812f7c97 | 726 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 727 | if (((p_hdr.obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) == rp_hdr.obj_id) && |
mfiore | 0:bb4e812f7c97 | 728 | ((rp_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL)) == |
mfiore | 0:bb4e812f7c97 | 729 | (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_DELET))) { |
mfiore | 0:bb4e812f7c97 | 730 | // pointing to something else valid, just delete this page then |
mfiore | 0:bb4e812f7c97 | 731 | SPIFFS_CHECK_DBG("PA: corresponding ref is good but different: %04x, delete this %04x\n", rpix, cur_pix); |
mfiore | 0:bb4e812f7c97 | 732 | delete_page = 1; |
mfiore | 0:bb4e812f7c97 | 733 | } else { |
mfiore | 0:bb4e812f7c97 | 734 | // pointing to something weird, update index to point to this page instead |
mfiore | 0:bb4e812f7c97 | 735 | if (rpix != cur_pix) { |
mfiore | 0:bb4e812f7c97 | 736 | SPIFFS_CHECK_DBG("PA: corresponding ref is weird: %04x %s%s%s%s, rewrite this %04x\n", rpix, |
mfiore | 0:bb4e812f7c97 | 737 | (rp_hdr.flags & SPIFFS_PH_FLAG_INDEX) ? "" : "INDEX ", |
mfiore | 0:bb4e812f7c97 | 738 | (rp_hdr.flags & SPIFFS_PH_FLAG_DELET) ? "" : "DELETED ", |
mfiore | 0:bb4e812f7c97 | 739 | (rp_hdr.flags & SPIFFS_PH_FLAG_USED) ? "NOTUSED " : "", |
mfiore | 0:bb4e812f7c97 | 740 | (rp_hdr.flags & SPIFFS_PH_FLAG_FINAL) ? "NOTFINAL " : "", |
mfiore | 0:bb4e812f7c97 | 741 | cur_pix); |
mfiore | 0:bb4e812f7c97 | 742 | rewrite_ix_to_this = 1; |
mfiore | 0:bb4e812f7c97 | 743 | } else { |
mfiore | 0:bb4e812f7c97 | 744 | // should not happen, destined for fubar |
mfiore | 0:bb4e812f7c97 | 745 | } |
mfiore | 0:bb4e812f7c97 | 746 | } |
mfiore | 0:bb4e812f7c97 | 747 | } |
mfiore | 0:bb4e812f7c97 | 748 | } else if (res == SPIFFS_ERR_NOT_FOUND) { |
mfiore | 0:bb4e812f7c97 | 749 | SPIFFS_CHECK_DBG("PA: corresponding ref not found, delete %04x\n", cur_pix); |
mfiore | 0:bb4e812f7c97 | 750 | delete_page = 1; |
mfiore | 0:bb4e812f7c97 | 751 | res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 752 | } |
mfiore | 0:bb4e812f7c97 | 753 | |
mfiore | 0:bb4e812f7c97 | 754 | if (rewrite_ix_to_this) { |
mfiore | 0:bb4e812f7c97 | 755 | // if pointing to invalid page, redirect index to this page |
mfiore | 0:bb4e812f7c97 | 756 | SPIFFS_CHECK_DBG("PA: FIXUP: rewrite index id %04x data spix %04x to point to this pix: %04x\n", |
mfiore | 0:bb4e812f7c97 | 757 | p_hdr.obj_id, p_hdr.span_ix, cur_pix); |
mfiore | 0:bb4e812f7c97 | 758 | res = spiffs_rewrite_index(fs, p_hdr.obj_id, p_hdr.span_ix, cur_pix, objix_pix); |
mfiore | 0:bb4e812f7c97 | 759 | if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) { |
mfiore | 0:bb4e812f7c97 | 760 | // index bad also, cannot mend this file |
mfiore | 0:bb4e812f7c97 | 761 | SPIFFS_CHECK_DBG("PA: FIXUP: index bad %i, cannot mend!\n", res); |
mfiore | 0:bb4e812f7c97 | 762 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0); |
mfiore | 0:bb4e812f7c97 | 763 | res = spiffs_page_delete(fs, cur_pix); |
mfiore | 0:bb4e812f7c97 | 764 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 765 | res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id); |
mfiore | 0:bb4e812f7c97 | 766 | } else { |
mfiore | 0:bb4e812f7c97 | 767 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, p_hdr.obj_id, p_hdr.span_ix); |
mfiore | 0:bb4e812f7c97 | 768 | } |
mfiore | 0:bb4e812f7c97 | 769 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 770 | restart = 1; |
mfiore | 0:bb4e812f7c97 | 771 | continue; |
mfiore | 0:bb4e812f7c97 | 772 | } else if (delete_page) { |
mfiore | 0:bb4e812f7c97 | 773 | SPIFFS_CHECK_DBG("PA: FIXUP: deleting page %04x\n", cur_pix); |
mfiore | 0:bb4e812f7c97 | 774 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_PAGE, cur_pix, 0); |
mfiore | 0:bb4e812f7c97 | 775 | res = spiffs_page_delete(fs, cur_pix); |
mfiore | 0:bb4e812f7c97 | 776 | } |
mfiore | 0:bb4e812f7c97 | 777 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 778 | } |
mfiore | 0:bb4e812f7c97 | 779 | if (bitmask == 0x2) { |
mfiore | 0:bb4e812f7c97 | 780 | |
mfiore | 0:bb4e812f7c97 | 781 | // 010 |
mfiore | 0:bb4e812f7c97 | 782 | SPIFFS_CHECK_DBG("PA: pix %04x FREE, REFERENCED, not index\n", cur_pix); |
mfiore | 0:bb4e812f7c97 | 783 | |
mfiore | 0:bb4e812f7c97 | 784 | // no op, this should be taken care of when checking valid references |
mfiore | 0:bb4e812f7c97 | 785 | } |
mfiore | 0:bb4e812f7c97 | 786 | |
mfiore | 0:bb4e812f7c97 | 787 | // 011 ok - busy, referenced, not index |
mfiore | 0:bb4e812f7c97 | 788 | |
mfiore | 0:bb4e812f7c97 | 789 | if (bitmask == 0x4) { |
mfiore | 0:bb4e812f7c97 | 790 | |
mfiore | 0:bb4e812f7c97 | 791 | // 100 |
mfiore | 0:bb4e812f7c97 | 792 | SPIFFS_CHECK_DBG("PA: pix %04x FREE, unreferenced, INDEX\n", cur_pix); |
mfiore | 0:bb4e812f7c97 | 793 | |
mfiore | 0:bb4e812f7c97 | 794 | // this should never happen, major fubar |
mfiore | 0:bb4e812f7c97 | 795 | } |
mfiore | 0:bb4e812f7c97 | 796 | |
mfiore | 0:bb4e812f7c97 | 797 | // 101 ok - busy, unreferenced, index |
mfiore | 0:bb4e812f7c97 | 798 | |
mfiore | 0:bb4e812f7c97 | 799 | if (bitmask == 0x6) { |
mfiore | 0:bb4e812f7c97 | 800 | |
mfiore | 0:bb4e812f7c97 | 801 | // 110 |
mfiore | 0:bb4e812f7c97 | 802 | SPIFFS_CHECK_DBG("PA: pix %04x FREE, REFERENCED, INDEX\n", cur_pix); |
mfiore | 0:bb4e812f7c97 | 803 | |
mfiore | 0:bb4e812f7c97 | 804 | // no op, this should be taken care of when checking valid references |
mfiore | 0:bb4e812f7c97 | 805 | } |
mfiore | 0:bb4e812f7c97 | 806 | if (bitmask == 0x7) { |
mfiore | 0:bb4e812f7c97 | 807 | |
mfiore | 0:bb4e812f7c97 | 808 | // 111 |
mfiore | 0:bb4e812f7c97 | 809 | SPIFFS_CHECK_DBG("PA: pix %04x USED, REFERENCED, INDEX\n", cur_pix); |
mfiore | 0:bb4e812f7c97 | 810 | |
mfiore | 0:bb4e812f7c97 | 811 | // no op, this should be taken care of when checking valid references |
mfiore | 0:bb4e812f7c97 | 812 | } |
mfiore | 0:bb4e812f7c97 | 813 | } |
mfiore | 0:bb4e812f7c97 | 814 | } |
mfiore | 0:bb4e812f7c97 | 815 | } |
mfiore | 0:bb4e812f7c97 | 816 | // next page range |
mfiore | 0:bb4e812f7c97 | 817 | if (!restart) { |
mfiore | 0:bb4e812f7c97 | 818 | pix_offset += pages_per_scan; |
mfiore | 0:bb4e812f7c97 | 819 | } |
mfiore | 0:bb4e812f7c97 | 820 | } // while page range not reached end |
mfiore | 0:bb4e812f7c97 | 821 | return res; |
mfiore | 0:bb4e812f7c97 | 822 | } |
mfiore | 0:bb4e812f7c97 | 823 | |
mfiore | 0:bb4e812f7c97 | 824 | // Checks consistency amongst all pages and fixes irregularities |
mfiore | 0:bb4e812f7c97 | 825 | s32_t spiffs_page_consistency_check(spiffs *fs) { |
mfiore | 0:bb4e812f7c97 | 826 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, 0, 0); |
mfiore | 0:bb4e812f7c97 | 827 | s32_t res = spiffs_page_consistency_check_i(fs); |
mfiore | 0:bb4e812f7c97 | 828 | if (res != SPIFFS_OK) { |
mfiore | 0:bb4e812f7c97 | 829 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_ERROR, res, 0); |
mfiore | 0:bb4e812f7c97 | 830 | } |
mfiore | 0:bb4e812f7c97 | 831 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, 256, 0); |
mfiore | 0:bb4e812f7c97 | 832 | return res; |
mfiore | 0:bb4e812f7c97 | 833 | } |
mfiore | 0:bb4e812f7c97 | 834 | |
mfiore | 0:bb4e812f7c97 | 835 | //--------------------------------------- |
mfiore | 0:bb4e812f7c97 | 836 | // Object index consistency |
mfiore | 0:bb4e812f7c97 | 837 | |
mfiore | 0:bb4e812f7c97 | 838 | // searches for given object id in temporary object id index, |
mfiore | 0:bb4e812f7c97 | 839 | // returns the index or -1 |
mfiore | 0:bb4e812f7c97 | 840 | static int spiffs_object_index_search(spiffs *fs, spiffs_obj_id obj_id) { |
mfiore | 0:bb4e812f7c97 | 841 | int i; |
mfiore | 0:bb4e812f7c97 | 842 | spiffs_obj_id *obj_table = (spiffs_obj_id *)fs->work; |
mfiore | 0:bb4e812f7c97 | 843 | obj_id &= ~SPIFFS_OBJ_ID_IX_FLAG; |
mfiore | 0:bb4e812f7c97 | 844 | for (i = 0; i < SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id); i++) { |
mfiore | 0:bb4e812f7c97 | 845 | if ((obj_table[i] & ~SPIFFS_OBJ_ID_IX_FLAG) == obj_id) { |
mfiore | 0:bb4e812f7c97 | 846 | return i; |
mfiore | 0:bb4e812f7c97 | 847 | } |
mfiore | 0:bb4e812f7c97 | 848 | } |
mfiore | 0:bb4e812f7c97 | 849 | return -1; |
mfiore | 0:bb4e812f7c97 | 850 | } |
mfiore | 0:bb4e812f7c97 | 851 | |
mfiore | 0:bb4e812f7c97 | 852 | s32_t spiffs_object_index_consistency_check_v(spiffs *fs, spiffs_obj_id obj_id, spiffs_block_ix cur_block, |
mfiore | 0:bb4e812f7c97 | 853 | int cur_entry, u32_t user_data, void *user_p) { |
mfiore | 0:bb4e812f7c97 | 854 | s32_t res_c = SPIFFS_VIS_COUNTINUE; |
mfiore | 0:bb4e812f7c97 | 855 | s32_t res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 856 | u32_t *log_ix = (u32_t *)user_p; |
mfiore | 0:bb4e812f7c97 | 857 | spiffs_obj_id *obj_table = (spiffs_obj_id *)fs->work; |
mfiore | 0:bb4e812f7c97 | 858 | |
mfiore | 0:bb4e812f7c97 | 859 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, |
mfiore | 0:bb4e812f7c97 | 860 | (cur_block * 256)/fs->block_count, 0); |
mfiore | 0:bb4e812f7c97 | 861 | |
mfiore | 0:bb4e812f7c97 | 862 | if (obj_id != SPIFFS_OBJ_ID_FREE && obj_id != SPIFFS_OBJ_ID_DELETED && (obj_id & SPIFFS_OBJ_ID_IX_FLAG)) { |
mfiore | 0:bb4e812f7c97 | 863 | spiffs_page_header p_hdr; |
mfiore | 0:bb4e812f7c97 | 864 | spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, cur_block, cur_entry); |
mfiore | 0:bb4e812f7c97 | 865 | |
mfiore | 0:bb4e812f7c97 | 866 | // load header |
mfiore | 0:bb4e812f7c97 | 867 | res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, |
mfiore | 0:bb4e812f7c97 | 868 | 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr); |
mfiore | 0:bb4e812f7c97 | 869 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 870 | |
mfiore | 0:bb4e812f7c97 | 871 | if (p_hdr.span_ix == 0 && |
mfiore | 0:bb4e812f7c97 | 872 | (p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) == |
mfiore | 0:bb4e812f7c97 | 873 | (SPIFFS_PH_FLAG_DELET)) { |
mfiore | 0:bb4e812f7c97 | 874 | SPIFFS_CHECK_DBG("IX: pix %04x, obj id:%04x spix:%04x header not fully deleted - deleting\n", |
mfiore | 0:bb4e812f7c97 | 875 | cur_pix, obj_id, p_hdr.span_ix); |
mfiore | 0:bb4e812f7c97 | 876 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_INDEX, SPIFFS_CHECK_DELETE_PAGE, cur_pix, obj_id); |
mfiore | 0:bb4e812f7c97 | 877 | res = spiffs_page_delete(fs, cur_pix); |
mfiore | 0:bb4e812f7c97 | 878 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 879 | return res_c; |
mfiore | 0:bb4e812f7c97 | 880 | } |
mfiore | 0:bb4e812f7c97 | 881 | |
mfiore | 0:bb4e812f7c97 | 882 | if ((p_hdr.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) == |
mfiore | 0:bb4e812f7c97 | 883 | (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) { |
mfiore | 0:bb4e812f7c97 | 884 | return res_c; |
mfiore | 0:bb4e812f7c97 | 885 | } |
mfiore | 0:bb4e812f7c97 | 886 | |
mfiore | 0:bb4e812f7c97 | 887 | if (p_hdr.span_ix == 0) { |
mfiore | 0:bb4e812f7c97 | 888 | // objix header page, register objid as reachable |
mfiore | 0:bb4e812f7c97 | 889 | int r = spiffs_object_index_search(fs, obj_id); |
mfiore | 0:bb4e812f7c97 | 890 | if (r == -1) { |
mfiore | 0:bb4e812f7c97 | 891 | // not registered, do it |
mfiore | 0:bb4e812f7c97 | 892 | obj_table[*log_ix] = obj_id & ~SPIFFS_OBJ_ID_IX_FLAG; |
mfiore | 0:bb4e812f7c97 | 893 | (*log_ix)++; |
mfiore | 0:bb4e812f7c97 | 894 | if (*log_ix >= SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id)) { |
mfiore | 0:bb4e812f7c97 | 895 | *log_ix = 0; |
mfiore | 0:bb4e812f7c97 | 896 | } |
mfiore | 0:bb4e812f7c97 | 897 | } |
mfiore | 0:bb4e812f7c97 | 898 | } else { // span index |
mfiore | 0:bb4e812f7c97 | 899 | // objix page, see if header can be found |
mfiore | 0:bb4e812f7c97 | 900 | int r = spiffs_object_index_search(fs, obj_id); |
mfiore | 0:bb4e812f7c97 | 901 | u8_t delete = 0; |
mfiore | 0:bb4e812f7c97 | 902 | if (r == -1) { |
mfiore | 0:bb4e812f7c97 | 903 | // not in temporary index, try finding it |
mfiore | 0:bb4e812f7c97 | 904 | spiffs_page_ix objix_hdr_pix; |
mfiore | 0:bb4e812f7c97 | 905 | res = spiffs_obj_lu_find_id_and_span(fs, obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &objix_hdr_pix); |
mfiore | 0:bb4e812f7c97 | 906 | res_c = SPIFFS_VIS_COUNTINUE_RELOAD; |
mfiore | 0:bb4e812f7c97 | 907 | if (res == SPIFFS_OK) { |
mfiore | 0:bb4e812f7c97 | 908 | // found, register as reachable |
mfiore | 0:bb4e812f7c97 | 909 | obj_table[*log_ix] = obj_id & ~SPIFFS_OBJ_ID_IX_FLAG; |
mfiore | 0:bb4e812f7c97 | 910 | } else if (res == SPIFFS_ERR_NOT_FOUND) { |
mfiore | 0:bb4e812f7c97 | 911 | // not found, register as unreachable |
mfiore | 0:bb4e812f7c97 | 912 | delete = 1; |
mfiore | 0:bb4e812f7c97 | 913 | obj_table[*log_ix] = obj_id | SPIFFS_OBJ_ID_IX_FLAG; |
mfiore | 0:bb4e812f7c97 | 914 | } else { |
mfiore | 0:bb4e812f7c97 | 915 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 916 | } |
mfiore | 0:bb4e812f7c97 | 917 | (*log_ix)++; |
mfiore | 0:bb4e812f7c97 | 918 | if (*log_ix >= SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id)) { |
mfiore | 0:bb4e812f7c97 | 919 | *log_ix = 0; |
mfiore | 0:bb4e812f7c97 | 920 | } |
mfiore | 0:bb4e812f7c97 | 921 | } else { |
mfiore | 0:bb4e812f7c97 | 922 | // in temporary index, check reachable flag |
mfiore | 0:bb4e812f7c97 | 923 | if ((obj_table[r] & SPIFFS_OBJ_ID_IX_FLAG)) { |
mfiore | 0:bb4e812f7c97 | 924 | // registered as unreachable |
mfiore | 0:bb4e812f7c97 | 925 | delete = 1; |
mfiore | 0:bb4e812f7c97 | 926 | } |
mfiore | 0:bb4e812f7c97 | 927 | } |
mfiore | 0:bb4e812f7c97 | 928 | |
mfiore | 0:bb4e812f7c97 | 929 | if (delete) { |
mfiore | 0:bb4e812f7c97 | 930 | SPIFFS_CHECK_DBG("IX: FIXUP: pix %04x, obj id:%04x spix:%04x is orphan index - deleting\n", |
mfiore | 0:bb4e812f7c97 | 931 | cur_pix, obj_id, p_hdr.span_ix); |
mfiore | 0:bb4e812f7c97 | 932 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_INDEX, SPIFFS_CHECK_DELETE_ORPHANED_INDEX, cur_pix, obj_id); |
mfiore | 0:bb4e812f7c97 | 933 | res = spiffs_page_delete(fs, cur_pix); |
mfiore | 0:bb4e812f7c97 | 934 | SPIFFS_CHECK_RES(res); |
mfiore | 0:bb4e812f7c97 | 935 | } |
mfiore | 0:bb4e812f7c97 | 936 | } // span index |
mfiore | 0:bb4e812f7c97 | 937 | } // valid object index id |
mfiore | 0:bb4e812f7c97 | 938 | |
mfiore | 0:bb4e812f7c97 | 939 | return res_c; |
mfiore | 0:bb4e812f7c97 | 940 | } |
mfiore | 0:bb4e812f7c97 | 941 | |
mfiore | 0:bb4e812f7c97 | 942 | // Removes orphaned and partially deleted index pages. |
mfiore | 0:bb4e812f7c97 | 943 | // Scans for index pages. When an index page is found, corresponding index header is searched for. |
mfiore | 0:bb4e812f7c97 | 944 | // If no such page exists, the index page cannot be reached as no index header exists and must be |
mfiore | 0:bb4e812f7c97 | 945 | // deleted. |
mfiore | 0:bb4e812f7c97 | 946 | s32_t spiffs_object_index_consistency_check(spiffs *fs) { |
mfiore | 0:bb4e812f7c97 | 947 | s32_t res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 948 | // impl note: |
mfiore | 0:bb4e812f7c97 | 949 | // fs->work is used for a temporary object index memory, listing found object ids and |
mfiore | 0:bb4e812f7c97 | 950 | // indicating whether they can be reached or not. Acting as a fifo if object ids cannot fit. |
mfiore | 0:bb4e812f7c97 | 951 | // In the temporary object index memory, SPIFFS_OBJ_ID_IX_FLAG bit is used to indicate |
mfiore | 0:bb4e812f7c97 | 952 | // a reachable/unreachable object id. |
mfiore | 0:bb4e812f7c97 | 953 | memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs)); |
mfiore | 0:bb4e812f7c97 | 954 | u32_t obj_id_log_ix = 0; |
mfiore | 0:bb4e812f7c97 | 955 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, 0, 0); |
mfiore | 0:bb4e812f7c97 | 956 | res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_object_index_consistency_check_v, 0, &obj_id_log_ix, |
mfiore | 0:bb4e812f7c97 | 957 | 0, 0); |
mfiore | 0:bb4e812f7c97 | 958 | if (res == SPIFFS_VIS_END) { |
mfiore | 0:bb4e812f7c97 | 959 | res = SPIFFS_OK; |
mfiore | 0:bb4e812f7c97 | 960 | } |
mfiore | 0:bb4e812f7c97 | 961 | if (res != SPIFFS_OK) { |
mfiore | 0:bb4e812f7c97 | 962 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_INDEX, SPIFFS_CHECK_ERROR, res, 0); |
mfiore | 0:bb4e812f7c97 | 963 | } |
mfiore | 0:bb4e812f7c97 | 964 | if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, 256, 0); |
mfiore | 0:bb4e812f7c97 | 965 | return res; |
mfiore | 0:bb4e812f7c97 | 966 | } |