mirror of
https://github.com/pellepl/spiffs.git
synced 2026-11-08 23:40:54 +00:00
changed ways of gc, optimized
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -32,6 +32,8 @@ MKDIR = mkdir -p
|
||||
|
||||
FILES = main.c \
|
||||
test_spiffs.c \
|
||||
test_dev.c \
|
||||
test_check.c \
|
||||
test_hydrogen.c \
|
||||
testsuites.c \
|
||||
testrunner.c
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
#define SPIFFS_DBG(...)
|
||||
#define SPIFFS_GC_DBG(...)
|
||||
#define SPIFFS_CACHE_DBG(...)
|
||||
#define SPIFFS_CHECK_DBG(...)
|
||||
|
||||
// define maximum number of gc runs to perform to reach desired free pages
|
||||
#define SPIFFS_GC_MAX_RUNS 3
|
||||
@@ -49,6 +50,9 @@
|
||||
#define SPIFFS_GC_HEUR_W_DELET (10)
|
||||
// garbage collecting heuristics - weight used for used pages
|
||||
#define SPIFFS_GC_HEUR_W_USED (-1)
|
||||
// garbage collecting heuristics - weight used for time between
|
||||
// last erased and erase of this block
|
||||
#define SPIFFS_GC_HEUR_W_ERASE_AGE (30)
|
||||
|
||||
// object name length
|
||||
#define SPIFFS_OBJ_NAME_LEN (32 - sizeof(spiffs_obj_type))
|
||||
@@ -78,7 +82,7 @@ typedef u16_t spiffs_span_ix;
|
||||
typedef u8_t spiffs_obj_type;
|
||||
|
||||
// enable if only one spiffs instance with constant configuration will exist
|
||||
// on the target, this will remove calculations and memory accesses
|
||||
// on the target, this will reduce calculations, flash and memory accesses
|
||||
//#define SPIFFS_SINGLETON
|
||||
|
||||
#ifdef SPIFFS_SINGLETON
|
||||
@@ -91,4 +95,13 @@ typedef u8_t spiffs_obj_type;
|
||||
#define SPIFFS_CFG_LOG_BLOCK_SZ(ignore) (65536)
|
||||
#endif
|
||||
|
||||
#define SPIFFS_TEST_VISUALISATION 1
|
||||
#if SPIFFS_TEST_VISUALISATION
|
||||
#define spiffs_printf(...) printf(__VA_ARGS__)
|
||||
#define SPIFFS_TEST_VIS_FREE_STR "_"
|
||||
#define SPIFFS_TEST_VIS_DELE_STR "/"
|
||||
#define SPIFFS_TEST_VIS_INDX_STR(id) "i"
|
||||
#define SPIFFS_TEST_VIS_DATA_STR(id) "d"
|
||||
#endif
|
||||
|
||||
#endif /* SPIFFS_CONFIG_H_ */
|
||||
|
||||
+53
-5
@@ -25,10 +25,17 @@
|
||||
#define SPIFFS_ERR_FILE_DELETED -10009
|
||||
#define SPIFFS_ERR_BAD_DESCRIPTOR -10010
|
||||
#define SPIFFS_ERR_IS_INDEX -10011
|
||||
#define SPIFFS_ERR_INDEX_SPAN_MISMATCH -10012
|
||||
#define SPIFFS_ERR_INDEX_WRONG_ID -10013
|
||||
#define SPIFFS_ERR_IS_FREE -10012
|
||||
#define SPIFFS_ERR_INDEX_SPAN_MISMATCH -10013
|
||||
#define SPIFFS_ERR_DATA_SPAN_MISMATCH -10014
|
||||
#define SPIFFS_ERR_DATA_WRONG_ID -10015
|
||||
#define SPIFFS_ERR_INDEX_REF_FREE -10015
|
||||
#define SPIFFS_ERR_INDEX_REF_LU -10016
|
||||
#define SPIFFS_ERR_INDEX_REF_INVALID -10017
|
||||
#define SPIFFS_ERR_INDEX_FREE -10018
|
||||
#define SPIFFS_ERR_INDEX_LU -10019
|
||||
#define SPIFFS_ERR_INDEX_INVALID -10020
|
||||
|
||||
#define SPIFFS_ERR_INTERNAL -10050
|
||||
|
||||
|
||||
// spi read call type
|
||||
@@ -38,6 +45,25 @@ typedef s32_t (*spiffs_write)(u32_t addr, u32_t size, u8_t *src);
|
||||
// spi erase call type
|
||||
typedef s32_t (*spiffs_erase)(u32_t addr, u32_t size);
|
||||
|
||||
|
||||
typedef enum {
|
||||
SPIFFS_CHECK_LOOKUP = 0,
|
||||
SPIFFS_CHECK_INDEX,
|
||||
SPIFFS_CHECK_PAGE
|
||||
} spiffs_check_type;
|
||||
|
||||
typedef enum {
|
||||
SPIFFS_CHECK_PROGRESS = 0,
|
||||
SPIFFS_CHECK_ERROR,
|
||||
SPIFFS_CHECK_FIX_INDEX,
|
||||
SPIFFS_CHECK_DELETE_ORPHANED_INDEX,
|
||||
SPIFFS_CHECK_DELETE_PAGE,
|
||||
SPIFFS_CHECK_DELETE_BAD_FILE,
|
||||
} spiffs_check_report;
|
||||
|
||||
typedef void (*spiffs_check_callback)(spiffs_check_type type, spiffs_check_report report,
|
||||
u32_t arg1, u32_t arg2);
|
||||
|
||||
// size of buffer on stack used when copying data
|
||||
#define SPIFFS_COPY_BUFFER_STACK (64)
|
||||
|
||||
@@ -51,6 +77,9 @@ typedef s32_t (*spiffs_erase)(u32_t addr, u32_t size);
|
||||
#ifndef SPIFFS_CACHE_DBG
|
||||
#define SPIFFS_CACHE_DBG(...) printf(__VA_ARGS__)
|
||||
#endif
|
||||
#ifndef SPIFFS_CHECK_DBG
|
||||
#define SPIFFS_CHECK_DBG(...) printf(__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#define SPIFFS_APPEND (1<<0)
|
||||
#define SPIFFS_TRUNC (1<<1)
|
||||
@@ -130,24 +159,37 @@ typedef struct {
|
||||
// available file descriptors
|
||||
u32_t fd_count;
|
||||
|
||||
// last error
|
||||
s32_t errno;
|
||||
|
||||
// current number of free blocks
|
||||
u32_t free_blocks;
|
||||
|
||||
// current number of busy pages
|
||||
u32_t stats_p_allocated;
|
||||
// current number of deleted pages
|
||||
u32_t stats_p_deleted;
|
||||
// flag indicating that garbage collector is cleaning
|
||||
u8_t cleaning;
|
||||
// max erase count amongst all blocks
|
||||
spiffs_obj_id max_erase_count;
|
||||
|
||||
#if SPIFFS_GC_STATS
|
||||
u32_t stats_gc_runs;
|
||||
#endif
|
||||
|
||||
#if SPIFFS_CACHE
|
||||
// cache memory
|
||||
void *cache;
|
||||
// cache size
|
||||
u32_t cache_size;
|
||||
#if SPIFFS_CACHE_STATS
|
||||
u32_t cache_hits;
|
||||
u32_t cache_misses;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// check callback function
|
||||
spiffs_check_callback check_cb_f;
|
||||
} spiffs;
|
||||
|
||||
typedef struct {
|
||||
@@ -185,7 +227,8 @@ typedef struct {
|
||||
*/
|
||||
s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
||||
u8_t *fd_space, u32_t fd_space_size,
|
||||
void *cache, u32_t cache_size);
|
||||
void *cache, u32_t cache_size,
|
||||
spiffs_check_callback check_cb_f);
|
||||
|
||||
void SPIFFS_unmount(spiffs *fs);
|
||||
|
||||
@@ -196,6 +239,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len);
|
||||
s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence);
|
||||
s32_t SPIFFS_remove(spiffs *fs, const char *path);
|
||||
s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh);
|
||||
s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s);
|
||||
s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s);
|
||||
s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh);
|
||||
void SPIFFS_close(spiffs *fs, spiffs_file fh);
|
||||
@@ -207,4 +251,8 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e);
|
||||
|
||||
s32_t SPIFFS_check(spiffs *fs);
|
||||
|
||||
#if SPIFFS_TEST_VISUALISATION
|
||||
s32_t SPIFFS_vis(spiffs *fs);
|
||||
#endif
|
||||
|
||||
#endif /* SPIFFS_H_ */
|
||||
|
||||
+19
-19
@@ -11,11 +11,11 @@
|
||||
#if SPIFFS_CACHE
|
||||
|
||||
static spiffs_cache_page *spiffs_cache_page_get(spiffs *fs, spiffs_page_ix pix) {
|
||||
spiffs_cache *cache = get_cache(fs);
|
||||
spiffs_cache *cache = spiffs_get_cache(fs);
|
||||
if ((cache->cpage_use_map & cache->cpage_use_mask) == 0) return 0;
|
||||
int i;
|
||||
for (i = 0; i < cache->cpage_count; i++) {
|
||||
spiffs_cache_page *cp = get_cache_page_hdr(fs, cache, i);
|
||||
spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i);
|
||||
if ((cache->cpage_use_map & (1<<i)) &&
|
||||
(cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 &&
|
||||
cp->pix == pix ) {
|
||||
@@ -30,13 +30,13 @@ static spiffs_cache_page *spiffs_cache_page_get(spiffs *fs, spiffs_page_ix pix)
|
||||
|
||||
static s32_t spiffs_cache_page_free(spiffs *fs, int ix, u8_t write_back) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
spiffs_cache *cache = get_cache(fs);
|
||||
spiffs_cache_page *cp = get_cache_page_hdr(fs, cache, ix);
|
||||
spiffs_cache *cache = spiffs_get_cache(fs);
|
||||
spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, ix);
|
||||
if (cache->cpage_use_map & (1<<ix)) {
|
||||
if (write_back &&
|
||||
(cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 &&
|
||||
(cp->flags & SPIFFS_CACHE_FLAG_DIRTY)) {
|
||||
u8_t *mem = get_cache_page(fs, cache, ix);
|
||||
u8_t *mem = spiffs_get_cache_page(fs, cache, ix);
|
||||
res = fs->cfg.hal_write_f(SPIFFS_PAGE_TO_PADDR(fs, cp->pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), mem);
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ static s32_t spiffs_cache_page_free(spiffs *fs, int ix, u8_t write_back) {
|
||||
|
||||
static s32_t spiffs_cache_page_remove_oldest(spiffs *fs, u8_t flag_mask, u8_t flags) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
spiffs_cache *cache = get_cache(fs);
|
||||
spiffs_cache *cache = spiffs_get_cache(fs);
|
||||
|
||||
if ((cache->cpage_use_map & cache->cpage_use_mask) != cache->cpage_use_mask) {
|
||||
// at least one free cpage
|
||||
@@ -67,7 +67,7 @@ static s32_t spiffs_cache_page_remove_oldest(spiffs *fs, u8_t flag_mask, u8_t fl
|
||||
int cand_ix = -1;
|
||||
u32_t oldest_val = 0;
|
||||
for (i = 0; i < cache->cpage_count; i++) {
|
||||
spiffs_cache_page *cp = get_cache_page_hdr(fs, cache, i);
|
||||
spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i);
|
||||
if ((cache->last_access - cp->last_access) > oldest_val &&
|
||||
(cp->flags & flag_mask) == flags) {
|
||||
oldest_val = cache->last_access - cp->last_access;
|
||||
@@ -83,7 +83,7 @@ static s32_t spiffs_cache_page_remove_oldest(spiffs *fs, u8_t flag_mask, u8_t fl
|
||||
}
|
||||
|
||||
static spiffs_cache_page *spiffs_cache_page_allocate(spiffs *fs) {
|
||||
spiffs_cache *cache = get_cache(fs);
|
||||
spiffs_cache *cache = spiffs_get_cache(fs);
|
||||
if (cache->cpage_use_map == 0xffffffff) {
|
||||
// out of cache memory
|
||||
return 0;
|
||||
@@ -91,7 +91,7 @@ static spiffs_cache_page *spiffs_cache_page_allocate(spiffs *fs) {
|
||||
int i;
|
||||
for (i = 0; i < cache->cpage_count; i++) {
|
||||
if ((cache->cpage_use_map & (1<<i)) == 0) {
|
||||
spiffs_cache_page *cp = get_cache_page_hdr(fs, cache, i);
|
||||
spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i);
|
||||
cache->cpage_use_map |= (1<<i);
|
||||
cp->last_access = cache->last_access;
|
||||
SPIFFS_CACHE_DBG("CACHE_ALLO: allocated cache page %i\n", i);
|
||||
@@ -119,7 +119,7 @@ s32_t spiffs_phys_rd(
|
||||
u32_t len,
|
||||
u8_t *dst) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
spiffs_cache *cache = get_cache(fs);
|
||||
spiffs_cache *cache = spiffs_get_cache(fs);
|
||||
spiffs_cache_page *cp = spiffs_cache_page_get(fs, SPIFFS_PADDR_TO_PAGE(fs, addr));
|
||||
cache->last_access++;
|
||||
if (cp) {
|
||||
@@ -148,12 +148,12 @@ s32_t spiffs_phys_rd(
|
||||
s32_t res2 = fs->cfg.hal_read_f(
|
||||
addr - SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr),
|
||||
SPIFFS_CFG_LOG_PAGE_SZ(fs),
|
||||
get_cache_page(fs, cache, cp->ix));
|
||||
spiffs_get_cache_page(fs, cache, cp->ix));
|
||||
if (res2 != SPIFFS_OK) {
|
||||
res = res2;
|
||||
}
|
||||
}
|
||||
u8_t *mem = get_cache_page(fs, cache, cp->ix);
|
||||
u8_t *mem = spiffs_get_cache_page(fs, cache, cp->ix);
|
||||
memcpy(dst, &mem[SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr)], len);
|
||||
return res;
|
||||
}
|
||||
@@ -166,10 +166,10 @@ s32_t spiffs_phys_wr(
|
||||
u32_t len,
|
||||
u8_t *src) {
|
||||
spiffs_page_ix pix = SPIFFS_PADDR_TO_PAGE(fs, addr);
|
||||
spiffs_cache *cache = get_cache(fs);
|
||||
spiffs_cache *cache = spiffs_get_cache(fs);
|
||||
spiffs_cache_page *cp = spiffs_cache_page_get(fs, pix);
|
||||
|
||||
if (cp) {
|
||||
if (cp && (op & SPIFFS_OP_COM_MASK) != SPIFFS_OP_C_WRTHRU) {
|
||||
// have a cache page
|
||||
// copy in data to cache page
|
||||
|
||||
@@ -180,7 +180,7 @@ s32_t spiffs_phys_wr(
|
||||
return fs->cfg.hal_write_f(addr, len, src);
|
||||
}
|
||||
|
||||
u8_t *mem = get_cache_page(fs, cache, cp->ix);
|
||||
u8_t *mem = spiffs_get_cache_page(fs, cache, cp->ix);
|
||||
memcpy(&mem[SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr)], src, len);
|
||||
|
||||
cache->last_access++;
|
||||
@@ -200,7 +200,7 @@ s32_t spiffs_phys_wr(
|
||||
|
||||
#if SPIFFS_CACHE_WR
|
||||
spiffs_cache_page *spiffs_cache_page_get_by_fd(spiffs *fs, spiffs_fd *fd) {
|
||||
spiffs_cache *cache = get_cache(fs);
|
||||
spiffs_cache *cache = spiffs_get_cache(fs);
|
||||
|
||||
if ((cache->cpage_use_map & cache->cpage_use_mask) == 0) {
|
||||
// all cpages free, no cpage cannot be assigned to obj_id
|
||||
@@ -209,7 +209,7 @@ spiffs_cache_page *spiffs_cache_page_get_by_fd(spiffs *fs, spiffs_fd *fd) {
|
||||
|
||||
int i;
|
||||
for (i = 0; i < cache->cpage_count; i++) {
|
||||
spiffs_cache_page *cp = get_cache_page_hdr(fs, cache, i);
|
||||
spiffs_cache_page *cp = spiffs_get_cache_page_hdr(fs, cache, i);
|
||||
if ((cache->cpage_use_map & (1<<i)) &&
|
||||
(cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) &&
|
||||
cp->obj_id == fd->obj_id) {
|
||||
@@ -276,13 +276,13 @@ void spiffs_cache_init(spiffs *fs) {
|
||||
cache.cpage_use_mask = cache_mask;
|
||||
memcpy(fs->cache, &cache, sizeof(spiffs_cache));
|
||||
|
||||
spiffs_cache *c = get_cache(fs);
|
||||
spiffs_cache *c = spiffs_get_cache(fs);
|
||||
|
||||
memset(c->cpages, 0, c->cpage_count * SPIFFS_CACHE_PAGE_SIZE(fs));
|
||||
|
||||
c->cpage_use_map &= ~(c->cpage_use_mask);
|
||||
for (i = 0; i < cache.cpage_count; i++) {
|
||||
get_cache_page_hdr(fs, c, i)->ix = i;
|
||||
spiffs_get_cache_page_hdr(fs, c, i)->ix = i;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+843
-129
File diff suppressed because it is too large
Load Diff
+203
-72
@@ -1,6 +1,90 @@
|
||||
#include "spiffs.h"
|
||||
#include "spiffs_nucleus.h"
|
||||
|
||||
s32_t spiffs_gc_quick(
|
||||
spiffs *fs) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
u32_t blocks = fs->block_count;
|
||||
spiffs_block_ix cur_block = 0;
|
||||
u32_t cur_block_addr = SPIFFS_CFG_PHYS_ADDR(fs);
|
||||
int cur_entry = 0;
|
||||
spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
|
||||
|
||||
u32_t entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
|
||||
|
||||
// find fully deleted blocks
|
||||
// check each block
|
||||
while (res == SPIFFS_OK && blocks--) {
|
||||
u16_t deleted_pages_in_block = 0;
|
||||
|
||||
int obj_lookup_page = 0;
|
||||
// check each object lookup page
|
||||
while (res == SPIFFS_OK && obj_lookup_page < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
|
||||
int entry_offset = obj_lookup_page * entries_per_page;
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
|
||||
0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
|
||||
// check each entry
|
||||
while (res == SPIFFS_OK &&
|
||||
cur_entry - entry_offset < entries_per_page && cur_entry < SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
|
||||
spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
|
||||
if (obj_id == SPIFFS_OBJ_ID_FREE) {
|
||||
obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs);
|
||||
break;
|
||||
} else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
|
||||
deleted_pages_in_block++;
|
||||
} else {
|
||||
obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs);
|
||||
break;
|
||||
}
|
||||
cur_entry++;
|
||||
} // per entry
|
||||
obj_lookup_page++;
|
||||
} // per object lookup page
|
||||
|
||||
if (res == SPIFFS_OK && deleted_pages_in_block == SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
|
||||
// found a fully deleted block
|
||||
fs->stats_p_deleted -= deleted_pages_in_block;
|
||||
|
||||
u32_t addr = SPIFFS_BLOCK_TO_PADDR(fs, cur_block);
|
||||
s32_t size = SPIFFS_CFG_LOG_BLOCK_SZ(fs);
|
||||
|
||||
SPIFFS_GC_DBG("gc_check: erase block %i\n", cur_block);
|
||||
|
||||
while (size > 0) {
|
||||
SPIFFS_GC_DBG("gc_check: erase %08x:%08x\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
|
||||
res = fs->cfg.hal_erase_f(addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
|
||||
addr += SPIFFS_CFG_PHYS_ERASE_SZ(fs);
|
||||
size -= SPIFFS_CFG_PHYS_ERASE_SZ(fs);
|
||||
}
|
||||
fs->free_blocks++;
|
||||
|
||||
// register erase count for this block
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_C_UPDT | SPIFFS_OP_T_OBJ_LU2, 0,
|
||||
SPIFFS_ERASE_COUNT_PADDR(fs, cur_block),
|
||||
sizeof(spiffs_obj_id), (u8_t *)&fs->max_erase_count);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
fs->max_erase_count++;
|
||||
|
||||
#if SPIFFS_CACHE
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < SPIFFS_PAGES_PER_BLOCK(fs); i++) {
|
||||
spiffs_cache_drop_page(fs, SPIFFS_PAGE_FOR_BLOCK(fs, cur_block) + i);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
cur_entry = 0;
|
||||
cur_block++;
|
||||
cur_block_addr += SPIFFS_CFG_LOG_BLOCK_SZ(fs);
|
||||
} // per block
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
s32_t spiffs_gc_check(
|
||||
spiffs *fs,
|
||||
u32_t len) {
|
||||
@@ -10,13 +94,15 @@ s32_t spiffs_gc_check(
|
||||
- fs->stats_p_allocated - fs->stats_p_deleted;
|
||||
int tries = 0;
|
||||
|
||||
if (fs->free_blocks > 2 &&
|
||||
if (fs->free_blocks > 3 &&
|
||||
len < free_pages * SPIFFS_DATA_PAGE_SIZE(fs)) {
|
||||
return SPIFFS_OK;
|
||||
}
|
||||
|
||||
//printf("gcing started %i dirty, blocks %i free, want %i bytes\n", fs->stats_p_allocated + fs->stats_p_deleted, fs->free_blocks, len);
|
||||
|
||||
do {
|
||||
SPIFFS_GC_DBG("\ngc_check #i: run gc free_blocks:%i pfree:%i pallo:%i pdele:%i [%i] len:%i of %i\n",
|
||||
SPIFFS_GC_DBG("\ngc_check #%i: run gc free_blocks:%i pfree:%i pallo:%i pdele:%i [%i] len:%i of %i\n",
|
||||
tries,
|
||||
fs->free_blocks, free_pages, fs->stats_p_allocated, fs->stats_p_deleted, (free_pages+fs->stats_p_allocated+fs->stats_p_deleted),
|
||||
len, free_pages*SPIFFS_DATA_PAGE_SIZE(fs));
|
||||
@@ -34,8 +120,15 @@ s32_t spiffs_gc_check(
|
||||
fs->stats_gc_runs++;
|
||||
#endif
|
||||
cand = cands[0];
|
||||
fs->cleaning = 1;
|
||||
//printf("gcing: cleaning block %i\n", cand);
|
||||
res = spiffs_gc_clean(fs, cand);
|
||||
SPIFFS_GC_DBG("gc_check: cleaning block %i, result %i\n", cand, res);
|
||||
fs->cleaning = 0;
|
||||
if (res < 0) {
|
||||
SPIFFS_GC_DBG("gc_check: cleaning block %i, result %i\n", cand, res);
|
||||
} else {
|
||||
SPIFFS_GC_DBG("gc_check: cleaning block %i, result %i\n", cand, res);
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
res = spiffs_gc_erase_page_stats(fs, cand);
|
||||
@@ -46,8 +139,9 @@ s32_t spiffs_gc_check(
|
||||
|
||||
// here we ignore res, just try erasing the block
|
||||
SPIFFS_GC_DBG("gc_check: erase block %i\n", cand);
|
||||
//printf("gcing: erase block %i\n", cand);
|
||||
while (size > 0) {
|
||||
SPIFFS_DBG("gc_check: erase %08x:%08x\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
|
||||
SPIFFS_GC_DBG("gc_check: erase %08x:%08x\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
|
||||
res = fs->cfg.hal_erase_f(addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
|
||||
addr += SPIFFS_CFG_PHYS_ERASE_SZ(fs);
|
||||
size -= SPIFFS_CFG_PHYS_ERASE_SZ(fs);
|
||||
@@ -56,6 +150,15 @@ s32_t spiffs_gc_check(
|
||||
free_pages =
|
||||
(SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs)) * fs->block_count
|
||||
- fs->stats_p_allocated - fs->stats_p_deleted;
|
||||
|
||||
// register erase count for this block
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_C_UPDT | SPIFFS_OP_T_OBJ_LU2, 0,
|
||||
SPIFFS_ERASE_COUNT_PADDR(fs, cand),
|
||||
sizeof(spiffs_obj_id), (u8_t *)&fs->max_erase_count);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
fs->max_erase_count++;
|
||||
|
||||
#if SPIFFS_CACHE
|
||||
{
|
||||
int i;
|
||||
@@ -64,10 +167,17 @@ s32_t spiffs_gc_check(
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} while (tries++ < SPIFFS_GC_MAX_RUNS && (fs->free_blocks <= 2 ||
|
||||
//printf("gcing #%i free blocks %i, free data %i of %i\n",
|
||||
// tries, fs->free_blocks,
|
||||
// free_pages*SPIFFS_DATA_PAGE_SIZE(fs), len);
|
||||
} while (++tries < SPIFFS_GC_MAX_RUNS && (fs->free_blocks <= 2 ||
|
||||
len > free_pages*SPIFFS_DATA_PAGE_SIZE(fs)));
|
||||
SPIFFS_GC_DBG("gc_check: finished\n");
|
||||
|
||||
//printf("gcing finished %i dirty, blocks %i free, %i pages free, %i tries, res %i\n",
|
||||
// fs->stats_p_allocated + fs->stats_p_deleted,
|
||||
// fs->free_blocks, free_pages, tries, res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -92,7 +202,7 @@ s32_t spiffs_gc_erase_page_stats(
|
||||
cur_entry - entry_offset < entries_per_page && cur_entry < SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
|
||||
spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
|
||||
if (obj_id == SPIFFS_OBJ_ID_FREE) {
|
||||
} else if (obj_id == SPIFFS_OBJ_ID_ERASED) {
|
||||
} else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
|
||||
dele++;
|
||||
} else {
|
||||
allo++;
|
||||
@@ -118,15 +228,15 @@ s32_t spiffs_gc_find_candidate(
|
||||
spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
|
||||
int cur_entry = 0;
|
||||
|
||||
// using fs->work area as sorted candidate memory, (spiffs_block_ix)cand_bix/(int)score
|
||||
int max_candidates = MIN(fs->block_count, (SPIFFS_CFG_LOG_PAGE_SZ(fs)-8)/(sizeof(spiffs_block_ix) + sizeof(int)));
|
||||
// using fs->work area as sorted candidate memory, (spiffs_block_ix)cand_bix/(s32_t)score
|
||||
int max_candidates = MIN(fs->block_count, (SPIFFS_CFG_LOG_PAGE_SZ(fs)-8)/(sizeof(spiffs_block_ix) + sizeof(s32_t)));
|
||||
*candidate_count = 0;
|
||||
memset(fs->work, 0xff, SPIFFS_CFG_LOG_PAGE_SZ(fs));
|
||||
|
||||
// divide up work area into block indices and scores
|
||||
// todo alignment?
|
||||
spiffs_block_ix *cand_blocks = (spiffs_block_ix *)fs->work;
|
||||
int *cand_scores = (int *)(fs->work + max_candidates * sizeof(spiffs_block_ix));
|
||||
s32_t *cand_scores = (s32_t *)(fs->work + max_candidates * sizeof(spiffs_block_ix));
|
||||
|
||||
*block_candidates = cand_blocks;
|
||||
|
||||
@@ -150,7 +260,7 @@ s32_t spiffs_gc_find_candidate(
|
||||
if (obj_id == SPIFFS_OBJ_ID_FREE) {
|
||||
// when a free entry is encountered, scan logic ensures that all following entries are free also
|
||||
break;
|
||||
} else if (obj_id == SPIFFS_OBJ_ID_ERASED) {
|
||||
} else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
|
||||
deleted_pages_in_block++;
|
||||
} else {
|
||||
used_pages_in_block++;
|
||||
@@ -163,9 +273,26 @@ s32_t spiffs_gc_find_candidate(
|
||||
// calculate score and insert into candidate table
|
||||
// stoneage sort, but probably not so many blocks
|
||||
if (res == SPIFFS_OK && deleted_pages_in_block > 0) {
|
||||
int score = deleted_pages_in_block * SPIFFS_GC_HEUR_W_DELET + used_pages_in_block * SPIFFS_GC_HEUR_W_USED;
|
||||
// read erase count
|
||||
spiffs_obj_id erase_count;
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_C_READ | SPIFFS_OP_T_OBJ_LU2, 0,
|
||||
SPIFFS_ERASE_COUNT_PADDR(fs, cur_block),
|
||||
sizeof(spiffs_obj_id), (u8_t *)&erase_count);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
spiffs_obj_id erase_age;
|
||||
if (fs->max_erase_count > erase_count) {
|
||||
erase_age = fs->max_erase_count - erase_count;
|
||||
} else {
|
||||
erase_age = SPIFFS_OBJ_ID_FREE - (erase_count - fs->max_erase_count);
|
||||
}
|
||||
|
||||
s32_t score =
|
||||
deleted_pages_in_block * SPIFFS_GC_HEUR_W_DELET +
|
||||
used_pages_in_block * SPIFFS_GC_HEUR_W_USED +
|
||||
erase_age * SPIFFS_GC_HEUR_W_ERASE_AGE;
|
||||
int cand_ix = 0;
|
||||
SPIFFS_DBG("gc_check: bix:%i del:%i use:%i score:%i\n", cur_block, deleted_pages_in_block, used_pages_in_block, score);
|
||||
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);
|
||||
while (cand_ix < max_candidates) {
|
||||
if (cand_blocks[cand_ix] == (spiffs_block_ix)-1) {
|
||||
cand_blocks[cand_ix] = cur_block;
|
||||
@@ -196,9 +323,9 @@ s32_t spiffs_gc_find_candidate(
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
MOVE_OBJ_IX,
|
||||
FIND_OBJ_DATA,
|
||||
MOVE_OBJ_DATA,
|
||||
MOVE_OBJ_IX,
|
||||
FINISHED
|
||||
} spiffs_gc_clean_state;
|
||||
|
||||
@@ -213,7 +340,6 @@ typedef struct {
|
||||
|
||||
// Empties given block by moving all data into free pages of another block
|
||||
// Strategy:
|
||||
// scan object lookup for object index pages, move to new page in other block
|
||||
// loop:
|
||||
// scan object lookup for object data pages
|
||||
// for first found id, check spix and load corresponding object index page to memory
|
||||
@@ -223,6 +349,7 @@ typedef struct {
|
||||
// when reached end of lookup, store updated object index
|
||||
// pop object scan lookup entry index
|
||||
// repeat loop until end of object lookup
|
||||
// scan object lookup again for remaining object index pages, move to new page in other block
|
||||
//
|
||||
s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
@@ -234,18 +361,20 @@ s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
|
||||
spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
|
||||
spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
|
||||
|
||||
SPIFFS_GC_DBG("gc_clean: cleaning block %i\n", bix);
|
||||
|
||||
memset(&gc, 0, sizeof(spiffs_gc));
|
||||
gc.state = MOVE_OBJ_IX;
|
||||
gc.state = FIND_OBJ_DATA;
|
||||
|
||||
if (fs->free_cursor_block_ix == bix) {
|
||||
// move free cursor to next block
|
||||
// move free cursor to next block, cannot use free pages from the block we want to clean
|
||||
fs->free_cursor_block_ix = (bix+1)%fs->block_count;
|
||||
fs->free_cursor_obj_lu_entry = 0;
|
||||
SPIFFS_DBG("gc_clean: move free cursor to block %i\n", fs->free_cursor_block_ix);
|
||||
SPIFFS_GC_DBG("gc_clean: move free cursor to block %i\n", fs->free_cursor_block_ix);
|
||||
}
|
||||
|
||||
while (res == SPIFFS_OK && gc.state != FINISHED) {
|
||||
SPIFFS_DBG("gc_clean: state = %i entry:%i\n", gc.state, cur_entry);
|
||||
SPIFFS_GC_DBG("gc_clean: state = %i entry:%i\n", gc.state, cur_entry);
|
||||
gc.obj_id_found = 0;
|
||||
|
||||
// scan through lookup pages
|
||||
@@ -265,40 +394,10 @@ s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
|
||||
|
||||
// act upon object id depending on gc state
|
||||
switch (gc.state) {
|
||||
case MOVE_OBJ_IX:
|
||||
if (obj_id != SPIFFS_OBJ_ID_ERASED && obj_id != SPIFFS_OBJ_ID_FREE && (obj_id & SPIFFS_OBJ_ID_IX_FLAG)) {
|
||||
// found an index object id
|
||||
spiffs_page_header p_hdr;
|
||||
spiffs_page_ix new_pix;
|
||||
// load header
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
if (p_hdr.flags & SPIFFS_PH_FLAG_DELET) {
|
||||
// move page
|
||||
res = spiffs_page_move(fs, 0, 0, &p_hdr, cur_pix, &new_pix);
|
||||
SPIFFS_DBG("gc_clean: MOVE_OBJIX move objix %04x:%04x page %04x to %04x\n", obj_id, p_hdr.span_ix, cur_pix, new_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
spiffs_cb_object_event(fs, 0, SPIFFS_EV_IX_UPD, obj_id, p_hdr.span_ix, new_pix, 0);
|
||||
// move wipes obj_lu, reload it
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page),
|
||||
SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
} else {
|
||||
// page is deleted but not deleted in lookup, scrap it
|
||||
SPIFFS_DBG("gc_clean: MOVE_OBJIX wipe objix %04x:%04x page %04x\n", obj_id, p_hdr.span_ix, cur_pix);
|
||||
res = spiffs_page_delete(fs, cur_pix);
|
||||
if (res == SPIFFS_OK) {
|
||||
spiffs_cb_object_event(fs, 0, SPIFFS_EV_IX_DEL, obj_id, p_hdr.span_ix, cur_pix, 0);
|
||||
}
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
break;
|
||||
case FIND_OBJ_DATA:
|
||||
if (obj_id != SPIFFS_OBJ_ID_ERASED && obj_id != SPIFFS_OBJ_ID_FREE) {
|
||||
SPIFFS_DBG("gc_clean: FIND_DATA state:%i - found obj id %04x\n", gc.state, obj_id);
|
||||
if (obj_id != SPIFFS_OBJ_ID_DELETED && obj_id != SPIFFS_OBJ_ID_FREE &&
|
||||
((obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0)) {
|
||||
SPIFFS_GC_DBG("gc_clean: FIND_DATA state:%i - found obj id %04x\n", gc.state, obj_id);
|
||||
gc.obj_id_found = 1;
|
||||
gc.cur_obj_id = obj_id;
|
||||
scan = 0;
|
||||
@@ -310,15 +409,15 @@ s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
SPIFFS_DBG("gc_clean: MOVE_DATA found data page %04x:%04x @ %04x\n", gc.cur_obj_id, p_hdr.span_ix, cur_pix);
|
||||
SPIFFS_GC_DBG("gc_clean: MOVE_DATA found data page %04x:%04x @ %04x\n", gc.cur_obj_id, p_hdr.span_ix, cur_pix);
|
||||
if (SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, p_hdr.span_ix) != gc.cur_objix_spix) {
|
||||
SPIFFS_DBG("gc_clean: MOVE_DATA no objix spix match, take in another run\n", gc.cur_obj_id, p_hdr.span_ix, cur_pix);
|
||||
SPIFFS_GC_DBG("gc_clean: MOVE_DATA no objix spix match, take in another run\n");
|
||||
} else {
|
||||
spiffs_page_ix new_data_pix;
|
||||
if (p_hdr.flags & SPIFFS_PH_FLAG_DELET) {
|
||||
// move page
|
||||
res = spiffs_page_move(fs, 0, 0, &p_hdr, cur_pix, &new_data_pix);
|
||||
SPIFFS_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);
|
||||
res = spiffs_page_move(fs, 0, 0, obj_id, &p_hdr, cur_pix, &new_data_pix);
|
||||
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);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
// move wipes obj_lu, reload it
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
|
||||
@@ -327,7 +426,7 @@ s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
|
||||
SPIFFS_CHECK_RES(res);
|
||||
} else {
|
||||
// page is deleted but not deleted in lookup, scrap it
|
||||
SPIFFS_DBG("gc_clean: MOVE_DATA wipe objix %04x:%04x page %04x\n", obj_id, p_hdr.span_ix, cur_pix);
|
||||
SPIFFS_GC_DBG("gc_clean: MOVE_DATA wipe objix %04x:%04x page %04x\n", obj_id, p_hdr.span_ix, cur_pix);
|
||||
res = spiffs_page_delete(fs, cur_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
new_data_pix = SPIFFS_OBJ_ID_FREE;
|
||||
@@ -336,15 +435,47 @@ s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
|
||||
if (gc.cur_objix_spix == 0) {
|
||||
// update object index header page
|
||||
((spiffs_page_ix*)((void*)objix_hdr + sizeof(spiffs_page_object_ix_header)))[p_hdr.span_ix] = new_data_pix;
|
||||
SPIFFS_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));
|
||||
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));
|
||||
} else {
|
||||
// update object index page
|
||||
((spiffs_page_ix*)((void*)objix + sizeof(spiffs_page_object_ix)))[SPIFFS_OBJ_IX_ENTRY(fs, p_hdr.span_ix)] = new_data_pix;
|
||||
SPIFFS_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));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MOVE_OBJ_IX:
|
||||
if (obj_id != SPIFFS_OBJ_ID_DELETED && obj_id != SPIFFS_OBJ_ID_FREE &&
|
||||
(obj_id & SPIFFS_OBJ_ID_IX_FLAG)) {
|
||||
// found an index object id
|
||||
spiffs_page_header p_hdr;
|
||||
spiffs_page_ix new_pix;
|
||||
// load header
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
if (p_hdr.flags & SPIFFS_PH_FLAG_DELET) {
|
||||
// move page
|
||||
res = spiffs_page_move(fs, 0, 0, obj_id, &p_hdr, cur_pix, &new_pix);
|
||||
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);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
spiffs_cb_object_event(fs, 0, SPIFFS_EV_IX_UPD, obj_id, p_hdr.span_ix, new_pix, 0);
|
||||
// move wipes obj_lu, reload it
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page),
|
||||
SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
} else {
|
||||
// page is deleted but not deleted in lookup, scrap it
|
||||
SPIFFS_GC_DBG("gc_clean: MOVE_OBJIX wipe objix %04x:%04x page %04x\n", obj_id, p_hdr.span_ix, cur_pix);
|
||||
res = spiffs_page_delete(fs, cur_pix);
|
||||
if (res == SPIFFS_OK) {
|
||||
spiffs_cb_object_event(fs, 0, SPIFFS_EV_IX_DEL, obj_id, p_hdr.span_ix, cur_pix, 0);
|
||||
}
|
||||
}
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
scan = 0;
|
||||
break;
|
||||
@@ -358,10 +489,6 @@ s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
|
||||
|
||||
// state finalization and switch
|
||||
switch (gc.state) {
|
||||
case MOVE_OBJ_IX:
|
||||
gc.state = FIND_OBJ_DATA;
|
||||
cur_entry = 0; // restart entry scan index
|
||||
break;
|
||||
case FIND_OBJ_DATA:
|
||||
if (gc.obj_id_found) {
|
||||
// find out corresponding obj ix page and load it to memory
|
||||
@@ -374,17 +501,18 @@ s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix), sizeof(spiffs_page_header), (u8_t*)&p_hdr);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
gc.cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, p_hdr.span_ix);
|
||||
SPIFFS_DBG("gc_clean: FIND_DATA find objix span_ix:%04x\n", gc.cur_objix_spix);
|
||||
res = spiffs_obj_lu_find_id_and_index(fs, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, gc.cur_objix_spix, &objix_pix);
|
||||
SPIFFS_GC_DBG("gc_clean: FIND_DATA find objix span_ix:%04x\n", gc.cur_objix_spix);
|
||||
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);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
SPIFFS_DBG("gc_clean: FIND_DATA found object index at page %04x\n", objix_pix);
|
||||
SPIFFS_GC_DBG("gc_clean: FIND_DATA found object index at page %04x\n", objix_pix);
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
SPIFFS_VALIDATE_OBJIX(objix->p_hdr, gc.cur_obj_id, gc.cur_objix_spix);
|
||||
SPIFFS_VALIDATE_OBJIX(objix->p_hdr, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, gc.cur_objix_spix);
|
||||
gc.cur_objix_pix = objix_pix;
|
||||
} else {
|
||||
gc.state = FINISHED;
|
||||
gc.state = MOVE_OBJ_IX;
|
||||
cur_entry = 0; // restart entry scan index
|
||||
}
|
||||
break;
|
||||
case MOVE_OBJ_DATA: {
|
||||
@@ -394,24 +522,27 @@ s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
|
||||
cur_entry = gc.stored_scan_entry_index;
|
||||
if (gc.cur_objix_spix == 0) {
|
||||
// store object index header page
|
||||
res = spiffs_object_update_index_hdr(fs, 0, gc.cur_objix_pix, fs->work, 0, 0, &new_objix_pix);
|
||||
SPIFFS_DBG("gc_clean: MOVE_DATA store modified objix_hdr page, %04x:%04x\n", new_objix_pix, 0);
|
||||
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);
|
||||
SPIFFS_GC_DBG("gc_clean: MOVE_DATA store modified objix_hdr page, %04x:%04x\n", new_objix_pix, 0);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
} else {
|
||||
// store object index page
|
||||
spiffs_page_ix new_objix_pix;
|
||||
res = spiffs_page_move(fs, 0, fs->work, 0, gc.cur_objix_pix, &new_objix_pix);
|
||||
SPIFFS_DBG("gc_clean: MOVE_DATA store modified objix page, %04x:%04x\n", new_objix_pix, objix->p_hdr.span_ix);
|
||||
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);
|
||||
SPIFFS_GC_DBG("gc_clean: MOVE_DATA store modified objix page, %04x:%04x\n", new_objix_pix, objix->p_hdr.span_ix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
spiffs_cb_object_event(fs, 0, SPIFFS_EV_IX_UPD, gc.cur_obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case MOVE_OBJ_IX:
|
||||
gc.state = FINISHED;
|
||||
break;
|
||||
default:
|
||||
cur_entry = 0;
|
||||
break;
|
||||
}
|
||||
SPIFFS_DBG("gc_clean: state-> %i\n", gc.state);
|
||||
SPIFFS_GC_DBG("gc_clean: state-> %i\n", gc.state);
|
||||
} // while state != FINISHED
|
||||
|
||||
|
||||
|
||||
+139
-30
@@ -13,7 +13,8 @@ static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh);
|
||||
|
||||
s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
||||
u8_t *fd_space, u32_t fd_space_size,
|
||||
void *cache, u32_t cache_size) {
|
||||
void *cache, u32_t cache_size,
|
||||
spiffs_check_callback check_cb_f) {
|
||||
SPIFFS_LOCK(fs);
|
||||
memset(fs, 0, sizeof(spiffs));
|
||||
memcpy(&fs->cfg, config, sizeof(spiffs_config));
|
||||
@@ -64,6 +65,8 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
||||
SPIFFS_DBG("available file descriptors: %i\n", fs->fd_count);
|
||||
SPIFFS_DBG("free blocks: %i\n", fs->free_blocks);
|
||||
|
||||
fs->check_cb_f = check_cb_f;
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
|
||||
return 0;
|
||||
@@ -270,7 +273,8 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
|
||||
SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page %i for fd %i:&04x, boundary viol, offs:%i size:%i\n",
|
||||
fd->cache_page->ix, fd->file_nbr, fd->obj_id, fd->cache_page->offset, fd->cache_page->size);
|
||||
res = spiffs_hydro_write(fs, fd,
|
||||
get_cache_page(fs, get_cache(fs), fd->cache_page->ix), fd->cache_page->offset, fd->cache_page->size);
|
||||
spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
|
||||
fd->cache_page->offset, fd->cache_page->size);
|
||||
spiffs_cache_fd_release(fs, fd->cache_page);
|
||||
} else {
|
||||
// writing within cache
|
||||
@@ -293,8 +297,8 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
|
||||
SPIFFS_CACHE_DBG("CACHE_WR_WRITE: storing to cache page %i for fd %i:%04x, offs %i:%i len %i\n",
|
||||
fd->cache_page->ix, fd->file_nbr, fd->obj_id,
|
||||
offset, offset_in_cpage, len);
|
||||
spiffs_cache *cache = get_cache(fs);
|
||||
u8_t *cpage_data = get_cache_page(fs, cache, fd->cache_page->ix);
|
||||
spiffs_cache *cache = spiffs_get_cache(fs);
|
||||
u8_t *cpage_data = spiffs_get_cache_page(fs, cache, fd->cache_page->ix);
|
||||
memcpy(&cpage_data[offset_in_cpage], buf, len);
|
||||
fd->cache_page->size = MAX(fd->cache_page->size, offset_in_cpage + len);
|
||||
fd->fdoffset += len;
|
||||
@@ -314,7 +318,8 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
|
||||
SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page %i for fd %i:%04x, big write, offs:%i size:%i\n",
|
||||
fd->cache_page->ix, fd->file_nbr, fd->obj_id, fd->cache_page->offset, fd->cache_page->size);
|
||||
res = spiffs_hydro_write(fs, fd,
|
||||
get_cache_page(fs, get_cache(fs), fd->cache_page->ix), fd->cache_page->offset, fd->cache_page->size);
|
||||
spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
|
||||
fd->cache_page->offset, fd->cache_page->size);
|
||||
spiffs_cache_fd_release(fs, fd->cache_page);
|
||||
res = spiffs_hydro_write(fs, fd, buf, offset, len);
|
||||
SPIFFS_API_CHECK_RES(fs, res);
|
||||
@@ -363,8 +368,8 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
|
||||
spiffs_span_ix objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
|
||||
if (fd->cursor_objix_spix != objix_spix) {
|
||||
spiffs_page_ix pix;
|
||||
res = spiffs_obj_lu_find_id_and_index(
|
||||
fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, objix_spix, &pix);
|
||||
res = spiffs_obj_lu_find_id_and_span(
|
||||
fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, objix_spix, 0, &pix);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
fd->cursor_objix_spix = objix_spix;
|
||||
fd->cursor_objix_pix = pix;
|
||||
@@ -380,16 +385,29 @@ s32_t SPIFFS_remove(spiffs *fs, const char *path) {
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
spiffs_fd fd;
|
||||
spiffs_fd *fd;
|
||||
spiffs_page_ix pix;
|
||||
s32_t res;
|
||||
fd.file_nbr = 0;
|
||||
fd.fs = fs;
|
||||
|
||||
res = spiffs_fd_find_new(fs, &fd);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
|
||||
res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)path, &pix);
|
||||
if (res != SPIFFS_OK) {
|
||||
spiffs_fd_return(fs, fd->file_nbr);
|
||||
}
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
res = spiffs_object_open_by_page(fs, pix, &fd, 0,0);
|
||||
|
||||
res = spiffs_object_open_by_page(fs, pix, fd, 0,0);
|
||||
if (res != SPIFFS_OK) {
|
||||
spiffs_fd_return(fs, fd->file_nbr);
|
||||
}
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
res = spiffs_object_truncate(&fd, 0, 1);
|
||||
|
||||
res = spiffs_object_truncate(fd, 0, 1);
|
||||
if (res != SPIFFS_OK) {
|
||||
spiffs_fd_return(fs, fd->file_nbr);
|
||||
}
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
@@ -418,13 +436,50 @@ s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file fh, spiffs_stat *s) {
|
||||
spiffs_page_object_ix_header objix_hdr;
|
||||
spiffs_obj_id obj_id;
|
||||
s32_t res =_spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ, fh,
|
||||
SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&objix_hdr);
|
||||
SPIFFS_API_CHECK_RES(fs, res);
|
||||
|
||||
u32_t obj_id_addr = SPIFFS_BLOCK_TO_PADDR(fs, SPIFFS_BLOCK_FOR_PAGE(fs , pix)) +
|
||||
SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, pix) * sizeof(spiffs_obj_id);
|
||||
res =_spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ, fh,
|
||||
obj_id_addr, sizeof(spiffs_obj_id), (u8_t *)&obj_id);
|
||||
SPIFFS_API_CHECK_RES(fs, res);
|
||||
|
||||
s->obj_id = obj_id;
|
||||
s->type = objix_hdr.type;
|
||||
s->size = objix_hdr.size == SPIFFS_UNDEFINED_LEN ? 0 : objix_hdr.size;
|
||||
strncpy((char *)s->name, (char *)objix_hdr.name, SPIFFS_OBJ_NAME_LEN);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s) {
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
s32_t res;
|
||||
spiffs_page_ix pix;
|
||||
|
||||
res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)path, &pix);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
|
||||
res = spiffs_stat_pix(fs, pix, 0, s);
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) {
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
spiffs_fd *fd;
|
||||
s32_t res;
|
||||
spiffs_page_object_ix_header objix_hdr;
|
||||
|
||||
res = spiffs_fd_get(fs, fh, &fd);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
@@ -433,17 +488,7 @@ s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) {
|
||||
spiffs_fflush_cache(fs, fh);
|
||||
#endif
|
||||
|
||||
res = spiffs_phys_rd(fs,
|
||||
#if SPIFFS_CACHE
|
||||
SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ, fh,
|
||||
#endif
|
||||
SPIFFS_PAGE_TO_PADDR(fs, fd->objix_hdr_pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&objix_hdr);
|
||||
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
|
||||
|
||||
s->obj_id = objix_hdr.p_hdr.obj_id;
|
||||
s->type = objix_hdr.type;
|
||||
s->size = objix_hdr.size == SPIFFS_UNDEFINED_LEN ? 0 : objix_hdr.size;
|
||||
strncpy((char *)s->name, (char *)objix_hdr.name, SPIFFS_OBJ_NAME_LEN);
|
||||
res = spiffs_stat_pix(fs, fd->objix_hdr_pix, fh, s);
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
|
||||
@@ -467,7 +512,8 @@ static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) {
|
||||
SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page %i for fd %i:%04x, flush, offs:%i size:%i\n",
|
||||
fd->cache_page->ix, fd->file_nbr, fd->obj_id, fd->cache_page->offset, fd->cache_page->size);
|
||||
res = spiffs_hydro_write(fs, fd,
|
||||
get_cache_page(fs, get_cache(fs), fd->cache_page->ix), fd->cache_page->offset, fd->cache_page->size);
|
||||
spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
|
||||
fd->cache_page->offset, fd->cache_page->size);
|
||||
spiffs_cache_fd_release(fs, fd->cache_page);
|
||||
}
|
||||
}
|
||||
@@ -524,7 +570,7 @@ static s32_t spiffs_read_dir_v(
|
||||
void *user_p) {
|
||||
s32_t res;
|
||||
spiffs_page_object_ix_header objix_hdr;
|
||||
if (obj_id == SPIFFS_OBJ_ID_FREE || obj_id == SPIFFS_OBJ_ID_ERASED ||
|
||||
if (obj_id == SPIFFS_OBJ_ID_FREE || obj_id == SPIFFS_OBJ_ID_DELETED ||
|
||||
(obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0) {
|
||||
return SPIFFS_VIS_COUNTINUE;
|
||||
}
|
||||
@@ -533,11 +579,12 @@ static s32_t spiffs_read_dir_v(
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&objix_hdr);
|
||||
if (res != SPIFFS_OK) return res;
|
||||
if ((objix_hdr.p_hdr.obj_id & SPIFFS_OBJ_ID_IX_FLAG) &&
|
||||
if ((obj_id & SPIFFS_OBJ_ID_IX_FLAG) &&
|
||||
objix_hdr.p_hdr.span_ix == 0 &&
|
||||
(objix_hdr.p_hdr.flags& (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL)) == SPIFFS_PH_FLAG_DELET) {
|
||||
(objix_hdr.p_hdr.flags& (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE)) ==
|
||||
(SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) {
|
||||
struct spiffs_dirent *e = (struct spiffs_dirent *)user_p;
|
||||
e->obj_id = objix_hdr.p_hdr.obj_id;
|
||||
e->obj_id = obj_id;
|
||||
strcpy((char *)e->name, (char *)objix_hdr.name);
|
||||
e->type = objix_hdr.type;
|
||||
e->size = objix_hdr.size == SPIFFS_UNDEFINED_LEN ? 0 : objix_hdr.size;
|
||||
@@ -590,8 +637,70 @@ s32_t SPIFFS_check(spiffs *fs) {
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
res = spiffs_area_check(fs, 0);
|
||||
res = spiffs_lookup_consistency_check(fs, 0);
|
||||
|
||||
res = spiffs_object_index_consistency_check(fs);
|
||||
|
||||
res = spiffs_page_consistency_check(fs);
|
||||
|
||||
res = spiffs_obj_lu_scan(fs);
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return res;
|
||||
}
|
||||
|
||||
#if SPIFFS_TEST_VISUALISATION
|
||||
s32_t SPIFFS_vis(spiffs *fs) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
SPIFFS_API_CHECK_MOUNT(fs);
|
||||
SPIFFS_LOCK(fs);
|
||||
|
||||
u32_t entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
|
||||
spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
|
||||
spiffs_block_ix bix = 0;
|
||||
|
||||
while (bix < fs->block_count) {
|
||||
// check each object lookup page
|
||||
int obj_lookup_page = 0;
|
||||
int cur_entry = 0;
|
||||
|
||||
while (res == SPIFFS_OK && obj_lookup_page < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
|
||||
int entry_offset = obj_lookup_page * entries_per_page;
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
|
||||
// check each entry
|
||||
while (res == SPIFFS_OK &&
|
||||
cur_entry - entry_offset < entries_per_page && cur_entry < SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
|
||||
spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
|
||||
if (cur_entry == 0) {
|
||||
spiffs_printf("%4i ", bix);
|
||||
} else if ((cur_entry & 0x3f) == 0) {
|
||||
spiffs_printf(" ");
|
||||
}
|
||||
if (obj_id == SPIFFS_OBJ_ID_FREE) {
|
||||
spiffs_printf(SPIFFS_TEST_VIS_FREE_STR);
|
||||
} else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
|
||||
spiffs_printf(SPIFFS_TEST_VIS_DELE_STR);
|
||||
} else if (obj_id & SPIFFS_OBJ_ID_IX_FLAG){
|
||||
spiffs_printf(SPIFFS_TEST_VIS_INDX_STR(obj_id));
|
||||
} else {
|
||||
spiffs_printf(SPIFFS_TEST_VIS_DATA_STR(obj_id));
|
||||
}
|
||||
cur_entry++;
|
||||
if ((cur_entry & 0x3f) == 0) {
|
||||
spiffs_printf("\n");
|
||||
}
|
||||
} // per entry
|
||||
obj_lookup_page++;
|
||||
} // per object lookup page
|
||||
if ((cur_entry & 0x1f) != 0) {
|
||||
spiffs_printf("\n");
|
||||
}
|
||||
|
||||
bix++;
|
||||
} // per block
|
||||
|
||||
SPIFFS_UNLOCK(fs);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
|
||||
+222
-76
@@ -1,22 +1,20 @@
|
||||
#include "spiffs.h"
|
||||
#include "spiffs_nucleus.h"
|
||||
|
||||
#define SPIFFS_VALIDATE_OBJIX(ph, objid, spix) \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_INDEX) != 0) return SPIFFS_ERR_NOT_INDEX; \
|
||||
if ((ph).span_ix != (spix)) return SPIFFS_ERR_INDEX_SPAN_MISMATCH;\
|
||||
if (((ph).obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) != ((objid) & ~SPIFFS_OBJ_ID_IX_FLAG)) return SPIFFS_ERR_INDEX_WRONG_ID;
|
||||
|
||||
#define SPIFFS_VALIDATE_DATA(ph, objid, spix) \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_INDEX) == 0) return SPIFFS_ERR_IS_INDEX; \
|
||||
if ((ph).span_ix != (spix)) return SPIFFS_ERR_DATA_SPAN_MISMATCH; \
|
||||
if (((ph).obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) != ((objid) & ~SPIFFS_OBJ_ID_IX_FLAG)) return SPIFFS_ERR_DATA_WRONG_ID;
|
||||
|
||||
static s32_t spiffs_page_data_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix pix, spiffs_span_ix spix) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
if (pix == (spiffs_page_ix)-1) {
|
||||
// referring to page 0xffff...., bad object index
|
||||
return SPIFFS_ERR_INDEX_REF_FREE;
|
||||
}
|
||||
if (pix % SPIFFS_PAGES_PER_BLOCK(fs) < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
|
||||
// referring to an object lookup page, bad object index
|
||||
return SPIFFS_ERR_INDEX_REF_LU;
|
||||
}
|
||||
if (pix > SPIFFS_MAX_PAGES(fs)) {
|
||||
// referring to a bad page
|
||||
return SPIFFS_ERR_INDEX_REF_INVALID;
|
||||
}
|
||||
#if SPIFFS_PAGE_CHECK
|
||||
spiffs_page_header ph;
|
||||
res = _spiffs_rd(
|
||||
@@ -26,13 +24,25 @@ static s32_t spiffs_page_data_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix pi
|
||||
sizeof(spiffs_page_header),
|
||||
(u8_t *)&ph);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
SPIFFS_VALIDATE_DATA(ph, fd->obj_id, spix);
|
||||
SPIFFS_VALIDATE_DATA(ph, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, spix);
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
static s32_t spiffs_page_index_check(spiffs *fs, spiffs_fd *fd, spiffs_page_ix pix, spiffs_span_ix spix) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
if (pix == (spiffs_page_ix)-1) {
|
||||
// referring to page 0xffff...., bad object index
|
||||
return SPIFFS_ERR_INDEX_FREE;
|
||||
}
|
||||
if (pix % SPIFFS_PAGES_PER_BLOCK(fs) < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
|
||||
// referring to an object lookup page, bad object index
|
||||
return SPIFFS_ERR_INDEX_LU;
|
||||
}
|
||||
if (pix > SPIFFS_MAX_PAGES(fs)) {
|
||||
// referring to a bad page
|
||||
return SPIFFS_ERR_INDEX_INVALID;
|
||||
}
|
||||
#if SPIFFS_PAGE_CHECK
|
||||
spiffs_page_header ph;
|
||||
res = _spiffs_rd(
|
||||
@@ -67,7 +77,7 @@ s32_t spiffs_phys_wr(
|
||||
|
||||
#endif
|
||||
|
||||
static s32_t spiffs_phys_cpy(
|
||||
s32_t spiffs_phys_cpy(
|
||||
spiffs *fs,
|
||||
spiffs_file fh,
|
||||
u32_t dst,
|
||||
@@ -144,8 +154,19 @@ s32_t spiffs_obj_lu_find_entry_visitor(
|
||||
if (block_ix) *block_ix = cur_block;
|
||||
if (index_entry) *index_entry = cur_entry;
|
||||
if (v) {
|
||||
res = v(fs, obj_lu_buf[cur_entry-entry_offset], cur_block, cur_entry, user_data, user_p);
|
||||
if (res == SPIFFS_VIS_COUNTINUE) {
|
||||
res = v(
|
||||
fs,
|
||||
(flags & SPIFFS_VIS_CHECK_PH) ? obj_id : obj_lu_buf[cur_entry-entry_offset],
|
||||
cur_block,
|
||||
cur_entry,
|
||||
user_data,
|
||||
user_p);
|
||||
if (res == SPIFFS_VIS_COUNTINUE || res == SPIFFS_VIS_COUNTINUE_RELOAD) {
|
||||
if (res == SPIFFS_VIS_COUNTINUE_RELOAD) {
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
|
||||
0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
res = SPIFFS_OK;
|
||||
cur_entry++;
|
||||
entry_count--;
|
||||
@@ -194,7 +215,7 @@ static s32_t spiffs_obj_lu_scan_v(
|
||||
fs->free_blocks++;
|
||||
// todo optimize further, return SPIFFS_NEXT_BLOCK
|
||||
}
|
||||
} else if (obj_id == SPIFFS_OBJ_ID_ERASED) {
|
||||
} else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
|
||||
fs->stats_p_deleted++;
|
||||
} else {
|
||||
fs->stats_p_allocated++;
|
||||
@@ -204,6 +225,7 @@ static s32_t spiffs_obj_lu_scan_v(
|
||||
}
|
||||
|
||||
// Scans thru all obj lu and counts free, deleted and used pages
|
||||
// Find the maximum block erase count
|
||||
s32_t spiffs_obj_lu_scan(
|
||||
spiffs *fs) {
|
||||
s32_t res;
|
||||
@@ -231,6 +253,36 @@ s32_t spiffs_obj_lu_scan(
|
||||
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
bix = 0;
|
||||
spiffs_obj_id erase_count_final;
|
||||
spiffs_obj_id erase_count_min = 0;
|
||||
spiffs_obj_id erase_count_max = SPIFFS_OBJ_ID_FREE;
|
||||
while (bix < fs->block_count) {
|
||||
spiffs_obj_id erase_count;
|
||||
res = _spiffs_rd(fs,
|
||||
SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_ERASE_COUNT_PADDR(fs, bix) ,
|
||||
sizeof(spiffs_obj_id), (u8_t *)&erase_count);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
if (erase_count != SPIFFS_OBJ_ID_FREE) {
|
||||
erase_count_min = MIN(erase_count_min, erase_count);
|
||||
erase_count_max = MAX(erase_count_max, erase_count);
|
||||
}
|
||||
bix++;
|
||||
}
|
||||
|
||||
if (erase_count_min == 0 && erase_count_max == SPIFFS_OBJ_ID_FREE) {
|
||||
// clean system, set counter to zero
|
||||
erase_count_final = 0;
|
||||
} else if (erase_count_max - erase_count_min > (SPIFFS_OBJ_ID_FREE)/2) {
|
||||
// wrap, take min
|
||||
erase_count_final = erase_count_min;
|
||||
} else {
|
||||
erase_count_final = erase_count_max;
|
||||
}
|
||||
|
||||
fs->max_erase_count = erase_count_final;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -243,6 +295,9 @@ s32_t spiffs_obj_lu_find_free(
|
||||
spiffs_block_ix *block_ix,
|
||||
int *index_entry) {
|
||||
s32_t res;
|
||||
if (!fs->cleaning && fs->free_blocks < 2) {
|
||||
return SPIFFS_ERR_FULL;
|
||||
}
|
||||
res = spiffs_obj_lu_find_id(fs, starting_block, starting_index_entry,
|
||||
SPIFFS_OBJ_ID_FREE, block_ix, index_entry);
|
||||
if (res == SPIFFS_OK) {
|
||||
@@ -255,6 +310,7 @@ s32_t spiffs_obj_lu_find_free(
|
||||
if (res == SPIFFS_VIS_END) {
|
||||
SPIFFS_DBG("fs full\n");
|
||||
}
|
||||
|
||||
return res == SPIFFS_VIS_END ? SPIFFS_ERR_FULL : res;
|
||||
}
|
||||
|
||||
@@ -276,7 +332,7 @@ s32_t spiffs_obj_lu_find_id(
|
||||
}
|
||||
|
||||
|
||||
static s32_t spiffs_obj_lu_find_id_and_index_v(
|
||||
static s32_t spiffs_obj_lu_find_id_and_span_v(
|
||||
spiffs *fs,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_block_ix bix,
|
||||
@@ -289,7 +345,11 @@ static s32_t spiffs_obj_lu_find_id_and_index_v(
|
||||
res = _spiffs_rd(fs, 0, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_header), (u8_t *)&ph);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
if (ph.span_ix == (spiffs_span_ix)user_data && ((ph.flags & (SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET)) == SPIFFS_PH_FLAG_DELET)) {
|
||||
if (ph.obj_id == obj_id &&
|
||||
ph.span_ix == (spiffs_span_ix)user_data &&
|
||||
(ph.flags & (SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_USED)) == SPIFFS_PH_FLAG_DELET &&
|
||||
!((obj_id & SPIFFS_OBJ_ID_IX_FLAG) && (ph.flags & SPIFFS_PH_FLAG_IXDELE) == 0 && ph.span_ix == 0) &&
|
||||
(user_p == 0 || *((spiffs_page_ix *)user_p) != pix)) {
|
||||
return SPIFFS_OK;
|
||||
} else {
|
||||
return SPIFFS_VIS_COUNTINUE;
|
||||
@@ -298,10 +358,11 @@ static s32_t spiffs_obj_lu_find_id_and_index_v(
|
||||
|
||||
// Find object lookup entry containing given id and span index
|
||||
// Iterate over object lookup pages in each block until a given object id entry is found
|
||||
s32_t spiffs_obj_lu_find_id_and_index(
|
||||
s32_t spiffs_obj_lu_find_id_and_span(
|
||||
spiffs *fs,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_span_ix spix,
|
||||
spiffs_page_ix exclusion_pix,
|
||||
spiffs_page_ix *pix) {
|
||||
s32_t res;
|
||||
spiffs_block_ix bix;
|
||||
@@ -312,9 +373,48 @@ s32_t spiffs_obj_lu_find_id_and_index(
|
||||
fs->cursor_obj_lu_entry,
|
||||
SPIFFS_VIS_CHECK_ID,
|
||||
obj_id,
|
||||
spiffs_obj_lu_find_id_and_index_v,
|
||||
spiffs_obj_lu_find_id_and_span_v,
|
||||
(u32_t)spix,
|
||||
0,
|
||||
exclusion_pix ? &exclusion_pix : 0,
|
||||
&bix,
|
||||
&entry);
|
||||
|
||||
if (res == SPIFFS_VIS_END) {
|
||||
res = SPIFFS_ERR_NOT_FOUND;
|
||||
}
|
||||
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
if (pix) {
|
||||
*pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry);
|
||||
}
|
||||
|
||||
fs->cursor_block_ix = bix;
|
||||
fs->cursor_obj_lu_entry = entry;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
// Find object lookup entry containing given id and span index in page headers only
|
||||
// Iterate over object lookup pages in each block until a given object id entry is found
|
||||
s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
|
||||
spiffs *fs,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_span_ix spix,
|
||||
spiffs_page_ix exclusion_pix,
|
||||
spiffs_page_ix *pix) {
|
||||
s32_t res;
|
||||
spiffs_block_ix bix;
|
||||
int entry;
|
||||
|
||||
res = spiffs_obj_lu_find_entry_visitor(fs,
|
||||
fs->cursor_block_ix,
|
||||
fs->cursor_obj_lu_entry,
|
||||
SPIFFS_VIS_CHECK_PH,
|
||||
obj_id,
|
||||
spiffs_obj_lu_find_id_and_span_v,
|
||||
(u32_t)spix,
|
||||
exclusion_pix ? &exclusion_pix : 0,
|
||||
&bix,
|
||||
&entry);
|
||||
|
||||
@@ -339,6 +439,7 @@ s32_t spiffs_obj_lu_find_id_and_index(
|
||||
// data may be NULL; where only page header is stored, len and page_offs is ignored
|
||||
s32_t spiffs_page_allocate_data(
|
||||
spiffs *fs,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_page_header *ph,
|
||||
u8_t *data,
|
||||
u32_t len,
|
||||
@@ -355,12 +456,13 @@ s32_t spiffs_page_allocate_data(
|
||||
|
||||
// occupy page in object lookup
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
|
||||
0, SPIFFS_BLOCK_TO_PADDR(fs, bix) + entry * sizeof(spiffs_obj_id), sizeof(spiffs_obj_id), (u8_t*)&ph->obj_id);
|
||||
0, SPIFFS_BLOCK_TO_PADDR(fs, bix) + entry * sizeof(spiffs_obj_id), sizeof(spiffs_obj_id), (u8_t*)&obj_id);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
fs->stats_p_allocated++;
|
||||
|
||||
// write page header
|
||||
ph->flags &= ~SPIFFS_PH_FLAG_USED;
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
|
||||
0, SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, bix, entry), sizeof(spiffs_page_header), (u8_t*)ph);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
@@ -396,6 +498,7 @@ s32_t spiffs_page_move(
|
||||
spiffs *fs,
|
||||
spiffs_file fh,
|
||||
u8_t *page_data,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_page_header *page_hdr,
|
||||
spiffs_page_ix src_pix,
|
||||
spiffs_page_ix *dst_pix) {
|
||||
@@ -419,6 +522,7 @@ s32_t spiffs_page_move(
|
||||
was_final = (p_hdr->flags & SPIFFS_PH_FLAG_FINAL) == 0;
|
||||
// write unfinalized page
|
||||
p_hdr->flags |= SPIFFS_PH_FLAG_FINAL;
|
||||
p_hdr->flags &= ~SPIFFS_PH_FLAG_USED;
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, free_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), page_data);
|
||||
} else {
|
||||
@@ -431,14 +535,14 @@ s32_t spiffs_page_move(
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
|
||||
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),
|
||||
sizeof(spiffs_obj_id),
|
||||
(u8_t *)&p_hdr->obj_id);
|
||||
(u8_t *)&obj_id);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
fs->stats_p_allocated++;
|
||||
|
||||
if (was_final) {
|
||||
// mark finalized in destination page
|
||||
p_hdr->flags &= ~SPIFFS_PH_FLAG_FINAL;
|
||||
p_hdr->flags &= ~(SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_USED);
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
|
||||
fh,
|
||||
SPIFFS_PAGE_TO_PADDR(fs, free_pix) + offsetof(spiffs_page_header, flags),
|
||||
@@ -457,9 +561,9 @@ s32_t spiffs_page_delete(
|
||||
spiffs_page_ix pix) {
|
||||
s32_t res;
|
||||
spiffs_page_header hdr;
|
||||
hdr.flags = 0xff & ~SPIFFS_PH_FLAG_DELET;
|
||||
hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_USED);
|
||||
// mark deleted entry in source object lookup
|
||||
spiffs_obj_id d_obj_id = SPIFFS_OBJ_ID_ERASED;
|
||||
spiffs_obj_id d_obj_id = SPIFFS_OBJ_ID_DELETED;
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_DELE,
|
||||
0,
|
||||
SPIFFS_BLOCK_TO_PADDR(fs, SPIFFS_BLOCK_FOR_PAGE(fs, pix)) + SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, pix) * sizeof(spiffs_page_ix),
|
||||
@@ -476,6 +580,7 @@ s32_t spiffs_page_delete(
|
||||
SPIFFS_PAGE_TO_PADDR(fs, pix) + offsetof(spiffs_page_header, flags),
|
||||
sizeof(u8_t),
|
||||
(u8_t *)&hdr.flags);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
@@ -499,7 +604,7 @@ s32_t spiffs_object_create(
|
||||
// find free entry
|
||||
res = spiffs_obj_lu_find_free(fs, fs->free_cursor_block_ix, fs->free_cursor_obj_lu_entry, &bix, &entry);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
SPIFFS_DBG("found free page @ %04x bix:%i entry:%i\n", SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry), bix, entry);
|
||||
SPIFFS_DBG("create: found free page @ %04x bix:%i entry:%i\n", SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, entry), bix, entry);
|
||||
|
||||
// occupy page in object lookup
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
|
||||
@@ -511,7 +616,7 @@ s32_t spiffs_object_create(
|
||||
// write empty object index page
|
||||
oix_hdr.p_hdr.obj_id = obj_id;
|
||||
oix_hdr.p_hdr.span_ix = 0;
|
||||
oix_hdr.p_hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX);
|
||||
oix_hdr.p_hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_USED);
|
||||
oix_hdr.type = type;
|
||||
oix_hdr.size = SPIFFS_UNDEFINED_LEN; // keep ones so we can update later without wasting this page
|
||||
strncpy((char *)&oix_hdr.name, (char *)name, SPIFFS_OBJ_NAME_LEN);
|
||||
@@ -538,6 +643,7 @@ s32_t spiffs_object_create(
|
||||
s32_t spiffs_object_update_index_hdr(
|
||||
spiffs *fs,
|
||||
spiffs_fd *fd,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_page_ix objix_hdr_pix,
|
||||
u8_t *new_objix_hdr_data,
|
||||
u8_t name[SPIFFS_OBJ_NAME_LEN],
|
||||
@@ -547,6 +653,8 @@ s32_t spiffs_object_update_index_hdr(
|
||||
spiffs_page_object_ix_header *objix_hdr;
|
||||
spiffs_page_ix new_objix_hdr_pix;
|
||||
|
||||
obj_id |= SPIFFS_OBJ_ID_IX_FLAG;
|
||||
|
||||
if (new_objix_hdr_data) {
|
||||
// object index header page already given to us, no need to load it
|
||||
objix_hdr = (spiffs_page_object_ix_header *)new_objix_hdr_data;
|
||||
@@ -558,7 +666,7 @@ s32_t spiffs_object_update_index_hdr(
|
||||
objix_hdr = (spiffs_page_object_ix_header *)fs->work;
|
||||
}
|
||||
|
||||
SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, objix_hdr->p_hdr.obj_id, 0);
|
||||
SPIFFS_VALIDATE_OBJIX(objix_hdr->p_hdr, obj_id, 0);
|
||||
|
||||
// change name
|
||||
if (name) {
|
||||
@@ -569,14 +677,14 @@ s32_t spiffs_object_update_index_hdr(
|
||||
}
|
||||
|
||||
// move and update page
|
||||
res = spiffs_page_move(fs, fd == 0 ? 0 : fd->file_nbr, (u8_t*)objix_hdr, 0, objix_hdr_pix, &new_objix_hdr_pix);
|
||||
res = spiffs_page_move(fs, fd == 0 ? 0 : fd->file_nbr, (u8_t*)objix_hdr, obj_id, 0, objix_hdr_pix, &new_objix_hdr_pix);
|
||||
|
||||
if (res == SPIFFS_OK) {
|
||||
if (new_pix) {
|
||||
*new_pix = new_objix_hdr_pix;
|
||||
}
|
||||
// callback on object index update
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, objix_hdr->p_hdr.obj_id, objix_hdr->p_hdr.span_ix, new_objix_hdr_pix, objix_hdr->size);
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, obj_id, objix_hdr->p_hdr.span_ix, new_objix_hdr_pix, objix_hdr->size);
|
||||
if (fd) fd->objix_hdr_pix = new_objix_hdr_pix; // if this is not in the registered cluster
|
||||
}
|
||||
|
||||
@@ -607,7 +715,7 @@ void spiffs_cb_object_event(
|
||||
}
|
||||
} else if (ev == SPIFFS_EV_IX_DEL) {
|
||||
cur_fd->file_nbr = 0;
|
||||
cur_fd->obj_id = SPIFFS_OBJ_ID_ERASED;
|
||||
cur_fd->obj_id = SPIFFS_OBJ_ID_DELETED;
|
||||
}
|
||||
}
|
||||
if (cur_fd->cursor_objix_spix == spix) {
|
||||
@@ -631,7 +739,7 @@ s32_t spiffs_object_open_by_id(
|
||||
s32_t res = SPIFFS_OK;
|
||||
spiffs_page_ix pix;
|
||||
|
||||
res = spiffs_obj_lu_find_id_and_index(fs, obj_id, 0, &pix);
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, 0, &pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
res = spiffs_object_open_by_page(fs, pix, fd, attr, mode);
|
||||
@@ -648,18 +756,25 @@ s32_t spiffs_object_open_by_page(
|
||||
spiffs_mode mode) {
|
||||
s32_t res = SPIFFS_OK;
|
||||
spiffs_page_object_ix_header oix_hdr;
|
||||
spiffs_obj_id obj_id;
|
||||
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
|
||||
fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&oix_hdr);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
spiffs_block_ix bix = SPIFFS_BLOCK_FOR_PAGE(fs, pix);
|
||||
int entry = SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, pix);
|
||||
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_BLOCK_TO_PADDR(fs, bix) + entry * sizeof(spiffs_obj_id), sizeof(spiffs_obj_id), (u8_t *)&obj_id);
|
||||
|
||||
fd->fs = fs;
|
||||
fd->objix_hdr_pix = pix;
|
||||
fd->size = oix_hdr.size;
|
||||
fd->offset = 0;
|
||||
fd->cursor_objix_pix = pix;
|
||||
fd->cursor_objix_spix = 0;
|
||||
fd->obj_id = oix_hdr.p_hdr.obj_id;
|
||||
fd->obj_id = obj_id;
|
||||
fd->mode = mode;
|
||||
|
||||
SPIFFS_VALIDATE_OBJIX(oix_hdr.p_hdr, fd->obj_id, 0);
|
||||
@@ -717,7 +832,8 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
SPIFFS_CHECK_RES(res);
|
||||
} else {
|
||||
// was a nonempty object, update to new page
|
||||
res = spiffs_object_update_index_hdr(fs, fd, fd->objix_hdr_pix, fs->work, 0, offset+written, &new_objix_hdr_page);
|
||||
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
||||
fd->objix_hdr_pix, fs->work, 0, offset+written, &new_objix_hdr_page);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
SPIFFS_DBG("append: %04x store new objix_hdr, %04x:%04x, written %i\n", fd->obj_id,
|
||||
new_objix_hdr_page, 0, written);
|
||||
@@ -730,11 +846,12 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_UPDT,
|
||||
fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, objix->p_hdr.obj_id, objix->p_hdr.span_ix, cur_objix_pix, 0);
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD,fd->obj_id, objix->p_hdr.span_ix, cur_objix_pix, 0);
|
||||
// update length in object index header page
|
||||
res = spiffs_object_update_index_hdr(fs, fd, fd->objix_hdr_pix, 0, 0, offset+written, &new_objix_hdr_page);
|
||||
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
||||
fd->objix_hdr_pix, 0, 0, offset+written, &new_objix_hdr_page);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
SPIFFS_DBG("append: %04x store new size %i in objix_hdr, %04x:%04x, written %i\n", fd->obj_id,
|
||||
SPIFFS_DBG("append: %04x store new size I %i in objix_hdr, %04x:%04x, written %i\n", fd->obj_id,
|
||||
offset+written, new_objix_hdr_page, 0, written);
|
||||
}
|
||||
fd->size = offset+written;
|
||||
@@ -756,7 +873,8 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
p_hdr.obj_id = fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG;
|
||||
p_hdr.span_ix = cur_objix_spix;
|
||||
p_hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX);
|
||||
res = spiffs_page_allocate_data(fs, &p_hdr, 0, 0, 0, 1, &cur_objix_pix);
|
||||
res = spiffs_page_allocate_data(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG,
|
||||
&p_hdr, 0, 0, 0, 1, &cur_objix_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_NEW, fd->obj_id, cur_objix_spix, cur_objix_pix, 0);
|
||||
// quick "load" of new object index page
|
||||
@@ -771,7 +889,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
if (fd->cursor_objix_spix == cur_objix_spix) {
|
||||
pix = fd->cursor_objix_pix;
|
||||
} else {
|
||||
res = spiffs_obj_lu_find_id_and_index(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, &pix);
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
SPIFFS_DBG("append: %04x found object index at page %04x\n", fd->obj_id, pix);
|
||||
@@ -796,7 +914,8 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
p_hdr.obj_id = fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
|
||||
p_hdr.span_ix = data_spix;
|
||||
p_hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL); // finalize immediately
|
||||
res = spiffs_page_allocate_data(fs, &p_hdr, &data[written], to_spiffs_wr, page_offs, 1, &data_page);
|
||||
res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
|
||||
&p_hdr, &data[written], to_spiffs_wr, page_offs, 1, &data_page);
|
||||
SPIFFS_DBG("append: %04x store new data page, %04x:%04x offset:%i, len %i, written %i\n", fd->obj_id,
|
||||
data_page, data_spix, page_offs, to_spiffs_wr, written);
|
||||
} else {
|
||||
@@ -859,12 +978,13 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
res2 = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_UPDT,
|
||||
fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
|
||||
SPIFFS_CHECK_RES(res2);
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, objix->p_hdr.obj_id, objix->p_hdr.span_ix, cur_objix_pix, 0);
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, cur_objix_pix, 0);
|
||||
|
||||
// update size in object header index page
|
||||
SPIFFS_DBG("append: %04x store new size %i in objix_hdr, %04x:%04x, written %i\n", fd->obj_id
|
||||
res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
||||
fd->objix_hdr_pix, 0, 0, offset+written, &new_objix_hdr_page);
|
||||
SPIFFS_DBG("append: %04x store new size II %i in objix_hdr, %04x:%04x, written %i\n", fd->obj_id
|
||||
, offset+written, new_objix_hdr_page, 0, written);
|
||||
res2 = spiffs_object_update_index_hdr(fs, fd, fd->objix_hdr_pix, 0, 0, offset+written, &new_objix_hdr_page);
|
||||
SPIFFS_CHECK_RES(res2);
|
||||
} else {
|
||||
// wrote within object index header page
|
||||
@@ -881,10 +1001,11 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, cur_objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
|
||||
SPIFFS_CHECK_RES(res2);
|
||||
// callback on object index update
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, objix_hdr->p_hdr.obj_id, objix_hdr->p_hdr.span_ix, cur_objix_pix, objix_hdr->size);
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, fd->obj_id, objix_hdr->p_hdr.span_ix, cur_objix_pix, objix_hdr->size);
|
||||
} else {
|
||||
// modifying object index header page, update size and make new copy
|
||||
res2 = spiffs_object_update_index_hdr(fs, fd, fd->objix_hdr_pix, fs->work, 0, offset+written, &new_objix_hdr_page);
|
||||
res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
||||
fd->objix_hdr_pix, fs->work, 0, offset+written, &new_objix_hdr_page);
|
||||
SPIFFS_DBG("append: %04x store modified objix_hdr page, %04x:%04x, written %i\n", fd->obj_id
|
||||
, new_objix_hdr_page, 0, written);
|
||||
SPIFFS_CHECK_RES(res2);
|
||||
@@ -931,7 +1052,8 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
// store previous object index (header) page, unless first pass
|
||||
if (prev_objix_spix == 0) {
|
||||
// store previous object index header page
|
||||
res = spiffs_object_update_index_hdr(fs, fd, fd->objix_hdr_pix, fs->work, 0, 0, &new_objix_hdr_pix);
|
||||
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
||||
fd->objix_hdr_pix, fs->work, 0, 0, &new_objix_hdr_pix);
|
||||
SPIFFS_DBG("modify: store modified objix_hdr page, %04x:%04x, written %i\n", new_objix_hdr_pix, 0, written);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
} else {
|
||||
@@ -941,10 +1063,10 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
res = spiffs_page_index_check(fs, fd, cur_objix_pix, prev_objix_spix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
res = spiffs_page_move(fs, fd->file_nbr, (u8_t*)objix, 0, cur_objix_pix, &new_objix_pix);
|
||||
res = spiffs_page_move(fs, fd->file_nbr, (u8_t*)objix, fd->obj_id, 0, cur_objix_pix, &new_objix_pix);
|
||||
SPIFFS_DBG("modify: store previous modified objix page, %04x:%04x, written %i\n", new_objix_pix, objix->p_hdr.span_ix, written);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, objix->p_hdr.obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -963,7 +1085,7 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
if (fd->cursor_objix_spix == cur_objix_spix) {
|
||||
pix = fd->cursor_objix_pix;
|
||||
} else {
|
||||
res = spiffs_obj_lu_find_id_and_index(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, &pix);
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
SPIFFS_DBG("modify: found object index at page %04x\n", pix);
|
||||
@@ -993,10 +1115,10 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
p_hdr.obj_id = fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG;
|
||||
p_hdr.span_ix = data_spix;
|
||||
p_hdr.flags = 0xff;
|
||||
p_hdr.flags = 0xff;
|
||||
if (page_offs == 0 && to_write == SPIFFS_DATA_PAGE_SIZE(fs)) {
|
||||
// a full page, allocate and write a new page of data
|
||||
res = spiffs_page_allocate_data(fs, &p_hdr, &data[written], to_write, page_offs, 1, &data_pix);
|
||||
res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
|
||||
&p_hdr, &data[written], to_write, page_offs, 1, &data_pix);
|
||||
SPIFFS_DBG("modify: store new data page, %04x:%04x offset:%i, len %i, written %i\n", data_pix, data_spix, page_offs, to_write, written);
|
||||
} else {
|
||||
// write to existing page, allocate new and copy unmodified data
|
||||
@@ -1004,7 +1126,8 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
res = spiffs_page_data_check(fs, fd, orig_data_pix, data_spix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
res = spiffs_page_allocate_data(fs, &p_hdr, 0, 0, 0, 0, &data_pix);
|
||||
res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
|
||||
&p_hdr, 0, 0, 0, 0, &data_pix);
|
||||
if (res != SPIFFS_OK) break;
|
||||
|
||||
// copy unmodified data
|
||||
@@ -1075,16 +1198,17 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
|
||||
res2 = spiffs_page_index_check(fs, fd, cur_objix_pix, cur_objix_spix);
|
||||
SPIFFS_CHECK_RES(res2);
|
||||
|
||||
res2 = spiffs_page_move(fs, fd->file_nbr, (u8_t*)objix, 0, cur_objix_pix, &new_objix_pix);
|
||||
res2 = spiffs_page_move(fs, fd->file_nbr, (u8_t*)objix, fd->obj_id, 0, cur_objix_pix, &new_objix_pix);
|
||||
SPIFFS_DBG("modify: store modified objix page, %04x:%04x, written %i\n", new_objix_pix, cur_objix_spix, written);
|
||||
fd->cursor_objix_pix = new_objix_pix;
|
||||
fd->cursor_objix_spix = cur_objix_spix;
|
||||
SPIFFS_CHECK_RES(res2);
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, objix->p_hdr.obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
|
||||
|
||||
} else {
|
||||
// wrote within object index header page
|
||||
res2 = spiffs_object_update_index_hdr(fs, fd, fd->objix_hdr_pix, fs->work, 0, 0, &new_objix_hdr_pix);
|
||||
res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
||||
fd->objix_hdr_pix, fs->work, 0, 0, &new_objix_hdr_pix);
|
||||
SPIFFS_DBG("modify: store modified objix_hdr page, %04x:%04x, written %i\n", new_objix_hdr_pix, 0, written);
|
||||
SPIFFS_CHECK_RES(res2);
|
||||
}
|
||||
@@ -1102,16 +1226,16 @@ static s32_t spiffs_object_find_object_index_header_by_name_v(
|
||||
s32_t res;
|
||||
spiffs_page_object_ix_header objix_hdr;
|
||||
spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry);
|
||||
if (obj_id == SPIFFS_OBJ_ID_FREE || obj_id == SPIFFS_OBJ_ID_ERASED ||
|
||||
if (obj_id == SPIFFS_OBJ_ID_FREE || obj_id == SPIFFS_OBJ_ID_DELETED ||
|
||||
(obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0) {
|
||||
return SPIFFS_VIS_COUNTINUE;
|
||||
}
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&objix_hdr);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
if ((objix_hdr.p_hdr.obj_id & SPIFFS_OBJ_ID_IX_FLAG) &&
|
||||
objix_hdr.p_hdr.span_ix == 0 &&
|
||||
(objix_hdr.p_hdr.flags& (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL)) == SPIFFS_PH_FLAG_DELET) {
|
||||
if (objix_hdr.p_hdr.span_ix == 0 &&
|
||||
(objix_hdr.p_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE)) ==
|
||||
(SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) {
|
||||
if (strcmp((char *)user_p, (char *)objix_hdr.name) == 0) {
|
||||
return SPIFFS_OK;
|
||||
}
|
||||
@@ -1155,6 +1279,10 @@ s32_t spiffs_object_find_object_index_header_by_name(
|
||||
return res;
|
||||
}
|
||||
|
||||
void stop() {
|
||||
printf("break");
|
||||
}
|
||||
|
||||
// Truncates object to new size. If new size is null, object may be removed totally
|
||||
s32_t spiffs_object_truncate(
|
||||
spiffs_fd *fd,
|
||||
@@ -1176,6 +1304,16 @@ s32_t spiffs_object_truncate(
|
||||
spiffs_page_ix data_pix;
|
||||
spiffs_page_ix new_objix_hdr_pix;
|
||||
|
||||
// before truncating, check if object is to be fully removed and mark this
|
||||
if (remove && new_size == 0) {
|
||||
u8_t flags = ~( SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE);
|
||||
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_UPDT,
|
||||
fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, fd->objix_hdr_pix) + offsetof(spiffs_page_header, flags),
|
||||
sizeof(u8_t),
|
||||
(u8_t *)&flags);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
|
||||
// delete from end of object until desired len is reached
|
||||
while (cur_size > new_size) {
|
||||
cur_objix_spix = SPIFFS_OBJ_IX_ENTRY_SPAN_IX(fs, data_spix);
|
||||
@@ -1191,11 +1329,12 @@ s32_t spiffs_object_truncate(
|
||||
|
||||
res = spiffs_page_delete(fs, objix_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_DEL, objix->p_hdr.obj_id, objix->p_hdr.span_ix, objix_pix, 0);
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_DEL, fd->obj_id, objix->p_hdr.span_ix, objix_pix, 0);
|
||||
if (prev_objix_spix > 0) {
|
||||
// update object index header page
|
||||
SPIFFS_DBG("truncate: update objix hdr page %04x:%04x to size %i\n", fd->objix_hdr_pix, prev_objix_spix, cur_size);
|
||||
res = spiffs_object_update_index_hdr(fs, fd, fd->objix_hdr_pix, 0, 0, cur_size, &new_objix_hdr_pix);
|
||||
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
||||
fd->objix_hdr_pix, 0, 0, cur_size, &new_objix_hdr_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
fd->size = cur_size;
|
||||
}
|
||||
@@ -1204,9 +1343,10 @@ s32_t spiffs_object_truncate(
|
||||
if (cur_objix_spix == 0) {
|
||||
objix_pix = fd->objix_hdr_pix;
|
||||
} else {
|
||||
res = spiffs_obj_lu_find_id_and_index(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, &objix_pix);
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &objix_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
|
||||
SPIFFS_DBG("truncate: load objix page %04x:%04x for data spix:%04x\n", objix_pix, cur_objix_spix, data_spix);
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
|
||||
fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, objix_pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
|
||||
@@ -1259,7 +1399,8 @@ s32_t spiffs_object_truncate(
|
||||
p_hdr.span_ix = data_spix;
|
||||
p_hdr.flags = 0xff;
|
||||
// allocate new page and copy unmodified data
|
||||
res = spiffs_page_allocate_data(fs, &p_hdr, 0, 0, 0, 0, &new_data_pix);
|
||||
res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
|
||||
&p_hdr, 0, 0, 0, 0, &new_data_pix);
|
||||
if (res != SPIFFS_OK) break;
|
||||
res = spiffs_phys_cpy(fs, 0,
|
||||
SPIFFS_PAGE_TO_PADDR(fs, new_data_pix) + sizeof(spiffs_page_header),
|
||||
@@ -1314,13 +1455,15 @@ s32_t spiffs_object_truncate(
|
||||
SPIFFS_DBG("truncate: reset objix_hdr page %04x\n", objix_pix);
|
||||
memset(fs->work + sizeof(spiffs_page_object_ix_header), 0xff,
|
||||
SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix_header));
|
||||
res = spiffs_object_update_index_hdr(fs, fd, objix_pix, fs->work, 0, SPIFFS_UNDEFINED_LEN, &new_objix_hdr_pix);
|
||||
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
||||
objix_pix, fs->work, 0, SPIFFS_UNDEFINED_LEN, &new_objix_hdr_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
} else {
|
||||
// update object index header page
|
||||
SPIFFS_DBG("truncate: update object index header page with indices and size\n");
|
||||
res = spiffs_object_update_index_hdr(fs, fd, objix_pix, fs->work, 0, cur_size, &new_objix_hdr_pix);
|
||||
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
||||
objix_pix, fs->work, 0, cur_size, &new_objix_hdr_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
} else {
|
||||
@@ -1331,15 +1474,16 @@ s32_t spiffs_object_truncate(
|
||||
SPIFFS_CHECK_RES(res);
|
||||
|
||||
// move and update object index page
|
||||
res = spiffs_page_move(fs, fd->file_nbr, (u8_t*)objix_hdr, 0, objix_pix, &new_objix_pix);
|
||||
res = spiffs_page_move(fs, fd->file_nbr, (u8_t*)objix_hdr, fd->obj_id, 0, objix_pix, &new_objix_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, objix->p_hdr.obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
|
||||
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, fd->obj_id, objix->p_hdr.span_ix, new_objix_pix, 0);
|
||||
SPIFFS_DBG("truncate: store modified objix page, %04x:%04x\n", new_objix_pix, cur_objix_spix);
|
||||
fd->cursor_objix_pix = new_objix_pix;
|
||||
fd->cursor_objix_spix = cur_objix_spix;
|
||||
fd->offset = cur_size;
|
||||
// update object index header page with new size
|
||||
res = spiffs_object_update_index_hdr(fs, fd, fd->objix_hdr_pix, 0, 0, cur_size, &new_objix_hdr_pix);
|
||||
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
|
||||
fd->objix_hdr_pix, 0, 0, cur_size, &new_objix_hdr_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
fd->size = cur_size;
|
||||
@@ -1370,7 +1514,8 @@ s32_t spiffs_object_read(
|
||||
if (cur_objix_spix == 0) {
|
||||
objix_pix = fd->objix_hdr_pix;
|
||||
} else {
|
||||
res = spiffs_obj_lu_find_id_and_index(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, &objix_pix);
|
||||
SPIFFS_DBG("read: find objix %04x:%04x\n", fd->obj_id, cur_objix_spix);
|
||||
res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &objix_pix);
|
||||
SPIFFS_CHECK_RES(res);
|
||||
}
|
||||
SPIFFS_DBG("read: load objix page %04x:%04x for data spix:%04x\n", objix_pix, cur_objix_spix, data_spix);
|
||||
@@ -1432,7 +1577,7 @@ typedef struct {
|
||||
|
||||
static s32_t spiffs_obj_lu_find_free_obj_id_bitmap_v(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry,
|
||||
u32_t user_data, void *user_p) {
|
||||
if (id != SPIFFS_OBJ_ID_FREE && id != SPIFFS_OBJ_ID_ERASED) {
|
||||
if (id != SPIFFS_OBJ_ID_FREE && id != SPIFFS_OBJ_ID_DELETED) {
|
||||
spiffs_obj_id min_obj_id = user_data;
|
||||
id &= ~SPIFFS_OBJ_ID_IX_FLAG;
|
||||
int bit_ix = (id-min_obj_id) & 7;
|
||||
@@ -1446,7 +1591,7 @@ static s32_t spiffs_obj_lu_find_free_obj_id_bitmap_v(spiffs *fs, spiffs_obj_id i
|
||||
|
||||
static s32_t spiffs_obj_lu_find_free_obj_id_compact_v(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry,
|
||||
u32_t user_data, void *user_p) {
|
||||
if (id != SPIFFS_OBJ_ID_FREE && id != SPIFFS_OBJ_ID_ERASED && (id & SPIFFS_OBJ_ID_IX_FLAG)) {
|
||||
if (id != SPIFFS_OBJ_ID_FREE && id != SPIFFS_OBJ_ID_DELETED && (id & SPIFFS_OBJ_ID_IX_FLAG)) {
|
||||
s32_t res;
|
||||
spiffs_free_obj_id_state *state = (spiffs_free_obj_id_state *)user_p;
|
||||
spiffs_page_header ph;
|
||||
@@ -1454,7 +1599,8 @@ static s32_t spiffs_obj_lu_find_free_obj_id_compact_v(spiffs *fs, spiffs_obj_id
|
||||
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
|
||||
0, SPIFFS_OBJ_LOOKUP_ENTRY_TO_PADDR(fs, bix, ix_entry), sizeof(spiffs_page_header), (u8_t*)&ph);
|
||||
if (res == SPIFFS_OK && ph.span_ix == 0 &&
|
||||
((ph.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET)) == (SPIFFS_PH_FLAG_DELET))) {
|
||||
((ph.flags & (SPIFFS_PH_FLAG_INDEX | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_DELET)) ==
|
||||
(SPIFFS_PH_FLAG_DELET))) {
|
||||
// ok object look up entry
|
||||
id &= ~SPIFFS_OBJ_ID_IX_FLAG;
|
||||
if (id >= state->min_obj_id && id <= state->max_obj_id) {
|
||||
|
||||
+68
-25
@@ -110,8 +110,15 @@
|
||||
#ifndef SPIFFS_NUCLEUS_H_
|
||||
#define SPIFFS_NUCLEUS_H_
|
||||
|
||||
#define SPIFFS_VIS_COUNTINUE -11000
|
||||
#define SPIFFS_VIS_END -11001
|
||||
#define _SPIFFS_ERR_CHECK_FIRST (SPIFFS_ERR_INTERNAL - 1)
|
||||
#define SPIFFS_ERR_CHECK_OBJ_ID_MISM (SPIFFS_ERR_INTERNAL - 1)
|
||||
#define SPIFFS_ERR_CHECK_SPIX_MISM (SPIFFS_ERR_INTERNAL - 2)
|
||||
#define SPIFFS_ERR_CHECK_FLAGS_BAD (SPIFFS_ERR_INTERNAL - 3)
|
||||
#define _SPIFFS_ERR_CHECK_LAST (SPIFFS_ERR_INTERNAL - 4)
|
||||
|
||||
#define SPIFFS_VIS_COUNTINUE (SPIFFS_ERR_INTERNAL - 20)
|
||||
#define SPIFFS_VIS_COUNTINUE_RELOAD (SPIFFS_ERR_INTERNAL - 21)
|
||||
#define SPIFFS_VIS_END (SPIFFS_ERR_INTERNAL - 22)
|
||||
|
||||
#define SPIFFS_EV_IX_UPD 0
|
||||
#define SPIFFS_EV_IX_NEW 1
|
||||
@@ -121,7 +128,7 @@
|
||||
|
||||
#define SPIFFS_UNDEFINED_LEN (-1)
|
||||
|
||||
#define SPIFFS_OBJ_ID_ERASED ((spiffs_obj_id)0)
|
||||
#define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
|
||||
#define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1)
|
||||
|
||||
#ifndef SPIFFS_SINGLETON
|
||||
@@ -137,6 +144,9 @@
|
||||
((fs)->cfg.phys_addr)
|
||||
#endif
|
||||
|
||||
// total number of pages
|
||||
#define SPIFFS_MAX_PAGES(fs) \
|
||||
( SPIFFS_CFG_PHYS_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
|
||||
// total number of pages per block, including object lookup pages
|
||||
#define SPIFFS_PAGES_PER_BLOCK(fs) \
|
||||
( SPIFFS_CFG_LOG_BLOCK_SZ(fs)/SPIFFS_CFG_LOG_PAGE_SZ(fs) )
|
||||
@@ -169,16 +179,19 @@
|
||||
( ((addr) - SPIFFS_CFG_PHYS_ADDR(fs)) % SPIFFS_CFG_LOG_PAGE_SZ(fs) )
|
||||
// returns containing block for given page
|
||||
#define SPIFFS_BLOCK_FOR_PAGE(fs, page) \
|
||||
((page) / SPIFFS_PAGES_PER_BLOCK(fs))
|
||||
( (page) / SPIFFS_PAGES_PER_BLOCK(fs) )
|
||||
// returns starting page for block
|
||||
#define SPIFFS_PAGE_FOR_BLOCK(fs, block) \
|
||||
((block) * SPIFFS_PAGES_PER_BLOCK(fs))
|
||||
( (block) * SPIFFS_PAGES_PER_BLOCK(fs) )
|
||||
// converts page to entry in object lookup page
|
||||
#define SPIFFS_OBJ_LOOKUP_ENTRY_FOR_PAGE(fs, page) \
|
||||
((page) % SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs))
|
||||
( (page) % SPIFFS_PAGES_PER_BLOCK(fs) - SPIFFS_OBJ_LOOKUP_PAGES(fs) )
|
||||
// returns data size in a data page
|
||||
#define SPIFFS_DATA_PAGE_SIZE(fs) \
|
||||
( SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_header) )
|
||||
// returns physical address for block's erase count
|
||||
#define SPIFFS_ERASE_COUNT_PADDR(fs, bix) \
|
||||
( SPIFFS_BLOCK_TO_PADDR(fs, bix) + SPIFFS_OBJ_LOOKUP_PAGES(fs) * SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_obj_id) )
|
||||
|
||||
// define helpers object
|
||||
|
||||
@@ -206,19 +219,23 @@
|
||||
#define SPIFFS_OP_C_MOVD (3<<2)
|
||||
#define SPIFFS_OP_C_FLSH (4<<2)
|
||||
#define SPIFFS_OP_C_READ (5<<2)
|
||||
#define SPIFFS_OP_C_WRTHRU (6<<2)
|
||||
|
||||
#define SPIFFS_OP_TYPE_MASK (3<<0)
|
||||
#define SPIFFS_OP_COM_MASK (7<<2)
|
||||
|
||||
|
||||
// if 0, this page is written to, else clean
|
||||
#define SPIFFS_PH_FLAG_USED (1<<0)
|
||||
// if 0, writing is finalized, else under modification
|
||||
#define SPIFFS_PH_FLAG_FINAL (1<<0)
|
||||
// if 0, page is deleted, else valid
|
||||
#define SPIFFS_PH_FLAG_DELET (1<<1)
|
||||
// if 0, page is corrupt, else ok
|
||||
#define SPIFFS_PH_FLAG_CORRU (1<<2)
|
||||
#define SPIFFS_PH_FLAG_FINAL (1<<1)
|
||||
// if 0, this is an index page, else a data page
|
||||
#define SPIFFS_PH_FLAG_INDEX (1<<3)
|
||||
#define SPIFFS_PH_FLAG_INDEX (1<<2)
|
||||
// if 0, page is deleted, else valid
|
||||
#define SPIFFS_PH_FLAG_DELET (1<<7)
|
||||
// if 0, this index header is being deleted
|
||||
#define SPIFFS_PH_FLAG_IXDELE (1<<6)
|
||||
|
||||
|
||||
#define SPIFFS_CHECK_MOUNT(fs) \
|
||||
((fs)->block_count > 0)
|
||||
@@ -247,24 +264,28 @@
|
||||
return -1; \
|
||||
}
|
||||
|
||||
|
||||
// todo
|
||||
#define SPIFFS_VALIDATE_OBJIX(ph, objid, spix) \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_INDEX) != 0) return SPIFFS_ERR_NOT_INDEX; \
|
||||
if ((ph).span_ix != (spix)) return SPIFFS_ERR_INDEX_SPAN_MISMATCH;\
|
||||
if (((ph).obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) != ((objid) & ~SPIFFS_OBJ_ID_IX_FLAG)) return SPIFFS_ERR_INDEX_WRONG_ID;
|
||||
if (((objid) & SPIFFS_OBJ_ID_IX_FLAG) == 0) return SPIFFS_ERR_NOT_INDEX; \
|
||||
if ((ph).span_ix != (spix)) {stop(); return SPIFFS_ERR_INDEX_SPAN_MISMATCH;};
|
||||
//if ((spix) == 0 && ((ph).flags & SPIFFS_PH_FLAG_IXDELE) == 0) return SPIFFS_ERR_DELETED;
|
||||
|
||||
#define SPIFFS_VALIDATE_DATA(ph, objid, spix) \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_USED) != 0) return SPIFFS_ERR_IS_FREE; \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_DELET) == 0) return SPIFFS_ERR_DELETED; \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_FINAL) != 0) return SPIFFS_ERR_NOT_FINALIZED; \
|
||||
if (((ph).flags & SPIFFS_PH_FLAG_INDEX) == 0) return SPIFFS_ERR_IS_INDEX; \
|
||||
if ((ph).span_ix != (spix)) return SPIFFS_ERR_DATA_SPAN_MISMATCH; \
|
||||
if (((ph).obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) != ((objid) & ~SPIFFS_OBJ_ID_IX_FLAG)) return SPIFFS_ERR_DATA_WRONG_ID;
|
||||
if ((objid) & SPIFFS_OBJ_ID_IX_FLAG) return SPIFFS_ERR_IS_INDEX; \
|
||||
if ((ph).span_ix != (spix)) return SPIFFS_ERR_DATA_SPAN_MISMATCH;
|
||||
|
||||
|
||||
#define SPIFFS_VIS_CHECK_ID (1<<0)
|
||||
#define SPIFFS_VIS_NO_WRAP (1<<1)
|
||||
#define SPIFFS_VIS_CHECK_PH (1<<1)
|
||||
#define SPIFFS_VIS_NO_WRAP (1<<2)
|
||||
|
||||
#if SPIFFS_CACHE
|
||||
|
||||
@@ -278,13 +299,13 @@
|
||||
#define SPIFFS_CACHE_PAGE_SIZE(fs) \
|
||||
(sizeof(spiffs_cache_page) + SPIFFS_CFG_LOG_PAGE_SZ(fs))
|
||||
|
||||
#define get_cache(fs) \
|
||||
#define spiffs_get_cache(fs) \
|
||||
((spiffs_cache *)((fs)->cache))
|
||||
|
||||
#define get_cache_page_hdr(fs, c, ix) \
|
||||
#define spiffs_get_cache_page_hdr(fs, c, ix) \
|
||||
((spiffs_cache_page *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])))
|
||||
|
||||
#define get_cache_page(fs, c, ix) \
|
||||
#define spiffs_get_cache_page(fs, c, ix) \
|
||||
((u8_t *)(&((c)->cpages[(ix) * SPIFFS_CACHE_PAGE_SIZE(fs)])) + sizeof(spiffs_cache_page))
|
||||
|
||||
typedef struct {
|
||||
@@ -417,14 +438,14 @@ s32_t spiffs_phys_wr(
|
||||
u32_t addr,
|
||||
u32_t len,
|
||||
u8_t *src);
|
||||
#if 0
|
||||
|
||||
s32_t spiffs_phys_cpy(
|
||||
spiffs *fs,
|
||||
spiffs_file fh,
|
||||
u32_t dst,
|
||||
u32_t src,
|
||||
u32_t len);
|
||||
#endif
|
||||
|
||||
s32_t spiffs_phys_count_free_blocks(
|
||||
spiffs *fs);
|
||||
|
||||
@@ -464,16 +485,25 @@ s32_t spiffs_obj_lu_find_id(
|
||||
spiffs_block_ix *block_ix,
|
||||
int *index_entry);
|
||||
|
||||
s32_t spiffs_obj_lu_find_id_and_index(
|
||||
s32_t spiffs_obj_lu_find_id_and_span(
|
||||
spiffs *fs,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_span_ix spix,
|
||||
spiffs_page_ix exclusion_pix,
|
||||
spiffs_page_ix *pix);
|
||||
|
||||
s32_t spiffs_obj_lu_find_id_and_span_by_phdr(
|
||||
spiffs *fs,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_span_ix spix,
|
||||
spiffs_page_ix exclusion_pix,
|
||||
spiffs_page_ix *pix);
|
||||
|
||||
// ---------------
|
||||
|
||||
s32_t spiffs_page_allocate_data(
|
||||
spiffs *fs,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_page_header *ph,
|
||||
u8_t *data,
|
||||
u32_t len,
|
||||
@@ -485,6 +515,7 @@ s32_t spiffs_page_move(
|
||||
spiffs *fs,
|
||||
spiffs_file fh,
|
||||
u8_t *page_data,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_page_header *page_hdr,
|
||||
spiffs_page_ix src_pix,
|
||||
spiffs_page_ix *dst_pix);
|
||||
@@ -505,6 +536,7 @@ s32_t spiffs_object_create(
|
||||
s32_t spiffs_object_update_index_hdr(
|
||||
spiffs *fs,
|
||||
spiffs_fd *fd,
|
||||
spiffs_obj_id obj_id,
|
||||
spiffs_page_ix objix_hdr_pix,
|
||||
u8_t *new_objix_hdr_data,
|
||||
u8_t name[SPIFFS_OBJ_NAME_LEN],
|
||||
@@ -581,6 +613,9 @@ s32_t spiffs_gc_clean(
|
||||
spiffs *fs,
|
||||
spiffs_block_ix bix);
|
||||
|
||||
s32_t spiffs_gc_quick(
|
||||
spiffs *fs);
|
||||
|
||||
// ---------------
|
||||
|
||||
s32_t spiffs_fd_find_new(
|
||||
@@ -619,6 +654,14 @@ spiffs_cache_page *spiffs_cache_page_get_by_fd(
|
||||
#endif
|
||||
#endif
|
||||
|
||||
s32_t spiffs_area_check(spiffs *fs, u8_t check_all_objects);
|
||||
s32_t spiffs_lookup_consistency_check(
|
||||
spiffs *fs,
|
||||
u8_t check_all_objects);
|
||||
|
||||
s32_t spiffs_page_consistency_check(
|
||||
spiffs *fs);
|
||||
|
||||
s32_t spiffs_object_index_consistency_check(
|
||||
spiffs *fs);
|
||||
|
||||
#endif /* SPIFFS_NUCLEUS_H_ */
|
||||
|
||||
+1
-1
@@ -20,8 +20,8 @@ void dump_page(spiffs *fs, spiffs_page_ix p);
|
||||
void hexdump(u32_t addr, u32_t len);
|
||||
char *make_test_fname(const char *name);
|
||||
void clear_test_path();
|
||||
u8_t area_read(u32_t addr);
|
||||
void area_write(u32_t addr, u8_t *buf, u32_t size);
|
||||
void area_read(u32_t addr, u8_t *buf, u32_t size);
|
||||
|
||||
|
||||
#endif /* TEST_SPIFFS_H_ */
|
||||
|
||||
+2
-1
@@ -8,6 +8,7 @@
|
||||
#include "testrunner.h"
|
||||
|
||||
void add_suites() {
|
||||
//ADD_SUITE(hydrogen_tests)
|
||||
ADD_SUITE(dev_tests);
|
||||
ADD_SUITE(check_tests);
|
||||
ADD_SUITE(hydrogen_tests)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user