changed ways of gc, optimized

This commit is contained in:
Peter Andersson
2013-07-26 14:46:22 +02:00
parent 13e3c47a32
commit ced3b61864
18 changed files with 1566 additions and 359 deletions
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.
+2
View File
@@ -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
+14 -1
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+203 -72
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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)
}