1
0
mirror of https://github.com/esp8266/Arduino.git synced 2025-04-19 23:22:16 +03:00

Merge remote-tracking branch 'esp8266/esp8266' into esp8266

This commit is contained in:
aalku 2015-08-14 15:23:03 +02:00
commit b79f1c689d
13 changed files with 421 additions and 249 deletions

View File

@ -144,6 +144,14 @@ String Dir::fileName() {
return _impl->fileName(); return _impl->fileName();
} }
size_t Dir::fileSize() {
if (!_impl) {
return 0;
}
return _impl->fileSize();
}
bool Dir::next() { bool Dir::next() {
if (!_impl) { if (!_impl) {
return false; return false;

View File

@ -78,6 +78,7 @@ public:
File openFile(const char* mode); File openFile(const char* mode);
String fileName(); String fileName();
size_t fileSize();
bool next(); bool next();
protected: protected:

View File

@ -56,6 +56,7 @@ public:
virtual ~DirImpl() { } virtual ~DirImpl() { }
virtual FileImplPtr openFile(OpenMode openMode, AccessMode accessMode) = 0; virtual FileImplPtr openFile(OpenMode openMode, AccessMode accessMode) = 0;
virtual const char* fileName() = 0; virtual const char* fileName() = 0;
virtual size_t fileSize() = 0;
virtual bool next() = 0; virtual bool next() = 0;
}; };

View File

@ -148,6 +148,7 @@ char* ultoa(unsigned long value, char* result, int base) {
} }
char * dtostrf(double number, signed char width, unsigned char prec, char *s) { char * dtostrf(double number, signed char width, unsigned char prec, char *s) {
bool negative = false;
if (isnan(number)) { if (isnan(number)) {
strcpy(s, "nan"); strcpy(s, "nan");
@ -158,50 +159,65 @@ char * dtostrf(double number, signed char width, unsigned char prec, char *s) {
return s; return s;
} }
if (number > 4294967040.0 || number < -4294967040.0) {
strcpy(s, "ovf");
return s;
}
char* out = s; char* out = s;
int signInt_Part = 1;
int fillme = width; // how many cells to fill for the integer part
if (prec > 0) {
fillme -= (prec+1);
}
// Handle negative numbers // Handle negative numbers
if (number < 0.0) { if (number < 0.0) {
signInt_Part = -1; negative = true;
fillme--;
number = -number; number = -number;
} }
// calc left over digits
if (prec > 0)
{
width -= (prec + 1);
}
// Round correctly so that print(1.999, 2) prints as "2.00" // Round correctly so that print(1.999, 2) prints as "2.00"
double rounding = 0.5; // I optimized out most of the divisions
double rounding = 2.0;
for (uint8_t i = 0; i < prec; ++i) for (uint8_t i = 0; i < prec; ++i)
rounding /= 10.0; rounding *= 10.0;
rounding = 1.0 / rounding;
number += rounding; number += rounding;
// Extract the integer part of the number and print it // Figure out how big our number really is
unsigned long int_part = (unsigned long)number; double tenpow = 1.0;
double remainder = number - (double)int_part; int digitcount = 1;
out += sprintf(out, "%*ld", width, int_part * signInt_Part); while (number >= 10.0 * tenpow) {
tenpow *= 10.0;
// Print the decimal point, but only if there are digits beyond digitcount++;
if (prec > 0) {
*out = '.';
++out;
for (unsigned char decShift = prec; decShift > 0; decShift--) {
remainder *= 10.0;
}
sprintf(out, "%0*d", prec, (int)remainder);
} }
number /= tenpow;
fillme -= digitcount;
// Pad unused cells with spaces
while (fillme-- > 0) {
*out++ = ' ';
}
// Handle negative sign
if (negative) *out++ = '-';
// Print the digits, and if necessary, the decimal point
digitcount += prec;
int8_t digit = 0;
while (digitcount-- > 0) {
digit = (int8_t)number;
if (digit > 9) digit = 9; // insurance
*out++ = (char)('0' | digit);
if ((digitcount == prec) && (prec > 0)) {
*out++ = '.';
}
number -= digit;
number *= 10.0;
}
// make sure the string is terminated
*out = 0;
return s; return s;
} }

View File

@ -1,5 +1,5 @@
SPIFFS (SPI Flash File System) SPIFFS (SPI Flash File System)
V0.3.0 V0.3.2
Copyright (c) 2013-2015 Peter Andersson (pelleplutt1976<at>gmail.com) Copyright (c) 2013-2015 Peter Andersson (pelleplutt1976<at>gmail.com)
@ -58,6 +58,30 @@ For testing and contributions, see the docs/IMPLEMENTING file.
* HISTORY * HISTORY
0.3.2
Limit cache size if too much cache is given (thanks pgeiem)
New feature - Controlled erase. #23
SPIFFS_rename leaks file descriptors #28 (thanks benpicco)
moved dbg print defines in test framework to params_test.h
lseek should return the resulting offset (thanks hefloryd)
fixed type on dbg ifdefs
silence warning about signed/unsigned comparison when spiffs_obj_id is 32 bit (thanks benpicco)
Possible error in test_spiffs.c #21 (thanks yihcdaso-yeskela)
Cache might writethrough too often #16
even moar testrunner updates
Test framework update and some added tests
Some thoughts for next gen
Test sigsevs when having too many sectors #13 (thanks alonewolfx2)
GC might be suboptimal #11
Fix eternal readdir when objheader at last block, last entry
New API functions:
SPIFFS_gc_quick - call a nonintrusive gc
SPIFFS_gc - call a full-scale intrusive gc
0.3.1
Removed two return warnings, was too triggerhappy on release
0.3.0 0.3.0
Added existing namecheck when creating files Added existing namecheck when creating files
Lots of static analysis bugs #6 Lots of static analysis bugs #6

View File

@ -9,7 +9,7 @@
#ifndef SPIFFS_H_ #ifndef SPIFFS_H_
#define SPIFFS_H_ #define SPIFFS_H_
#ifdef __cplusplus #if defined(__cplusplus)
extern "C" { extern "C" {
#endif #endif
@ -47,6 +47,9 @@ extern "C" {
#define SPIFFS_ERR_ERASE_FAIL -10027 #define SPIFFS_ERR_ERASE_FAIL -10027
#define SPIFFS_ERR_MAGIC_NOT_POSSIBLE -10028 #define SPIFFS_ERR_MAGIC_NOT_POSSIBLE -10028
#define SPIFFS_ERR_NO_DELETED_BLOCKS -10029
#define SPIFFS_ERR_FILE_EXISTS -10030
#define SPIFFS_ERR_INTERNAL -10050 #define SPIFFS_ERR_INTERNAL -10050
@ -62,12 +65,25 @@ typedef u16_t spiffs_mode;
// object type // object type
typedef u8_t spiffs_obj_type; typedef u8_t spiffs_obj_type;
#if SPIFFS_HAL_CALLBACK_EXTRA
struct spiffs_t;
/* spi read call function type */
typedef s32_t (*spiffs_read)(struct spiffs_t *fs, u32_t addr, u32_t size, u8_t *dst);
/* spi write call function type */
typedef s32_t (*spiffs_write)(struct spiffs_t *fs, u32_t addr, u32_t size, u8_t *src);
/* spi erase call function type */
typedef s32_t (*spiffs_erase)(struct spiffs_t *fs, u32_t addr, u32_t size);
#else // SPIFFS_HAL_CALLBACK_EXTRA
/* spi read call function type */ /* spi read call function type */
typedef s32_t (*spiffs_read)(u32_t addr, u32_t size, u8_t *dst); typedef s32_t (*spiffs_read)(u32_t addr, u32_t size, u8_t *dst);
/* spi write call function type */ /* spi write call function type */
typedef s32_t (*spiffs_write)(u32_t addr, u32_t size, u8_t *src); typedef s32_t (*spiffs_write)(u32_t addr, u32_t size, u8_t *src);
/* spi erase call function type */ /* spi erase call function type */
typedef s32_t (*spiffs_erase)(u32_t addr, u32_t size); typedef s32_t (*spiffs_erase)(u32_t addr, u32_t size);
#endif // SPIFFS_HAL_CALLBACK_EXTRA
/* file system check callback report operation */ /* file system check callback report operation */
typedef enum { typedef enum {
@ -88,21 +104,26 @@ typedef enum {
} spiffs_check_report; } spiffs_check_report;
/* file system check callback function */ /* file system check callback function */
#if SPIFFS_HAL_CALLBACK_EXTRA
typedef void (*spiffs_check_callback)(struct spiffs_t *fs, spiffs_check_type type, spiffs_check_report report,
u32_t arg1, u32_t arg2);
#else // SPIFFS_HAL_CALLBACK_EXTRA
typedef void (*spiffs_check_callback)(spiffs_check_type type, spiffs_check_report report, typedef void (*spiffs_check_callback)(spiffs_check_type type, spiffs_check_report report,
u32_t arg1, u32_t arg2); u32_t arg1, u32_t arg2);
#endif // SPIFFS_HAL_CALLBACK_EXTRA
#ifndef SPIFFS_DBG #ifndef SPIFFS_DBG
#define SPIFFS_DBG(...) \ #define SPIFFS_DBG(...) \
print(__VA_ARGS__) print(__VA_ARGS__)
#endif #endif
#ifndef SPIFFS_GC_DBG #ifndef SPIFFS_GC_DBG
#define SPIFFS_GC_DBG(...) c_printf(__VA_ARGS__) #define SPIFFS_GC_DBG(...) printf(__VA_ARGS__)
#endif #endif
#ifndef SPIFFS_CACHE_DBG #ifndef SPIFFS_CACHE_DBG
#define SPIFFS_CACHE_DBG(...) c_printf(__VA_ARGS__) #define SPIFFS_CACHE_DBG(...) printf(__VA_ARGS__)
#endif #endif
#ifndef SPIFFS_CHECK_DBG #ifndef SPIFFS_CHECK_DBG
#define SPIFFS_CHECK_DBG(...) c_printf(__VA_ARGS__) #define SPIFFS_CHECK_DBG(...) printf(__VA_ARGS__)
#endif #endif
/* Any write to the filehandle is appended to end of the file */ /* Any write to the filehandle is appended to end of the file */
@ -119,6 +140,8 @@ typedef void (*spiffs_check_callback)(spiffs_check_type type, spiffs_check_repor
#define SPIFFS_RDWR (SPIFFS_RDONLY | SPIFFS_WRONLY) #define SPIFFS_RDWR (SPIFFS_RDONLY | SPIFFS_WRONLY)
/* Any writes to the filehandle will never be cached */ /* Any writes to the filehandle will never be cached */
#define SPIFFS_DIRECT (1<<5) #define SPIFFS_DIRECT (1<<5)
/* If SPIFFS_CREAT and SPIFFS_EXCL are set, SPIFFS_open() shall fail if the file exists */
#define SPIFFS_EXCL (1<<6)
#define SPIFFS_SEEK_SET (0) #define SPIFFS_SEEK_SET (0)
#define SPIFFS_SEEK_CUR (1) #define SPIFFS_SEEK_CUR (1)
@ -166,7 +189,7 @@ typedef struct {
#endif #endif
} spiffs_config; } spiffs_config;
typedef struct { typedef struct spiffs_t {
// file system configuration // file system configuration
spiffs_config cfg; spiffs_config cfg;
// number of logical blocks // number of logical blocks
@ -224,6 +247,8 @@ typedef struct {
// mounted flag // mounted flag
u8_t mounted; u8_t mounted;
// user data
void *user_data;
// config magic // config magic
u32_t config_magic; u32_t config_magic;
} spiffs; } spiffs;
@ -387,7 +412,7 @@ s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh);
* @param fs the file system struct * @param fs the file system struct
* @param fh the filehandle of the file to close * @param fh the filehandle of the file to close
*/ */
void SPIFFS_close(spiffs *fs, spiffs_file fh); s32_t SPIFFS_close(spiffs *fs, spiffs_file fh);
/** /**
* Renames a file * Renames a file
@ -440,7 +465,6 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e);
*/ */
s32_t SPIFFS_check(spiffs *fs); s32_t SPIFFS_check(spiffs *fs);
/** /**
* Returns number of total bytes available and number of used bytes. * Returns number of total bytes available and number of used bytes.
* This is an estimation, and depends on if there a many files with little * This is an estimation, and depends on if there a many files with little
@ -465,27 +489,60 @@ s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used);
* SPIFFS_format. * SPIFFS_format.
* If SPIFFS_mount fails, SPIFFS_format can be called directly without calling * If SPIFFS_mount fails, SPIFFS_format can be called directly without calling
* SPIFFS_unmount first. * SPIFFS_unmount first.
*
* @param fs the file system struct
*/ */
s32_t SPIFFS_format(spiffs *fs); s32_t SPIFFS_format(spiffs *fs);
/** /**
* Returns nonzero if spiffs is mounted, or zero if unmounted. * Returns nonzero if spiffs is mounted, or zero if unmounted.
* @param fs the file system struct
*/ */
u8_t SPIFFS_mounted(spiffs *fs); u8_t SPIFFS_mounted(spiffs *fs);
/** /**
* Check if EOF reached. * Tries to find a block where most or all pages are deleted, and erase that
* @param fs the file system struct * block if found. Does not care for wear levelling. Will not move pages
* @param fh the filehandle of the file to check * around.
* If parameter max_free_pages are set to 0, only blocks with only deleted
* pages will be selected.
*
* NB: the garbage collector is automatically called when spiffs needs free
* pages. The reason for this function is to give possibility to do background
* tidying when user knows the system is idle.
*
* Use with care.
*
* Setting max_free_pages to anything larger than zero will eventually wear
* flash more as a block containing free pages can be erased.
*
* Will set err_no to SPIFFS_OK if a block was found and erased,
* SPIFFS_ERR_NO_DELETED_BLOCK if no matching block was found,
* or other error.
*
* @param fs the file system struct
* @param max_free_pages maximum number allowed free pages in block
*/ */
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh); s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages);
/** /**
* Get the current position of the data pointer. * Will try to make room for given amount of bytes in the filesystem by moving
* pages and erasing blocks.
* If it is physically impossible, err_no will be set to SPIFFS_ERR_FULL. If
* there already is this amount (or more) of free space, SPIFFS_gc will
* silently return. It is recommended to call SPIFFS_info before invoking
* this method in order to determine what amount of bytes to give.
*
* NB: the garbage collector is automatically called when spiffs needs free
* pages. The reason for this function is to give possibility to do background
* tidying when user knows the system is idle.
*
* Use with care.
*
* @param fs the file system struct * @param fs the file system struct
* @param fh the filehandle of the open file * @param size amount of bytes that should be freed
*/ */
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh); s32_t SPIFFS_gc(spiffs *fs, u32_t size);
#if SPIFFS_TEST_VISUALISATION #if SPIFFS_TEST_VISUALISATION
/** /**
@ -511,8 +568,9 @@ u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages);
#endif #endif
#endif #endif
#if SPIFFS_CACHE
#ifdef __cplusplus #endif
#if defined(__cplusplus)
} }
#endif #endif

View File

@ -20,7 +20,7 @@ static spiffs_cache_page *spiffs_cache_page_get(spiffs *fs, spiffs_page_ix pix)
if ((cache->cpage_use_map & (1<<i)) && if ((cache->cpage_use_map & (1<<i)) &&
(cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 && (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 &&
cp->pix == pix ) { cp->pix == pix ) {
SPIFFS_CACHE_DBG("CACHE_GET: have cache page %d for %04x\n", i, pix); SPIFFS_CACHE_DBG("CACHE_GET: have cache page %i for %04x\n", i, pix);
cp->last_access = cache->last_access; cp->last_access = cache->last_access;
return cp; return cp;
} }
@ -39,16 +39,16 @@ static s32_t spiffs_cache_page_free(spiffs *fs, int ix, u8_t write_back) {
(cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 && (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) == 0 &&
(cp->flags & SPIFFS_CACHE_FLAG_DIRTY)) { (cp->flags & SPIFFS_CACHE_FLAG_DIRTY)) {
u8_t *mem = spiffs_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); res = SPIFFS_HAL_WRITE(fs, SPIFFS_PAGE_TO_PADDR(fs, cp->pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), mem);
} }
cp->flags = 0; cp->flags = 0;
cache->cpage_use_map &= ~(1 << ix); cache->cpage_use_map &= ~(1 << ix);
if (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) { if (cp->flags & SPIFFS_CACHE_FLAG_TYPE_WR) {
SPIFFS_CACHE_DBG("CACHE_FREE: free cache page %d objid %04x\n", ix, cp->obj_id); SPIFFS_CACHE_DBG("CACHE_FREE: free cache page %i objid %04x\n", ix, cp->obj_id);
} else { } else {
SPIFFS_CACHE_DBG("CACHE_FREE: free cache page %d pix %04x\n", ix, cp->pix); SPIFFS_CACHE_DBG("CACHE_FREE: free cache page %i pix %04x\n", ix, cp->pix);
} }
} }
@ -98,7 +98,7 @@ static spiffs_cache_page *spiffs_cache_page_allocate(spiffs *fs) {
spiffs_cache_page *cp = spiffs_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); cache->cpage_use_map |= (1<<i);
cp->last_access = cache->last_access; cp->last_access = cache->last_access;
SPIFFS_CACHE_DBG("CACHE_ALLO: allocated cache page %d\n", i); SPIFFS_CACHE_DBG("CACHE_ALLO: allocated cache page %i\n", i);
return cp; return cp;
} }
} }
@ -137,10 +137,7 @@ s32_t spiffs_phys_rd(
} else { } else {
if ((op & SPIFFS_OP_TYPE_MASK) == SPIFFS_OP_T_OBJ_LU2) { if ((op & SPIFFS_OP_TYPE_MASK) == SPIFFS_OP_T_OBJ_LU2) {
// for second layer lookup functions, we do not cache in order to prevent shredding // for second layer lookup functions, we do not cache in order to prevent shredding
return fs->cfg.hal_read_f( return SPIFFS_HAL_READ(fs, addr, len, dst);
addr ,
len,
dst);
} }
#if SPIFFS_CACHE_STATS #if SPIFFS_CACHE_STATS
fs->cache_misses++; fs->cache_misses++;
@ -151,8 +148,7 @@ s32_t spiffs_phys_rd(
cp->flags = SPIFFS_CACHE_FLAG_WRTHRU; cp->flags = SPIFFS_CACHE_FLAG_WRTHRU;
cp->pix = SPIFFS_PADDR_TO_PAGE(fs, addr); cp->pix = SPIFFS_PADDR_TO_PAGE(fs, addr);
} }
s32_t res2 = SPIFFS_HAL_READ(fs,
s32_t res2 = fs->cfg.hal_read_f(
addr - SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr), addr - SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr),
SPIFFS_CFG_LOG_PAGE_SZ(fs), SPIFFS_CFG_LOG_PAGE_SZ(fs),
spiffs_get_cache_page(fs, cache, cp->ix)); spiffs_get_cache_page(fs, cache, cp->ix));
@ -161,7 +157,7 @@ s32_t spiffs_phys_rd(
} }
} }
u8_t *mem = spiffs_get_cache_page(fs, cache, cp->ix); u8_t *mem = spiffs_get_cache_page(fs, cache, cp->ix);
c_memcpy(dst, &mem[SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr)], len); memcpy(dst, &mem[SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr)], len);
return res; return res;
} }
@ -186,24 +182,24 @@ s32_t spiffs_phys_wr(
(op & SPIFFS_OP_TYPE_MASK) != SPIFFS_OP_T_OBJ_LU) { (op & SPIFFS_OP_TYPE_MASK) != SPIFFS_OP_T_OBJ_LU) {
// page is being deleted, wipe from cache - unless it is a lookup page // page is being deleted, wipe from cache - unless it is a lookup page
spiffs_cache_page_free(fs, cp->ix, 0); spiffs_cache_page_free(fs, cp->ix, 0);
return fs->cfg.hal_write_f(addr, len, src); return SPIFFS_HAL_WRITE(fs, addr, len, src);
} }
u8_t *mem = spiffs_get_cache_page(fs, cache, cp->ix); u8_t *mem = spiffs_get_cache_page(fs, cache, cp->ix);
c_memcpy(&mem[SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr)], src, len); memcpy(&mem[SPIFFS_PADDR_TO_PAGE_OFFSET(fs, addr)], src, len);
cache->last_access++; cache->last_access++;
cp->last_access = cache->last_access; cp->last_access = cache->last_access;
if (cp->flags && SPIFFS_CACHE_FLAG_WRTHRU) { if (cp->flags & SPIFFS_CACHE_FLAG_WRTHRU) {
// page is being updated, no write-cache, just pass thru // page is being updated, no write-cache, just pass thru
return fs->cfg.hal_write_f(addr, len, src); return SPIFFS_HAL_WRITE(fs, addr, len, src);
} else { } else {
return SPIFFS_OK; return SPIFFS_OK;
} }
} else { } else {
// no cache page, no write cache - just write thru // no cache page, no write cache - just write thru
return fs->cfg.hal_write_f(addr, len, src); return SPIFFS_HAL_WRITE(fs, addr, len, src);
} }
} }
@ -282,17 +278,17 @@ void spiffs_cache_init(spiffs *fs) {
} }
spiffs_cache cache; spiffs_cache cache;
c_memset(&cache, 0, sizeof(spiffs_cache)); memset(&cache, 0, sizeof(spiffs_cache));
cache.cpage_count = cache_entries; cache.cpage_count = cache_entries;
cache.cpages = (u8_t *)((u8_t *)fs->cache + sizeof(spiffs_cache)); cache.cpages = (u8_t *)((u8_t *)fs->cache + sizeof(spiffs_cache));
cache.cpage_use_map = 0xffffffff; cache.cpage_use_map = 0xffffffff;
cache.cpage_use_mask = cache_mask; cache.cpage_use_mask = cache_mask;
c_memcpy(fs->cache, &cache, sizeof(spiffs_cache)); memcpy(fs->cache, &cache, sizeof(spiffs_cache));
spiffs_cache *c = spiffs_get_cache(fs); spiffs_cache *c = spiffs_get_cache(fs);
c_memset(c->cpages, 0, c->cpage_count * SPIFFS_CACHE_PAGE_SIZE(fs)); memset(c->cpages, 0, c->cpage_count * SPIFFS_CACHE_PAGE_SIZE(fs));
c->cpage_use_map &= ~(c->cpage_use_mask); c->cpage_use_map &= ~(c->cpage_use_mask);
for (i = 0; i < cache.cpage_count; i++) { for (i = 0; i < cache.cpage_count; i++) {

View File

@ -22,6 +22,19 @@
#include "spiffs.h" #include "spiffs.h"
#include "spiffs_nucleus.h" #include "spiffs_nucleus.h"
#if SPIFFS_HAL_CALLBACK_EXTRA
#define CHECK_CB(_fs, _type, _rep, _arg1, _arg2) \
do { \
if ((_fs)->check_cb_f) (_fs)->check_cb_f((_fs), (_type), (_rep), (_arg1), (_arg2)); \
} while (0)
#else
#define CHECK_CB(_fs, _type, _rep, _arg1, _arg2) \
do { \
if ((_fs)->check_cb_f) (_fs)->check_cb_f((_type), (_rep), (_arg1), (_arg2)); \
} while (0)
#endif
//--------------------------------------- //---------------------------------------
// Look up consistency // Look up consistency
@ -190,13 +203,13 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
res = spiffs_rewrite_index(fs, p_hdr->obj_id, p_hdr->span_ix, new_pix, objix_pix); res = spiffs_rewrite_index(fs, p_hdr->obj_id, p_hdr->span_ix, new_pix, objix_pix);
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) { if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
// index bad also, cannot mend this file // index bad also, cannot mend this file
SPIFFS_CHECK_DBG("LU: FIXUP: index bad %d, cannot mend!\n", res); SPIFFS_CHECK_DBG("LU: FIXUP: index bad %i, cannot mend!\n", res);
res = spiffs_page_delete(fs, new_pix); res = spiffs_page_delete(fs, new_pix);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
res = spiffs_delete_obj_lazy(fs, p_hdr->obj_id); res = spiffs_delete_obj_lazy(fs, p_hdr->obj_id);
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr->obj_id, 0); CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr->obj_id, 0);
} else { } else {
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, p_hdr->obj_id, p_hdr->span_ix); CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, p_hdr->obj_id, p_hdr->span_ix);
} }
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
} }
@ -216,7 +229,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
SPIFFS_CHECK_DBG("LU: FIXUP: ix page with data not found elsewhere, rewriting %04x to new page %04x\n", cur_pix, new_pix); SPIFFS_CHECK_DBG("LU: FIXUP: ix page with data not found elsewhere, rewriting %04x to new page %04x\n", cur_pix, new_pix);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
*reload_lu = 1; *reload_lu = 1;
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix); CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
} }
} else { } else {
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
@ -249,12 +262,12 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
res = spiffs_rewrite_index(fs, p_hdr->obj_id, p_hdr->span_ix, new_pix, objix_pix); res = spiffs_rewrite_index(fs, p_hdr->obj_id, p_hdr->span_ix, new_pix, objix_pix);
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) { if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
// index bad also, cannot mend this file // index bad also, cannot mend this file
SPIFFS_CHECK_DBG("LU: FIXUP: index bad %d, cannot mend!\n", res); SPIFFS_CHECK_DBG("LU: FIXUP: index bad %i, cannot mend!\n", res);
res = spiffs_page_delete(fs, new_pix); res = spiffs_page_delete(fs, new_pix);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
res = spiffs_delete_obj_lazy(fs, p_hdr->obj_id); res = spiffs_delete_obj_lazy(fs, p_hdr->obj_id);
*reload_lu = 1; *reload_lu = 1;
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr->obj_id, 0); CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr->obj_id, 0);
} }
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
} }
@ -306,7 +319,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
new_ph.obj_id = p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG; new_ph.obj_id = p_hdr->obj_id | SPIFFS_OBJ_ID_IX_FLAG;
res = spiffs_rewrite_page(fs, cur_pix, &new_ph, &new_pix); res = spiffs_rewrite_page(fs, cur_pix, &new_ph, &new_pix);
SPIFFS_CHECK_DBG("LU: FIXUP: rewrite page %04x as %04x to pix %04x\n", cur_pix, new_ph.obj_id, new_pix); SPIFFS_CHECK_DBG("LU: FIXUP: rewrite page %04x as %04x to pix %04x\n", cur_pix, new_ph.obj_id, new_pix);
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix); CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
*reload_lu = 1; *reload_lu = 1;
} else if ((objix_pix_ph && data_pix_ph && data_pix_lu && objix_pix_lu == 0) || } else if ((objix_pix_ph && data_pix_ph && data_pix_lu && objix_pix_lu == 0) ||
@ -315,7 +328,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
// rewrite as obj_id_lu // rewrite as obj_id_lu
new_ph.obj_id = lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG; new_ph.obj_id = lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG;
SPIFFS_CHECK_DBG("LU: FIXUP: rewrite page %04x as %04x\n", cur_pix, new_ph.obj_id); SPIFFS_CHECK_DBG("LU: FIXUP: rewrite page %04x as %04x\n", cur_pix, new_ph.obj_id);
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix); CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
res = spiffs_rewrite_page(fs, cur_pix, &new_ph, &new_pix); res = spiffs_rewrite_page(fs, cur_pix, &new_ph, &new_pix);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
*reload_lu = 1; *reload_lu = 1;
@ -353,7 +366,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
// if only data page exists, make this page index // if only data page exists, make this page index
if (data_pix && objix_pix_d == 0) { if (data_pix && objix_pix_d == 0) {
SPIFFS_CHECK_DBG("LU: FIXUP: other data page exists, make this index\n"); SPIFFS_CHECK_DBG("LU: FIXUP: other data page exists, make this index\n");
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, lu_obj_id, p_hdr->span_ix); CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, lu_obj_id, p_hdr->span_ix);
spiffs_page_header new_ph; spiffs_page_header new_ph;
spiffs_page_ix new_pix; spiffs_page_ix new_pix;
new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX); new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_INDEX);
@ -369,7 +382,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
// if only index exists, make data page // if only index exists, make data page
if (data_pix == 0 && objix_pix_d) { if (data_pix == 0 && objix_pix_d) {
SPIFFS_CHECK_DBG("LU: FIXUP: other index page exists, make this data\n"); SPIFFS_CHECK_DBG("LU: FIXUP: other index page exists, make this data\n");
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, lu_obj_id, p_hdr->span_ix); CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, lu_obj_id, p_hdr->span_ix);
spiffs_page_header new_ph; spiffs_page_header new_ph;
spiffs_page_ix new_pix; spiffs_page_ix new_pix;
new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL); new_ph.flags = 0xff & ~(SPIFFS_PH_FLAG_USED | SPIFFS_PH_FLAG_FINAL);
@ -406,7 +419,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
// page referenced by object index but not final // page referenced by object index but not final
// just finalize // just finalize
SPIFFS_CHECK_DBG("LU: FIXUP: unfinalized page is referred, finalizing\n"); SPIFFS_CHECK_DBG("LU: FIXUP: unfinalized page is referred, finalizing\n");
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix); CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, p_hdr->obj_id, p_hdr->span_ix);
u8_t flags = 0xff & ~SPIFFS_PH_FLAG_FINAL; u8_t flags = 0xff & ~SPIFFS_PH_FLAG_FINAL;
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT, res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + offsetof(spiffs_page_header, flags), 0, SPIFFS_PAGE_TO_PADDR(fs, cur_pix) + offsetof(spiffs_page_header, flags),
@ -418,7 +431,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
if (delete_page) { if (delete_page) {
SPIFFS_CHECK_DBG("LU: FIXUP: deleting page %04x\n", cur_pix); SPIFFS_CHECK_DBG("LU: FIXUP: deleting page %04x\n", cur_pix);
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_PAGE, cur_pix, 0); CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_DELETE_PAGE, cur_pix, 0);
res = spiffs_page_delete(fs, cur_pix); res = spiffs_page_delete(fs, cur_pix);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
} }
@ -434,7 +447,7 @@ static s32_t spiffs_lookup_check_v(spiffs *fs, spiffs_obj_id obj_id, spiffs_bloc
spiffs_page_header p_hdr; spiffs_page_header p_hdr;
spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, cur_block, cur_entry); spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, cur_block, cur_entry);
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS,
(cur_block * 256)/fs->block_count, 0); (cur_block * 256)/fs->block_count, 0);
// load header // load header
@ -460,7 +473,7 @@ s32_t spiffs_lookup_consistency_check(spiffs *fs, u8_t check_all_objects) {
(void)check_all_objects; (void)check_all_objects;
s32_t res = SPIFFS_OK; s32_t res = SPIFFS_OK;
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 0, 0); CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 0, 0);
res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_lookup_check_v, 0, 0, 0, 0); res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_lookup_check_v, 0, 0, 0, 0);
@ -469,10 +482,10 @@ s32_t spiffs_lookup_consistency_check(spiffs *fs, u8_t check_all_objects) {
} }
if (res != SPIFFS_OK) { if (res != SPIFFS_OK) {
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_ERROR, res, 0); CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_ERROR, res, 0);
} }
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 256, 0); CHECK_CB(fs, SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 256, 0);
return res; return res;
} }
@ -501,19 +514,22 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
while (pix_offset < SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count) { while (pix_offset < SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count) {
// set this flag to abort all checks and rescan the page range // set this flag to abort all checks and rescan the page range
u8_t restart = 0; u8_t restart = 0;
c_memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs)); memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
spiffs_block_ix cur_block = 0; spiffs_block_ix cur_block = 0;
// build consistency bitmap for id range traversing all blocks // build consistency bitmap for id range traversing all blocks
while (!restart && cur_block < fs->block_count) { while (!restart && cur_block < fs->block_count) {
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS,
(pix_offset*256)/(SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count) + (pix_offset*256)/(SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count) +
((((cur_block * pages_per_scan * 256)/ (SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count))) / fs->block_count), ((((cur_block * pages_per_scan * 256)/ (SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count))) / fs->block_count),
0); 0);
// traverse each page except for lookup pages // traverse each page except for lookup pages
spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_PAGES(fs) + SPIFFS_PAGES_PER_BLOCK(fs) * cur_block; spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_PAGES(fs) + SPIFFS_PAGES_PER_BLOCK(fs) * cur_block;
while (!restart && cur_pix < SPIFFS_PAGES_PER_BLOCK(fs) * (cur_block+1)) { while (!restart && cur_pix < SPIFFS_PAGES_PER_BLOCK(fs) * (cur_block+1)) {
//if ((cur_pix & 0xff) == 0)
// SPIFFS_CHECK_DBG("PA: processing pix %08x, block %08x of pix %08x, block %08x\n",
// cur_pix, cur_block, SPIFFS_PAGES_PER_BLOCK(fs) * fs->block_count, fs->block_count);
// read header // read header
spiffs_page_header p_hdr; spiffs_page_header p_hdr;
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ, res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
@ -597,12 +613,12 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
data_spix_offset + i, data_pix, cur_pix); data_spix_offset + i, data_pix, cur_pix);
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) { if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
// index bad also, cannot mend this file // index bad also, cannot mend this file
SPIFFS_CHECK_DBG("PA: FIXUP: index bad %d, cannot mend - delete object\n", res); SPIFFS_CHECK_DBG("PA: FIXUP: index bad %i, cannot mend - delete object\n", res);
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, objix_p_hdr->obj_id, 0); CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, objix_p_hdr->obj_id, 0);
// delete file // delete file
res = spiffs_page_delete(fs, cur_pix); res = spiffs_page_delete(fs, cur_pix);
} else { } else {
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, objix_p_hdr->obj_id, objix_p_hdr->span_ix); CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, objix_p_hdr->obj_id, objix_p_hdr->span_ix);
} }
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
restart = 1; restart = 1;
@ -636,7 +652,7 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
if (data_pix == 0) { if (data_pix == 0) {
// not found, this index is badly borked // not found, this index is badly borked
SPIFFS_CHECK_DBG("PA: FIXUP: index bad, delete object id %04x\n", p_hdr.obj_id); SPIFFS_CHECK_DBG("PA: FIXUP: index bad, delete object id %04x\n", p_hdr.obj_id);
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0); CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id); res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
break; break;
@ -647,11 +663,11 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
res = spiffs_rewrite_index(fs, p_hdr.obj_id, data_spix_offset + i, data_pix, cur_pix); res = spiffs_rewrite_index(fs, p_hdr.obj_id, data_spix_offset + i, data_pix, cur_pix);
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) { if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
// index bad also, cannot mend this file // index bad also, cannot mend this file
SPIFFS_CHECK_DBG("PA: FIXUP: index bad %d, cannot mend!\n", res); SPIFFS_CHECK_DBG("PA: FIXUP: index bad %i, cannot mend!\n", res);
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0); CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id); res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
} else { } else {
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, p_hdr.obj_id, p_hdr.span_ix); CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, p_hdr.obj_id, p_hdr.span_ix);
} }
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
restart = 1; restart = 1;
@ -669,7 +685,7 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
// the object which is referring to this page // the object which is referring to this page
SPIFFS_CHECK_DBG("PA: FIXUP: removing object %04x and page %04x\n", SPIFFS_CHECK_DBG("PA: FIXUP: removing object %04x and page %04x\n",
p_hdr.obj_id, cur_pix); p_hdr.obj_id, cur_pix);
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0); CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id); res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
// extra precaution, delete this page also // extra precaution, delete this page also
@ -763,20 +779,20 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
res = spiffs_rewrite_index(fs, p_hdr.obj_id, p_hdr.span_ix, cur_pix, objix_pix); res = spiffs_rewrite_index(fs, p_hdr.obj_id, p_hdr.span_ix, cur_pix, objix_pix);
if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) { if (res <= _SPIFFS_ERR_CHECK_FIRST && res > _SPIFFS_ERR_CHECK_LAST) {
// index bad also, cannot mend this file // index bad also, cannot mend this file
SPIFFS_CHECK_DBG("PA: FIXUP: index bad %d, cannot mend!\n", res); SPIFFS_CHECK_DBG("PA: FIXUP: index bad %i, cannot mend!\n", res);
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0); CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_BAD_FILE, p_hdr.obj_id, 0);
res = spiffs_page_delete(fs, cur_pix); res = spiffs_page_delete(fs, cur_pix);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id); res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
} else { } else {
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, p_hdr.obj_id, p_hdr.span_ix); CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_FIX_INDEX, p_hdr.obj_id, p_hdr.span_ix);
} }
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
restart = 1; restart = 1;
continue; continue;
} else if (delete_page) { } else if (delete_page) {
SPIFFS_CHECK_DBG("PA: FIXUP: deleting page %04x\n", cur_pix); SPIFFS_CHECK_DBG("PA: FIXUP: deleting page %04x\n", cur_pix);
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_PAGE, cur_pix, 0); CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_DELETE_PAGE, cur_pix, 0);
res = spiffs_page_delete(fs, cur_pix); res = spiffs_page_delete(fs, cur_pix);
} }
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
@ -818,6 +834,8 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
} }
} }
} }
SPIFFS_CHECK_DBG("PA: processed %04x, restart %i\n", pix_offset, restart);
// next page range // next page range
if (!restart) { if (!restart) {
pix_offset += pages_per_scan; pix_offset += pages_per_scan;
@ -828,12 +846,12 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
// Checks consistency amongst all pages and fixes irregularities // Checks consistency amongst all pages and fixes irregularities
s32_t spiffs_page_consistency_check(spiffs *fs) { s32_t spiffs_page_consistency_check(spiffs *fs) {
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, 0, 0); CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, 0, 0);
s32_t res = spiffs_page_consistency_check_i(fs); s32_t res = spiffs_page_consistency_check_i(fs);
if (res != SPIFFS_OK) { if (res != SPIFFS_OK) {
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_ERROR, res, 0); CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_ERROR, res, 0);
} }
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, 256, 0); CHECK_CB(fs, SPIFFS_CHECK_PAGE, SPIFFS_CHECK_PROGRESS, 256, 0);
return res; return res;
} }
@ -862,7 +880,7 @@ static s32_t spiffs_object_index_consistency_check_v(spiffs *fs, spiffs_obj_id o
u32_t *log_ix = (u32_t *)user_p; u32_t *log_ix = (u32_t *)user_p;
spiffs_obj_id *obj_table = (spiffs_obj_id *)fs->work; spiffs_obj_id *obj_table = (spiffs_obj_id *)fs->work;
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS,
(cur_block * 256)/fs->block_count, 0); (cur_block * 256)/fs->block_count, 0);
if (obj_id != SPIFFS_OBJ_ID_FREE && obj_id != SPIFFS_OBJ_ID_DELETED && (obj_id & SPIFFS_OBJ_ID_IX_FLAG)) { if (obj_id != SPIFFS_OBJ_ID_FREE && obj_id != SPIFFS_OBJ_ID_DELETED && (obj_id & SPIFFS_OBJ_ID_IX_FLAG)) {
@ -879,7 +897,7 @@ static s32_t spiffs_object_index_consistency_check_v(spiffs *fs, spiffs_obj_id o
(SPIFFS_PH_FLAG_DELET)) { (SPIFFS_PH_FLAG_DELET)) {
SPIFFS_CHECK_DBG("IX: pix %04x, obj id:%04x spix:%04x header not fully deleted - deleting\n", SPIFFS_CHECK_DBG("IX: pix %04x, obj id:%04x spix:%04x header not fully deleted - deleting\n",
cur_pix, obj_id, p_hdr.span_ix); cur_pix, obj_id, p_hdr.span_ix);
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_INDEX, SPIFFS_CHECK_DELETE_PAGE, cur_pix, obj_id); CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_DELETE_PAGE, cur_pix, obj_id);
res = spiffs_page_delete(fs, cur_pix); res = spiffs_page_delete(fs, cur_pix);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
return res_c; return res_c;
@ -935,7 +953,7 @@ static s32_t spiffs_object_index_consistency_check_v(spiffs *fs, spiffs_obj_id o
if (delete) { if (delete) {
SPIFFS_CHECK_DBG("IX: FIXUP: pix %04x, obj id:%04x spix:%04x is orphan index - deleting\n", SPIFFS_CHECK_DBG("IX: FIXUP: pix %04x, obj id:%04x spix:%04x is orphan index - deleting\n",
cur_pix, obj_id, p_hdr.span_ix); cur_pix, obj_id, p_hdr.span_ix);
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_INDEX, SPIFFS_CHECK_DELETE_ORPHANED_INDEX, cur_pix, obj_id); CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_DELETE_ORPHANED_INDEX, cur_pix, obj_id);
res = spiffs_page_delete(fs, cur_pix); res = spiffs_page_delete(fs, cur_pix);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
} }
@ -956,18 +974,18 @@ s32_t spiffs_object_index_consistency_check(spiffs *fs) {
// indicating whether they can be reached or not. Acting as a fifo if object ids cannot fit. // indicating whether they can be reached or not. Acting as a fifo if object ids cannot fit.
// In the temporary object index memory, SPIFFS_OBJ_ID_IX_FLAG bit is used to indicate // In the temporary object index memory, SPIFFS_OBJ_ID_IX_FLAG bit is used to indicate
// a reachable/unreachable object id. // a reachable/unreachable object id.
c_memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs)); memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
u32_t obj_id_log_ix = 0; u32_t obj_id_log_ix = 0;
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, 0, 0); CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, 0, 0);
res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_object_index_consistency_check_v, 0, &obj_id_log_ix, res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_object_index_consistency_check_v, 0, &obj_id_log_ix,
0, 0); 0, 0);
if (res == SPIFFS_VIS_END) { if (res == SPIFFS_VIS_END) {
res = SPIFFS_OK; res = SPIFFS_OK;
} }
if (res != SPIFFS_OK) { if (res != SPIFFS_OK) {
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_INDEX, SPIFFS_CHECK_ERROR, res, 0); CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_ERROR, res, 0);
} }
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, 256, 0); CHECK_CB(fs, SPIFFS_CHECK_INDEX, SPIFFS_CHECK_PROGRESS, 256, 0);
return res; return res;
} }

View File

@ -9,7 +9,7 @@ static s32_t spiffs_gc_erase_block(
spiffs_block_ix bix) { spiffs_block_ix bix) {
s32_t res; s32_t res;
SPIFFS_GC_DBG("gc: erase block %d\n", bix); SPIFFS_GC_DBG("gc: erase block %i\n", bix);
res = spiffs_erase_block(fs, bix); res = spiffs_erase_block(fs, bix);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
@ -28,7 +28,7 @@ static s32_t spiffs_gc_erase_block(
// the block is erased. Compared to the non-quick gc, the quick one ensures // the block is erased. Compared to the non-quick gc, the quick one ensures
// that no updates are needed on existing objects on pages that are erased. // that no updates are needed on existing objects on pages that are erased.
s32_t spiffs_gc_quick( s32_t spiffs_gc_quick(
spiffs *fs) { spiffs *fs, u16_t max_free_pages) {
s32_t res = SPIFFS_OK; s32_t res = SPIFFS_OK;
u32_t blocks = fs->block_count; u32_t blocks = fs->block_count;
spiffs_block_ix cur_block = 0; spiffs_block_ix cur_block = 0;
@ -47,6 +47,7 @@ s32_t spiffs_gc_quick(
// check each block // check each block
while (res == SPIFFS_OK && blocks--) { while (res == SPIFFS_OK && blocks--) {
u16_t deleted_pages_in_block = 0; u16_t deleted_pages_in_block = 0;
u16_t free_pages_in_block = 0;
int obj_lookup_page = 0; int obj_lookup_page = 0;
// check each object lookup page // check each object lookup page
@ -63,9 +64,12 @@ s32_t spiffs_gc_quick(
deleted_pages_in_block++; deleted_pages_in_block++;
} else if (obj_id == SPIFFS_OBJ_ID_FREE) { } else if (obj_id == SPIFFS_OBJ_ID_FREE) {
// kill scan, go for next block // kill scan, go for next block
obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs); free_pages_in_block++;
res = 1; // kill object lu loop if (free_pages_in_block > max_free_pages) {
break; obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs);
res = 1; // kill object lu loop
break;
}
} else { } else {
// kill scan, go for next block // kill scan, go for next block
obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs); obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs);
@ -78,7 +82,9 @@ s32_t spiffs_gc_quick(
} // per object lookup page } // per object lookup page
if (res == 1) res = SPIFFS_OK; if (res == 1) res = SPIFFS_OK;
if (res == SPIFFS_OK && deleted_pages_in_block == SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) { if (res == SPIFFS_OK &&
deleted_pages_in_block + free_pages_in_block == SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs) &&
free_pages_in_block <= max_free_pages) {
// found a fully deleted block // found a fully deleted block
fs->stats_p_deleted -= deleted_pages_in_block; fs->stats_p_deleted -= deleted_pages_in_block;
res = spiffs_gc_erase_block(fs, cur_block); res = spiffs_gc_erase_block(fs, cur_block);
@ -90,10 +96,13 @@ s32_t spiffs_gc_quick(
cur_block_addr += SPIFFS_CFG_LOG_BLOCK_SZ(fs); cur_block_addr += SPIFFS_CFG_LOG_BLOCK_SZ(fs);
} // per block } // per block
if (res == SPIFFS_OK) {
res = SPIFFS_ERR_NO_DELETED_BLOCKS;
}
return res; return res;
} }
// Checks if garbaga collecting is necessary. If so a candidate block is found, // Checks if garbage collecting is necessary. If so a candidate block is found,
// cleansed and erased // cleansed and erased
s32_t spiffs_gc_check( s32_t spiffs_gc_check(
spiffs *fs, spiffs *fs,
@ -111,16 +120,16 @@ s32_t spiffs_gc_check(
u32_t needed_pages = (len + SPIFFS_DATA_PAGE_SIZE(fs) - 1) / SPIFFS_DATA_PAGE_SIZE(fs); u32_t needed_pages = (len + SPIFFS_DATA_PAGE_SIZE(fs) - 1) / SPIFFS_DATA_PAGE_SIZE(fs);
// if (fs->free_blocks <= 2 && (s32_t)needed_pages > free_pages) { // if (fs->free_blocks <= 2 && (s32_t)needed_pages > free_pages) {
// SPIFFS_GC_DBG("gc: full freeblk:%d needed:%d free:%d dele:%d\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted); // SPIFFS_GC_DBG("gc: full freeblk:%i needed:%i free:%i dele:%i\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted);
// return SPIFFS_ERR_FULL; // return SPIFFS_ERR_FULL;
// } // }
if ((s32_t)needed_pages > (s32_t)(free_pages + fs->stats_p_deleted)) { if ((s32_t)needed_pages > (s32_t)(free_pages + fs->stats_p_deleted)) {
SPIFFS_GC_DBG("gc_check: full freeblk:%d needed:%d free:%d dele:%d\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted); SPIFFS_GC_DBG("gc_check: full freeblk:%i needed:%i free:%i dele:%i\n", fs->free_blocks, needed_pages, free_pages, fs->stats_p_deleted);
return SPIFFS_ERR_FULL; return SPIFFS_ERR_FULL;
} }
do { do {
SPIFFS_GC_DBG("\ngc_check #%d: run gc free_blocks:%d pfree:%d pallo:%d pdele:%d [%d] len:%d of %d\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, tries,
fs->free_blocks, free_pages, fs->stats_p_allocated, fs->stats_p_deleted, (free_pages+fs->stats_p_allocated+fs->stats_p_deleted), 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)); len, free_pages*SPIFFS_DATA_PAGE_SIZE(fs));
@ -141,13 +150,13 @@ s32_t spiffs_gc_check(
#endif #endif
cand = cands[0]; cand = cands[0];
fs->cleaning = 1; fs->cleaning = 1;
//c_printf("gcing: cleaning block %d\n", cand); //printf("gcing: cleaning block %i\n", cand);
res = spiffs_gc_clean(fs, cand); res = spiffs_gc_clean(fs, cand);
fs->cleaning = 0; fs->cleaning = 0;
if (res < 0) { if (res < 0) {
SPIFFS_GC_DBG("gc_check: cleaning block %d, result %d\n", cand, res); SPIFFS_GC_DBG("gc_check: cleaning block %i, result %i\n", cand, res);
} else { } else {
SPIFFS_GC_DBG("gc_check: cleaning block %d, result %d\n", cand, res); SPIFFS_GC_DBG("gc_check: cleaning block %i, result %i\n", cand, res);
} }
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
@ -177,7 +186,7 @@ s32_t spiffs_gc_check(
res = SPIFFS_ERR_FULL; res = SPIFFS_ERR_FULL;
} }
SPIFFS_GC_DBG("gc_check: finished, %d dirty, blocks %d free, %d pages free, %d tries, res %d\n", SPIFFS_GC_DBG("gc_check: finished, %i dirty, blocks %i free, %i pages free, %i tries, res %i\n",
fs->stats_p_allocated + fs->stats_p_deleted, fs->stats_p_allocated + fs->stats_p_deleted,
fs->free_blocks, free_pages, tries, res); fs->free_blocks, free_pages, tries, res);
@ -215,7 +224,7 @@ s32_t spiffs_gc_erase_page_stats(
} // per entry } // per entry
obj_lookup_page++; obj_lookup_page++;
} // per object lookup page } // per object lookup page
SPIFFS_GC_DBG("gc_check: wipe pallo:%d pdele:%d\n", allo, dele); SPIFFS_GC_DBG("gc_check: wipe pallo:%i pdele:%i\n", allo, dele);
fs->stats_p_allocated -= allo; fs->stats_p_allocated -= allo;
fs->stats_p_deleted -= dele; fs->stats_p_deleted -= dele;
return res; return res;
@ -237,13 +246,18 @@ s32_t spiffs_gc_find_candidate(
// using fs->work area as sorted candidate memory, (spiffs_block_ix)cand_bix/(s32_t)score // 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))); int max_candidates = MIN(fs->block_count, (SPIFFS_CFG_LOG_PAGE_SZ(fs)-8)/(sizeof(spiffs_block_ix) + sizeof(s32_t)));
*candidate_count = 0; *candidate_count = 0;
c_memset(fs->work, 0xff, SPIFFS_CFG_LOG_PAGE_SZ(fs)); memset(fs->work, 0xff, SPIFFS_CFG_LOG_PAGE_SZ(fs));
// divide up work area into block indices and scores // divide up work area into block indices and scores
// todo alignment?
spiffs_block_ix *cand_blocks = (spiffs_block_ix *)fs->work; spiffs_block_ix *cand_blocks = (spiffs_block_ix *)fs->work;
s32_t *cand_scores = (s32_t *)(fs->work + max_candidates * sizeof(spiffs_block_ix)); s32_t *cand_scores = (s32_t *)(fs->work + max_candidates * sizeof(spiffs_block_ix));
// align cand_scores on s32_t boundary
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wpointer-to-int-cast"
cand_scores = (s32_t*)(((u32_t)cand_scores + sizeof(s32_t) - 1) & ~(sizeof(s32_t) - 1));
#pragma GCC diagnostic pop
*block_candidates = cand_blocks; *block_candidates = cand_blocks;
int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id)); int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
@ -301,7 +315,7 @@ s32_t spiffs_gc_find_candidate(
used_pages_in_block * SPIFFS_GC_HEUR_W_USED + used_pages_in_block * SPIFFS_GC_HEUR_W_USED +
erase_age * (fs_crammed ? 0 : SPIFFS_GC_HEUR_W_ERASE_AGE); erase_age * (fs_crammed ? 0 : SPIFFS_GC_HEUR_W_ERASE_AGE);
int cand_ix = 0; int cand_ix = 0;
SPIFFS_GC_DBG("gc_check: bix:%d del:%d use:%d score:%d\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) { while (cand_ix < max_candidates) {
if (cand_blocks[cand_ix] == (spiffs_block_ix)-1) { if (cand_blocks[cand_ix] == (spiffs_block_ix)-1) {
cand_blocks[cand_ix] = cur_block; cand_blocks[cand_ix] = cur_block;
@ -370,20 +384,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_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work; spiffs_page_object_ix *objix = (spiffs_page_object_ix *)fs->work;
SPIFFS_GC_DBG("gc_clean: cleaning block %d\n", bix); SPIFFS_GC_DBG("gc_clean: cleaning block %i\n", bix);
c_memset(&gc, 0, sizeof(spiffs_gc)); memset(&gc, 0, sizeof(spiffs_gc));
gc.state = FIND_OBJ_DATA; gc.state = FIND_OBJ_DATA;
if (fs->free_cursor_block_ix == bix) { if (fs->free_cursor_block_ix == bix) {
// move free cursor to next block, cannot use free pages from the block we want to clean // 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_block_ix = (bix+1)%fs->block_count;
fs->free_cursor_obj_lu_entry = 0; fs->free_cursor_obj_lu_entry = 0;
SPIFFS_GC_DBG("gc_clean: move free cursor to block %d\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) { while (res == SPIFFS_OK && gc.state != FINISHED) {
SPIFFS_GC_DBG("gc_clean: state = %d entry:%d\n", gc.state, cur_entry); SPIFFS_GC_DBG("gc_clean: state = %i entry:%i\n", gc.state, cur_entry);
gc.obj_id_found = 0; gc.obj_id_found = 0;
// scan through lookup pages // scan through lookup pages
@ -406,7 +420,7 @@ s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
case FIND_OBJ_DATA: case FIND_OBJ_DATA:
if (obj_id != SPIFFS_OBJ_ID_DELETED && obj_id != SPIFFS_OBJ_ID_FREE && if (obj_id != SPIFFS_OBJ_ID_DELETED && obj_id != SPIFFS_OBJ_ID_FREE &&
((obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0)) { ((obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0)) {
SPIFFS_GC_DBG("gc_clean: FIND_DATA state:%d - found obj id %04x\n", gc.state, obj_id); SPIFFS_GC_DBG("gc_clean: FIND_DATA state:%i - found obj id %04x\n", gc.state, obj_id);
gc.obj_id_found = 1; gc.obj_id_found = 1;
gc.cur_obj_id = obj_id; gc.cur_obj_id = obj_id;
scan = 0; scan = 0;
@ -550,9 +564,10 @@ s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
cur_entry = 0; cur_entry = 0;
break; break;
} }
SPIFFS_GC_DBG("gc_clean: state-> %d\n", gc.state); SPIFFS_GC_DBG("gc_clean: state-> %i\n", gc.state);
} // while state != FINISHED } // while state != FINISHED
return res; return res;
} }

View File

@ -8,7 +8,9 @@
#include "spiffs.h" #include "spiffs.h"
#include "spiffs_nucleus.h" #include "spiffs_nucleus.h"
#if SPIFFS_CACHE == 1
static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh); static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh);
#endif
#if SPIFFS_BUFFER_HELP #if SPIFFS_BUFFER_HELP
u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs) { u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs) {
@ -56,12 +58,12 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
void *cache, u32_t cache_size, void *cache, u32_t cache_size,
spiffs_check_callback check_cb_f) { spiffs_check_callback check_cb_f) {
SPIFFS_LOCK(fs); SPIFFS_LOCK(fs);
c_memset(fs, 0, sizeof(spiffs)); memset(fs, 0, sizeof(spiffs));
c_memcpy(&fs->cfg, config, sizeof(spiffs_config)); memcpy(&fs->cfg, config, sizeof(spiffs_config));
fs->block_count = SPIFFS_CFG_PHYS_SZ(fs) / SPIFFS_CFG_LOG_BLOCK_SZ(fs); fs->block_count = SPIFFS_CFG_PHYS_SZ(fs) / SPIFFS_CFG_LOG_BLOCK_SZ(fs);
fs->work = &work[0]; fs->work = &work[0];
fs->lu_work = &work[SPIFFS_CFG_LOG_PAGE_SZ(fs)]; fs->lu_work = &work[SPIFFS_CFG_LOG_PAGE_SZ(fs)];
c_memset(fd_space, 0, fd_space_size); memset(fd_space, 0, fd_space_size);
// align fd_space pointer to pointer size byte boundary, below is safe // align fd_space pointer to pointer size byte boundary, below is safe
u8_t ptr_size = sizeof(void*); u8_t ptr_size = sizeof(void*);
#pragma GCC diagnostic push #pragma GCC diagnostic push
@ -89,9 +91,10 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
if (cache_size & (ptr_size-1)) { if (cache_size & (ptr_size-1)) {
cache_size -= (cache_size & (ptr_size-1)); cache_size -= (cache_size & (ptr_size-1));
} }
#if SPIFFS_CACHE #if SPIFFS_CACHE
fs->cache = cache; fs->cache = cache;
fs->cache_size = cache_size; fs->cache_size = (cache_size > (SPIFFS_CFG_LOG_PAGE_SZ(fs)*32)) ? SPIFFS_CFG_LOG_PAGE_SZ(fs)*32 : cache_size;
spiffs_cache_init(fs); spiffs_cache_init(fs);
#endif #endif
@ -107,14 +110,14 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
res = spiffs_obj_lu_scan(fs); res = spiffs_obj_lu_scan(fs);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
SPIFFS_DBG("page index byte len: %d\n", SPIFFS_CFG_LOG_PAGE_SZ(fs)); SPIFFS_DBG("page index byte len: %i\n", SPIFFS_CFG_LOG_PAGE_SZ(fs));
SPIFFS_DBG("object lookup pages: %d\n", SPIFFS_OBJ_LOOKUP_PAGES(fs)); SPIFFS_DBG("object lookup pages: %i\n", SPIFFS_OBJ_LOOKUP_PAGES(fs));
SPIFFS_DBG("page pages per block: %d\n", SPIFFS_PAGES_PER_BLOCK(fs)); SPIFFS_DBG("page pages per block: %i\n", SPIFFS_PAGES_PER_BLOCK(fs));
SPIFFS_DBG("page header length: %d\n", sizeof(spiffs_page_header)); SPIFFS_DBG("page header length: %i\n", sizeof(spiffs_page_header));
SPIFFS_DBG("object header index entries: %d\n", SPIFFS_OBJ_HDR_IX_LEN(fs)); SPIFFS_DBG("object header index entries: %i\n", SPIFFS_OBJ_HDR_IX_LEN(fs));
SPIFFS_DBG("object index entries: %d\n", SPIFFS_OBJ_IX_LEN(fs)); SPIFFS_DBG("object index entries: %i\n", SPIFFS_OBJ_IX_LEN(fs));
SPIFFS_DBG("available file descriptors: %d\n", fs->fd_count); SPIFFS_DBG("available file descriptors: %i\n", fs->fd_count);
SPIFFS_DBG("free blocks: %d\n", fs->free_blocks); SPIFFS_DBG("free blocks: %i\n", fs->free_blocks);
fs->check_cb_f = check_cb_f; fs->check_cb_f = check_cb_f;
@ -188,6 +191,14 @@ spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
} }
if (res == SPIFFS_OK &&
(flags & (SPIFFS_CREAT | SPIFFS_EXCL)) == (SPIFFS_CREAT | SPIFFS_EXCL)) {
// creat and excl and file exists - fail
res = SPIFFS_ERR_FILE_EXISTS;
spiffs_fd_return(fs, fd->file_nbr);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
}
if ((flags & SPIFFS_CREAT) && res == SPIFFS_ERR_NOT_FOUND) { if ((flags & SPIFFS_CREAT) && res == SPIFFS_ERR_NOT_FOUND) {
spiffs_obj_id obj_id; spiffs_obj_id obj_id;
// no need to enter conflicting name here, already looked for it above // no need to enter conflicting name here, already looked for it above
@ -377,7 +388,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
offset + len > fd->cache_page->offset + SPIFFS_CFG_LOG_PAGE_SZ(fs)) // writing beyond cache page offset + len > fd->cache_page->offset + SPIFFS_CFG_LOG_PAGE_SZ(fs)) // writing beyond cache page
{ {
// boundary violation, write back cache first and allocate new // boundary violation, write back cache first and allocate new
SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page %d for fd %d:%04x, boundary viol, offs:%d size:%d\n", 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); fd->cache_page->ix, fd->file_nbr, fd->obj_id, fd->cache_page->offset, fd->cache_page->size);
res = spiffs_hydro_write(fs, fd, res = spiffs_hydro_write(fs, fd,
spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix), spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
@ -395,19 +406,19 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
if (fd->cache_page) { if (fd->cache_page) {
fd->cache_page->offset = offset; fd->cache_page->offset = offset;
fd->cache_page->size = 0; fd->cache_page->size = 0;
SPIFFS_CACHE_DBG("CACHE_WR_ALLO: allocating cache page %d for fd %d:%04x\n", SPIFFS_CACHE_DBG("CACHE_WR_ALLO: allocating cache page %i for fd %i:%04x\n",
fd->cache_page->ix, fd->file_nbr, fd->obj_id); fd->cache_page->ix, fd->file_nbr, fd->obj_id);
} }
} }
if (fd->cache_page) { if (fd->cache_page) {
u32_t offset_in_cpage = offset - fd->cache_page->offset; u32_t offset_in_cpage = offset - fd->cache_page->offset;
SPIFFS_CACHE_DBG("CACHE_WR_WRITE: storing to cache page %d for fd %d:%04x, offs %d:%d len %d\n", 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, fd->cache_page->ix, fd->file_nbr, fd->obj_id,
offset, offset_in_cpage, len); offset, offset_in_cpage, len);
spiffs_cache *cache = spiffs_get_cache(fs); spiffs_cache *cache = spiffs_get_cache(fs);
u8_t *cpage_data = spiffs_get_cache_page(fs, cache, fd->cache_page->ix); u8_t *cpage_data = spiffs_get_cache_page(fs, cache, fd->cache_page->ix);
c_memcpy(&cpage_data[offset_in_cpage], buf, len); memcpy(&cpage_data[offset_in_cpage], buf, len);
fd->cache_page->size = MAX(fd->cache_page->size, offset_in_cpage + len); fd->cache_page->size = MAX(fd->cache_page->size, offset_in_cpage + len);
fd->fdoffset += len; fd->fdoffset += len;
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
@ -423,7 +434,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, s32_t len) {
// big write, no need to cache it - but first check if there is a cached write already // big write, no need to cache it - but first check if there is a cached write already
if (fd->cache_page) { if (fd->cache_page) {
// write back cache first // write back cache first
SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page %d for fd %d:%04x, big write, offs:%d size:%d\n", 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); fd->cache_page->ix, fd->file_nbr, fd->obj_id, fd->cache_page->offset, fd->cache_page->size);
res = spiffs_hydro_write(fs, fd, res = spiffs_hydro_write(fs, fd,
spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix), spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
@ -488,7 +499,7 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return 0; return offs;
} }
s32_t SPIFFS_remove(spiffs *fs, char *path) { s32_t SPIFFS_remove(spiffs *fs, char *path) {
@ -554,6 +565,7 @@ s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh) {
} }
static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file fh, spiffs_stat *s) { static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file fh, spiffs_stat *s) {
(void)fh;
spiffs_page_object_ix_header objix_hdr; spiffs_page_object_ix_header objix_hdr;
spiffs_obj_id obj_id; spiffs_obj_id obj_id;
s32_t res =_spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ, fh, s32_t res =_spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ, fh,
@ -616,7 +628,10 @@ s32_t SPIFFS_fstat(spiffs *fs, spiffs_file fh, spiffs_stat *s) {
// Checks if there are any cached writes for the object id associated with // Checks if there are any cached writes for the object id associated with
// given filehandle. If so, these writes are flushed. // given filehandle. If so, these writes are flushed.
#if SPIFFS_CACHE == 1
static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) { static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) {
(void)fs;
(void)fh;
s32_t res = SPIFFS_OK; s32_t res = SPIFFS_OK;
#if SPIFFS_CACHE_WR #if SPIFFS_CACHE_WR
@ -630,7 +645,7 @@ static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) {
fd->cache_page = spiffs_cache_page_get_by_fd(fs, fd); fd->cache_page = spiffs_cache_page_get_by_fd(fs, fd);
} }
if (fd->cache_page) { if (fd->cache_page) {
SPIFFS_CACHE_DBG("CACHE_WR_DUMP: dumping cache page %d for fd %d:%04x, flush, offs:%d size:%d\n", 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); fd->cache_page->ix, fd->file_nbr, fd->obj_id, fd->cache_page->offset, fd->cache_page->size);
res = spiffs_hydro_write(fs, fd, res = spiffs_hydro_write(fs, fd,
spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix), spiffs_get_cache_page(fs, spiffs_get_cache(fs), fd->cache_page->ix),
@ -645,8 +660,10 @@ static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh) {
return res; return res;
} }
#endif
s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) { s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) {
(void)fh;
SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_API_CHECK_MOUNT(fs);
s32_t res = SPIFFS_OK; s32_t res = SPIFFS_OK;
@ -660,24 +677,23 @@ s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh) {
return res; return res;
} }
void SPIFFS_close(spiffs *fs, spiffs_file fh) { s32_t SPIFFS_close(spiffs *fs, spiffs_file fh) {
if (!SPIFFS_CHECK_CFG((fs))) { SPIFFS_API_CHECK_CFG(fs);
(fs)->err_code = SPIFFS_ERR_NOT_CONFIGURED; SPIFFS_API_CHECK_MOUNT(fs);
return;
}
if (!SPIFFS_CHECK_MOUNT(fs)) { s32_t res = SPIFFS_OK;
fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
return;
}
SPIFFS_LOCK(fs); SPIFFS_LOCK(fs);
#if SPIFFS_CACHE #if SPIFFS_CACHE
spiffs_fflush_cache(fs, fh); res = spiffs_fflush_cache(fs, fh);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
#endif #endif
spiffs_fd_return(fs, fh); res = spiffs_fd_return(fs, fh);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return res;
} }
s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) { s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) {
@ -711,9 +727,8 @@ s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) {
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, fd->objix_hdr_pix, 0, (u8_t*)new, res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, fd->objix_hdr_pix, 0, (u8_t*)new,
0, &pix_dummy); 0, &pix_dummy);
if (res != SPIFFS_OK) { spiffs_fd_return(fs, fd->file_nbr);
spiffs_fd_return(fs, fd->file_nbr);
}
SPIFFS_API_CHECK_RES_UNLOCK(fs, res); SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
@ -780,7 +795,7 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) {
d->fs->err_code = SPIFFS_ERR_NOT_MOUNTED; d->fs->err_code = SPIFFS_ERR_NOT_MOUNTED;
return 0; return 0;
} }
SPIFFS_LOCK(fs); SPIFFS_LOCK(d->fs);
spiffs_block_ix bix; spiffs_block_ix bix;
int entry; int entry;
@ -804,7 +819,7 @@ struct spiffs_dirent *SPIFFS_readdir(spiffs_DIR *d, struct spiffs_dirent *e) {
} else { } else {
d->fs->err_code = res; d->fs->err_code = res;
} }
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(d->fs);
return ret; return ret;
} }
@ -856,46 +871,34 @@ s32_t SPIFFS_info(spiffs *fs, u32_t *total, u32_t *used) {
return res; return res;
} }
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh) { s32_t SPIFFS_gc_quick(spiffs *fs, u16_t max_free_pages) {
s32_t res;
SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_API_CHECK_MOUNT(fs);
SPIFFS_LOCK(fs); SPIFFS_LOCK(fs);
spiffs_fd *fd; res = spiffs_gc_quick(fs, max_free_pages);
s32_t res;
res = spiffs_fd_get(fs, fh, &fd);
SPIFFS_API_CHECK_RES(fs, res);
#if SPIFFS_CACHE_WR
spiffs_fflush_cache(fs, fh);
#endif
res = (fd->fdoffset == fd->size);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return res; return 0;
} }
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) {
s32_t SPIFFS_gc(spiffs *fs, u32_t size) {
s32_t res;
SPIFFS_API_CHECK_CFG(fs); SPIFFS_API_CHECK_CFG(fs);
SPIFFS_API_CHECK_MOUNT(fs); SPIFFS_API_CHECK_MOUNT(fs);
SPIFFS_LOCK(fs); SPIFFS_LOCK(fs);
spiffs_fd *fd; res = spiffs_gc_check(fs, size);
s32_t res;
res = spiffs_fd_get(fs, fh, &fd);
SPIFFS_API_CHECK_RES(fs, res);
#if SPIFFS_CACHE_WR
spiffs_fflush_cache(fs, fh);
#endif
res = fd->fdoffset;
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return res; return 0;
} }
#if SPIFFS_TEST_VISUALISATION #if SPIFFS_TEST_VISUALISATION
s32_t SPIFFS_vis(spiffs *fs) { s32_t SPIFFS_vis(spiffs *fs) {
s32_t res = SPIFFS_OK; s32_t res = SPIFFS_OK;
@ -949,7 +952,7 @@ s32_t SPIFFS_vis(spiffs *fs) {
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
if (erase_count != (spiffs_obj_id)-1) { if (erase_count != (spiffs_obj_id)-1) {
spiffs_printf("\tera_cnt: %d\n", erase_count); spiffs_printf("\tera_cnt: %i\n", erase_count);
} else { } else {
spiffs_printf("\tera_cnt: N/A\n"); spiffs_printf("\tera_cnt: N/A\n");
} }
@ -957,15 +960,15 @@ s32_t SPIFFS_vis(spiffs *fs) {
bix++; bix++;
} // per block } // per block
spiffs_printf("era_cnt_max: %d\n", fs->max_erase_count); spiffs_printf("era_cnt_max: %i\n", fs->max_erase_count);
spiffs_printf("last_errno: %d\n", fs->err_code); spiffs_printf("last_errno: %i\n", fs->err_code);
spiffs_printf("blocks: %d\n", fs->block_count); spiffs_printf("blocks: %i\n", fs->block_count);
spiffs_printf("free_blocks: %d\n", fs->free_blocks); spiffs_printf("free_blocks: %i\n", fs->free_blocks);
spiffs_printf("page_alloc: %d\n", fs->stats_p_allocated); spiffs_printf("page_alloc: %i\n", fs->stats_p_allocated);
spiffs_printf("page_delet: %d\n", fs->stats_p_deleted); spiffs_printf("page_delet: %i\n", fs->stats_p_deleted);
u32_t total, used; u32_t total, used;
SPIFFS_info(fs, &total, &used); SPIFFS_info(fs, &total, &used);
spiffs_printf("used: %d of %d\n", used, total); spiffs_printf("used: %i of %i\n", used, total);
SPIFFS_UNLOCK(fs); SPIFFS_UNLOCK(fs);
return res; return res;

View File

@ -64,7 +64,7 @@ s32_t spiffs_phys_rd(
u32_t addr, u32_t addr,
u32_t len, u32_t len,
u8_t *dst) { u8_t *dst) {
return fs->cfg.hal_read_f(addr, len, dst); return SPIFFS_HAL_READ(fs, addr, len, dst);
} }
s32_t spiffs_phys_wr( s32_t spiffs_phys_wr(
@ -72,7 +72,7 @@ s32_t spiffs_phys_wr(
u32_t addr, u32_t addr,
u32_t len, u32_t len,
u8_t *src) { u8_t *src) {
return fs->cfg.hal_write_f(addr, len, src); return SPIFFS_HAL_WRITE(fs, addr, len, src);
} }
#endif #endif
@ -83,6 +83,7 @@ s32_t spiffs_phys_cpy(
u32_t dst, u32_t dst,
u32_t src, u32_t src,
u32_t len) { u32_t len) {
(void)fh;
s32_t res; s32_t res;
u8_t b[SPIFFS_COPY_BUFFER_STACK]; u8_t b[SPIFFS_COPY_BUFFER_STACK];
while (len > 0) { while (len > 0) {
@ -227,7 +228,8 @@ s32_t spiffs_erase_block(
// here we ignore res, just try erasing the block // here we ignore res, just try erasing the block
while (size > 0) { while (size > 0) {
SPIFFS_DBG("erase %08x:%08x\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs)); SPIFFS_DBG("erase %08x:%08x\n", addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
(void)fs->cfg.hal_erase_f(addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs)); SPIFFS_HAL_ERASE(fs, addr, SPIFFS_CFG_PHYS_ERASE_SZ(fs));
addr += SPIFFS_CFG_PHYS_ERASE_SZ(fs); addr += SPIFFS_CFG_PHYS_ERASE_SZ(fs);
size -= SPIFFS_CFG_PHYS_ERASE_SZ(fs); size -= SPIFFS_CFG_PHYS_ERASE_SZ(fs);
} }
@ -347,7 +349,7 @@ s32_t spiffs_obj_lu_scan(
#if SPIFFS_USE_MAGIC #if SPIFFS_USE_MAGIC
if (unerased_bix != (spiffs_block_ix)-1) { if (unerased_bix != (spiffs_block_ix)-1) {
// found one unerased block, remedy // found one unerased block, remedy
SPIFFS_DBG("mount: erase block %d\n", bix); SPIFFS_DBG("mount: erase block %i\n", bix);
res = spiffs_erase_block(fs, unerased_bix); res = spiffs_erase_block(fs, unerased_bix);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
} }
@ -389,7 +391,10 @@ s32_t spiffs_obj_lu_find_free(
int *lu_entry) { int *lu_entry) {
s32_t res; s32_t res;
if (!fs->cleaning && fs->free_blocks < 2) { if (!fs->cleaning && fs->free_blocks < 2) {
res = spiffs_gc_quick(fs); res = spiffs_gc_quick(fs, 0);
if (res == SPIFFS_ERR_NO_DELETED_BLOCKS) {
res = SPIFFS_OK;
}
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
if (fs->free_blocks < 2) { if (fs->free_blocks < 2) {
return SPIFFS_ERR_FULL; return SPIFFS_ERR_FULL;
@ -701,7 +706,7 @@ s32_t spiffs_object_create(
// find free entry // find free entry
res = spiffs_obj_lu_find_free(fs, fs->free_cursor_block_ix, fs->free_cursor_obj_lu_entry, &bix, &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_CHECK_RES(res);
SPIFFS_DBG("create: found free page @ %04x bix:%d entry:%d\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 // occupy page in object lookup
res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT, res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_UPDT,
@ -806,7 +811,7 @@ void spiffs_cb_object_event(
if (cur_fd->file_nbr == 0 || (cur_fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) != obj_id) continue; if (cur_fd->file_nbr == 0 || (cur_fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG) != obj_id) continue;
if (spix == 0) { if (spix == 0) {
if (ev == SPIFFS_EV_IX_NEW || ev == SPIFFS_EV_IX_UPD) { if (ev == SPIFFS_EV_IX_NEW || ev == SPIFFS_EV_IX_UPD) {
SPIFFS_DBG(" callback: setting fd %d:%04x objix_hdr_pix to %04x, size:%d\n", cur_fd->file_nbr, cur_fd->obj_id, new_pix, new_size); SPIFFS_DBG(" callback: setting fd %i:%04x objix_hdr_pix to %04x, size:%i\n", cur_fd->file_nbr, cur_fd->obj_id, new_pix, new_size);
cur_fd->objix_hdr_pix = new_pix; cur_fd->objix_hdr_pix = new_pix;
if (new_size != 0) { if (new_size != 0) {
cur_fd->size = new_size; cur_fd->size = new_size;
@ -818,7 +823,7 @@ void spiffs_cb_object_event(
} }
if (cur_fd->cursor_objix_spix == spix) { if (cur_fd->cursor_objix_spix == spix) {
if (ev == SPIFFS_EV_IX_NEW || ev == SPIFFS_EV_IX_UPD) { if (ev == SPIFFS_EV_IX_NEW || ev == SPIFFS_EV_IX_UPD) {
SPIFFS_DBG(" callback: setting fd %d:%04x span:%04x objix_pix to %04x\n", cur_fd->file_nbr, cur_fd->obj_id, spix, new_pix); SPIFFS_DBG(" callback: setting fd %i:%04x span:%04x objix_pix to %04x\n", cur_fd->file_nbr, cur_fd->obj_id, spix, new_pix);
cur_fd->cursor_objix_pix = new_pix; cur_fd->cursor_objix_pix = new_pix;
} else { } else {
cur_fd->cursor_objix_pix = 0; cur_fd->cursor_objix_pix = 0;
@ -878,7 +883,7 @@ s32_t spiffs_object_open_by_page(
SPIFFS_VALIDATE_OBJIX(oix_hdr.p_hdr, fd->obj_id, 0); SPIFFS_VALIDATE_OBJIX(oix_hdr.p_hdr, fd->obj_id, 0);
SPIFFS_DBG("open: fd %d is obj id %04x\n", fd->file_nbr, fd->obj_id); SPIFFS_DBG("open: fd %i is obj id %04x\n", fd->file_nbr, fd->obj_id);
return res; return res;
} }
@ -890,7 +895,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
s32_t res = SPIFFS_OK; s32_t res = SPIFFS_OK;
u32_t written = 0; u32_t written = 0;
SPIFFS_DBG("append: %d bytes @ offs %d of size %d\n", len, offset, fd->size); SPIFFS_DBG("append: %i bytes @ offs %i of size %i\n", len, offset, fd->size);
if (offset > fd->size) { if (offset > fd->size) {
SPIFFS_DBG("append: offset reversed to size\n"); SPIFFS_DBG("append: offset reversed to size\n");
@ -899,7 +904,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
res = spiffs_gc_check(fs, len + SPIFFS_DATA_PAGE_SIZE(fs)); // add an extra page of data worth for meta res = spiffs_gc_check(fs, len + SPIFFS_DATA_PAGE_SIZE(fs)); // add an extra page of data worth for meta
if (res != SPIFFS_OK) { if (res != SPIFFS_OK) {
SPIFFS_DBG("append: gc check fail %d\n", res); SPIFFS_DBG("append: gc check fail %i\n", res);
} }
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
@ -927,7 +932,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
// within this clause we return directly if something fails, object index mess-up // within this clause we return directly if something fails, object index mess-up
if (written > 0) { if (written > 0) {
// store previous object index page, unless first pass // store previous object index page, unless first pass
SPIFFS_DBG("append: %04x store objix %04x:%04x, written %d\n", fd->obj_id, SPIFFS_DBG("append: %04x store objix %04x:%04x, written %i\n", fd->obj_id,
cur_objix_pix, prev_objix_spix, written); cur_objix_pix, prev_objix_spix, written);
if (prev_objix_spix == 0) { if (prev_objix_spix == 0) {
// this is an update to object index header page // this is an update to object index header page
@ -944,7 +949,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
fd->objix_hdr_pix, fs->work, 0, offset+written, &new_objix_hdr_page); fd->objix_hdr_pix, fs->work, 0, offset+written, &new_objix_hdr_page);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
SPIFFS_DBG("append: %04x store new objix_hdr, %04x:%04x, written %d\n", fd->obj_id, SPIFFS_DBG("append: %04x store new objix_hdr, %04x:%04x, written %i\n", fd->obj_id,
new_objix_hdr_page, 0, written); new_objix_hdr_page, 0, written);
} }
} else { } else {
@ -960,7 +965,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
fd->objix_hdr_pix, 0, 0, offset+written, &new_objix_hdr_page); fd->objix_hdr_pix, 0, 0, offset+written, &new_objix_hdr_page);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
SPIFFS_DBG("append: %04x store new size I %d in objix_hdr, %04x:%04x, written %d\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); offset+written, new_objix_hdr_page, 0, written);
} }
fd->size = offset+written; fd->size = offset+written;
@ -987,9 +992,9 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_NEW, fd->obj_id, cur_objix_spix, cur_objix_pix, 0); 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 // quick "load" of new object index page
c_memset(fs->work, 0xff, SPIFFS_CFG_LOG_PAGE_SZ(fs)); memset(fs->work, 0xff, SPIFFS_CFG_LOG_PAGE_SZ(fs));
c_memcpy(fs->work, &p_hdr, sizeof(spiffs_page_header)); memcpy(fs->work, &p_hdr, sizeof(spiffs_page_header));
SPIFFS_DBG("append: %04x create objix page, %04x:%04x, written %d\n", fd->obj_id SPIFFS_DBG("append: %04x create objix page, %04x:%04x, written %i\n", fd->obj_id
, cur_objix_pix, cur_objix_spix, written); , cur_objix_pix, cur_objix_spix, written);
} else { } else {
// on first pass, we load existing object index page // on first pass, we load existing object index page
@ -1001,7 +1006,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
res = spiffs_obj_lu_find_id_and_span(fs, fd->obj_id | SPIFFS_OBJ_ID_IX_FLAG, cur_objix_spix, 0, &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_CHECK_RES(res);
} }
SPIFFS_DBG("append: %04x found object index at page %04x [fd size %d]\n", fd->obj_id, pix, fd->size); SPIFFS_DBG("append: %04x found object index at page %04x [fd size %i]\n", fd->obj_id, pix, fd->size);
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ, res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_IX | SPIFFS_OP_C_READ,
fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work); fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, pix), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->work);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
@ -1025,7 +1030,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
p_hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL); // finalize immediately p_hdr.flags = 0xff & ~(SPIFFS_PH_FLAG_FINAL); // finalize immediately
res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG,
&p_hdr, &data[written], to_write, page_offs, 1, &data_page); &p_hdr, &data[written], to_write, page_offs, 1, &data_page);
SPIFFS_DBG("append: %04x store new data page, %04x:%04x offset:%d, len %d, written %d\n", fd->obj_id, 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_write, written); data_page, data_spix, page_offs, to_write, written);
} else { } else {
// append to existing page, fill out free data in existing page // append to existing page, fill out free data in existing page
@ -1042,7 +1047,7 @@ 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_DA | SPIFFS_OP_C_UPDT, res = _spiffs_wr(fs, SPIFFS_OP_T_OBJ_DA | SPIFFS_OP_C_UPDT,
fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, data_page) + sizeof(spiffs_page_header) + page_offs, to_write, &data[written]); fd->file_nbr, SPIFFS_PAGE_TO_PADDR(fs, data_page) + sizeof(spiffs_page_header) + page_offs, to_write, &data[written]);
SPIFFS_DBG("append: %04x store to existing data page, %04x:%04x offset:%d, len %d, written %d\n", fd->obj_id SPIFFS_DBG("append: %04x store to existing data page, %04x:%04x offset:%i, len %i, written %i\n", fd->obj_id
, data_page, data_spix, page_offs, to_write, written); , data_page, data_spix, page_offs, to_write, written);
} }
@ -1078,7 +1083,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
if (cur_objix_spix != 0) { if (cur_objix_spix != 0) {
// wrote beyond object index header page // wrote beyond object index header page
// write last modified object index page, unless object header index page // write last modified object index page, unless object header index page
SPIFFS_DBG("append: %04x store objix page, %04x:%04x, written %d\n", fd->obj_id, SPIFFS_DBG("append: %04x store objix page, %04x:%04x, written %i\n", fd->obj_id,
cur_objix_pix, cur_objix_spix, written); cur_objix_pix, cur_objix_spix, written);
res2 = spiffs_page_index_check(fs, fd, cur_objix_pix, cur_objix_spix); res2 = spiffs_page_index_check(fs, fd, cur_objix_pix, cur_objix_spix);
@ -1092,7 +1097,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
// update size in object header index page // update size in object header index page
res2 = spiffs_object_update_index_hdr(fs, fd, 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); fd->objix_hdr_pix, 0, 0, offset+written, &new_objix_hdr_page);
SPIFFS_DBG("append: %04x store new size II %d in objix_hdr, %04x:%04x, written %d, res %d\n", fd->obj_id SPIFFS_DBG("append: %04x store new size II %i in objix_hdr, %04x:%04x, written %i, res %i\n", fd->obj_id
, offset+written, new_objix_hdr_page, 0, written, res2); , offset+written, new_objix_hdr_page, 0, written, res2);
SPIFFS_CHECK_RES(res2); SPIFFS_CHECK_RES(res2);
} else { } else {
@ -1100,7 +1105,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
if (offset == 0) { if (offset == 0) {
// wrote to empty object - simply update size and write whole page // wrote to empty object - simply update size and write whole page
objix_hdr->size = offset+written; objix_hdr->size = offset+written;
SPIFFS_DBG("append: %04x store fresh objix_hdr page, %04x:%04x, written %d\n", fd->obj_id SPIFFS_DBG("append: %04x store fresh objix_hdr page, %04x:%04x, written %i\n", fd->obj_id
, cur_objix_pix, cur_objix_spix, written); , cur_objix_pix, cur_objix_spix, written);
res2 = spiffs_page_index_check(fs, fd, cur_objix_pix, cur_objix_spix); res2 = spiffs_page_index_check(fs, fd, cur_objix_pix, cur_objix_spix);
@ -1115,7 +1120,7 @@ s32_t spiffs_object_append(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
// modifying object index header page, update size and make new copy // modifying object index header page, update size and make new copy
res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
fd->objix_hdr_pix, fs->work, 0, offset+written, &new_objix_hdr_page); 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 %d\n", fd->obj_id SPIFFS_DBG("append: %04x store modified objix_hdr page, %04x:%04x, written %i\n", fd->obj_id
, new_objix_hdr_page, 0, written); , new_objix_hdr_page, 0, written);
SPIFFS_CHECK_RES(res2); SPIFFS_CHECK_RES(res2);
} }
@ -1163,7 +1168,7 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
// store previous object index header page // store previous object index header page
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
fd->objix_hdr_pix, fs->work, 0, 0, &new_objix_hdr_pix); fd->objix_hdr_pix, fs->work, 0, 0, &new_objix_hdr_pix);
SPIFFS_DBG("modify: store modified objix_hdr page, %04x:%04x, written %d\n", new_objix_hdr_pix, 0, written); SPIFFS_DBG("modify: store modified objix_hdr page, %04x:%04x, written %i\n", new_objix_hdr_pix, 0, written);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
} else { } else {
// store new version of previous object index page // store new version of previous object index page
@ -1173,7 +1178,7 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
res = spiffs_page_move(fs, fd->file_nbr, (u8_t*)objix, fd->obj_id, 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 %d\n", new_objix_pix, objix->p_hdr.span_ix, written); 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_CHECK_RES(res);
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_UPD, fd->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);
} }
@ -1228,7 +1233,7 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
// a full page, allocate and write a new page of data // a full page, allocate and write a new page of data
res = spiffs_page_allocate_data(fs, fd->obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, 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); &p_hdr, &data[written], to_write, page_offs, 1, &data_pix);
SPIFFS_DBG("modify: store new data page, %04x:%04x offset:%d, len %d, written %d\n", data_pix, data_spix, page_offs, to_write, written); 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 { } else {
// write to existing page, allocate new and copy unmodified data // write to existing page, allocate new and copy unmodified data
@ -1269,7 +1274,7 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
(u8_t *)&p_hdr.flags); (u8_t *)&p_hdr.flags);
if (res != SPIFFS_OK) break; if (res != SPIFFS_OK) break;
SPIFFS_DBG("modify: store to existing data page, src:%04x, dst:%04x:%04x offset:%d, len %d, written %d\n", orig_data_pix, data_pix, data_spix, page_offs, to_write, written); SPIFFS_DBG("modify: store to existing data page, src:%04x, dst:%04x:%04x offset:%i, len %i, written %i\n", orig_data_pix, data_pix, data_spix, page_offs, to_write, written);
} }
// delete original data page // delete original data page
@ -1308,7 +1313,7 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
SPIFFS_CHECK_RES(res2); SPIFFS_CHECK_RES(res2);
res2 = spiffs_page_move(fs, fd->file_nbr, (u8_t*)objix, fd->obj_id, 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 %d\n", new_objix_pix, cur_objix_spix, written); 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_pix = new_objix_pix;
fd->cursor_objix_spix = cur_objix_spix; fd->cursor_objix_spix = cur_objix_spix;
SPIFFS_CHECK_RES(res2); SPIFFS_CHECK_RES(res2);
@ -1318,7 +1323,7 @@ s32_t spiffs_object_modify(spiffs_fd *fd, u32_t offset, u8_t *data, u32_t len) {
// wrote within object index header page // wrote within object index header page
res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, res2 = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
fd->objix_hdr_pix, fs->work, 0, 0, &new_objix_hdr_pix); fd->objix_hdr_pix, fs->work, 0, 0, &new_objix_hdr_pix);
SPIFFS_DBG("modify: store modified objix_hdr page, %04x:%04x, written %d\n", new_objix_hdr_pix, 0, written); SPIFFS_DBG("modify: store modified objix_hdr page, %04x:%04x, written %i\n", new_objix_hdr_pix, 0, written);
SPIFFS_CHECK_RES(res2); SPIFFS_CHECK_RES(res2);
} }
@ -1438,7 +1443,7 @@ s32_t spiffs_object_truncate(
spiffs_cb_object_event(fs, fd, SPIFFS_EV_IX_DEL, fd->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) { if (prev_objix_spix > 0) {
// update object index header page // update object index header page
SPIFFS_DBG("truncate: update objix hdr page %04x:%04x to size %d\n", fd->objix_hdr_pix, prev_objix_spix, cur_size); 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->obj_id, res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
fd->objix_hdr_pix, 0, 0, cur_size, &new_objix_hdr_pix); fd->objix_hdr_pix, 0, 0, cur_size, &new_objix_hdr_pix);
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);
@ -1481,14 +1486,14 @@ s32_t spiffs_object_truncate(
// delete full data page // delete full data page
res = spiffs_page_data_check(fs, fd, data_pix, data_spix); res = spiffs_page_data_check(fs, fd, data_pix, data_spix);
if (res != SPIFFS_ERR_DELETED && res != SPIFFS_OK && res != SPIFFS_ERR_INDEX_REF_FREE) { if (res != SPIFFS_ERR_DELETED && res != SPIFFS_OK && res != SPIFFS_ERR_INDEX_REF_FREE) {
SPIFFS_DBG("truncate: err validating data pix %d\n", res); SPIFFS_DBG("truncate: err validating data pix %i\n", res);
break; break;
} }
if (res == SPIFFS_OK) { if (res == SPIFFS_OK) {
res = spiffs_page_delete(fs, data_pix); res = spiffs_page_delete(fs, data_pix);
if (res != SPIFFS_OK) { if (res != SPIFFS_OK) {
SPIFFS_DBG("truncate: err deleting data pix %d\n", res); SPIFFS_DBG("truncate: err deleting data pix %i\n", res);
break; break;
} }
} else if (res == SPIFFS_ERR_DELETED || res == SPIFFS_ERR_INDEX_REF_FREE) { } else if (res == SPIFFS_ERR_DELETED || res == SPIFFS_ERR_INDEX_REF_FREE) {
@ -1503,13 +1508,13 @@ s32_t spiffs_object_truncate(
} }
fd->size = cur_size; fd->size = cur_size;
fd->offset = cur_size; fd->offset = cur_size;
SPIFFS_DBG("truncate: delete data page %04x for data spix:%04x, cur_size:%d\n", data_pix, data_spix, cur_size); SPIFFS_DBG("truncate: delete data page %04x for data spix:%04x, cur_size:%i\n", data_pix, data_spix, cur_size);
} else { } else {
// delete last page, partially // delete last page, partially
spiffs_page_header p_hdr; spiffs_page_header p_hdr;
spiffs_page_ix new_data_pix; spiffs_page_ix new_data_pix;
u32_t bytes_to_remove = SPIFFS_DATA_PAGE_SIZE(fs) - (new_size % SPIFFS_DATA_PAGE_SIZE(fs)); u32_t bytes_to_remove = SPIFFS_DATA_PAGE_SIZE(fs) - (new_size % SPIFFS_DATA_PAGE_SIZE(fs));
SPIFFS_DBG("truncate: delete %d bytes from data page %04x for data spix:%04x, cur_size:%d\n", bytes_to_remove, data_pix, data_spix, cur_size); SPIFFS_DBG("truncate: delete %i bytes from data page %04x for data spix:%04x, cur_size:%i\n", bytes_to_remove, data_pix, data_spix, cur_size);
res = spiffs_page_data_check(fs, fd, data_pix, data_spix); res = spiffs_page_data_check(fs, fd, data_pix, data_spix);
if (res != SPIFFS_OK) break; if (res != SPIFFS_OK) break;
@ -1572,7 +1577,7 @@ s32_t spiffs_object_truncate(
} else { } else {
// make uninitialized object // make uninitialized object
SPIFFS_DBG("truncate: reset objix_hdr page %04x\n", objix_pix); SPIFFS_DBG("truncate: reset objix_hdr page %04x\n", objix_pix);
c_memset(fs->work + sizeof(spiffs_page_object_ix_header), 0xff, memset(fs->work + sizeof(spiffs_page_object_ix_header), 0xff,
SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix_header)); SPIFFS_CFG_LOG_PAGE_SZ(fs) - sizeof(spiffs_page_object_ix_header));
res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id,
objix_pix, fs->work, 0, SPIFFS_UNDEFINED_LEN, &new_objix_hdr_pix); objix_pix, fs->work, 0, SPIFFS_UNDEFINED_LEN, &new_objix_hdr_pix);
@ -1664,7 +1669,7 @@ s32_t spiffs_object_read(
len_to_read = MIN(len_to_read, SPIFFS_DATA_PAGE_SIZE(fs) - (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs))); len_to_read = MIN(len_to_read, SPIFFS_DATA_PAGE_SIZE(fs) - (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs)));
// remaining data in file // remaining data in file
len_to_read = MIN(len_to_read, fd->size); len_to_read = MIN(len_to_read, fd->size);
SPIFFS_DBG("read: offset:%d rd:%d data spix:%04x is data_pix:%04x addr:%08x\n", cur_offset, len_to_read, data_spix, data_pix, SPIFFS_DBG("read: offset:%i rd:%i data spix:%04x is data_pix:%04x addr:%08x\n", cur_offset, len_to_read, data_spix, data_pix,
SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header) + (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs))); SPIFFS_PAGE_TO_PADDR(fs, data_pix) + sizeof(spiffs_page_header) + (cur_offset % SPIFFS_DATA_PAGE_SIZE(fs)));
if (len_to_read <= 0) { if (len_to_read <= 0) {
res = SPIFFS_ERR_END_OF_OBJECT; res = SPIFFS_ERR_END_OF_OBJECT;
@ -1750,7 +1755,7 @@ static s32_t spiffs_obj_lu_find_free_obj_id_compact_v(spiffs *fs, spiffs_obj_id
if (id >= state->min_obj_id && id <= state->max_obj_id) { if (id >= state->min_obj_id && id <= state->max_obj_id) {
u8_t *map = (u8_t *)fs->work; u8_t *map = (u8_t *)fs->work;
int ix = (id - state->min_obj_id) / state->compaction; int ix = (id - state->min_obj_id) / state->compaction;
//SPIFFS_DBG("free_obj_id: add ix %d for id %04x min:%04x max%04x comp:%d\n", ix, id, state->min_obj_id, state->max_obj_id, state->compaction); //SPIFFS_DBG("free_obj_id: add ix %i for id %04x min:%04x max%04x comp:%i\n", ix, id, state->min_obj_id, state->max_obj_id, state->compaction);
map[ix]++; map[ix]++;
} }
} }
@ -1780,7 +1785,7 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, u8_t *co
u32_t i, j; u32_t i, j;
SPIFFS_DBG("free_obj_id: BITM min:%04x max:%04x\n", state.min_obj_id, state.max_obj_id); SPIFFS_DBG("free_obj_id: BITM min:%04x max:%04x\n", state.min_obj_id, state.max_obj_id);
c_memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs)); memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_obj_lu_find_free_obj_id_bitmap_v, state.min_obj_id, res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_obj_lu_find_free_obj_id_bitmap_v, state.min_obj_id,
conflicting_name, 0, 0); conflicting_name, 0, 0);
if (res == SPIFFS_VIS_END) res = SPIFFS_OK; if (res == SPIFFS_VIS_END) res = SPIFFS_OK;
@ -1823,7 +1828,7 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, u8_t *co
return SPIFFS_ERR_FULL; return SPIFFS_ERR_FULL;
} }
SPIFFS_DBG("free_obj_id: COMP select index:%d min_count:%d min:%04x max:%04x compact:%d\n", min_i, min_count, state.min_obj_id, state.max_obj_id, state.compaction); SPIFFS_DBG("free_obj_id: COMP select index:%i min_count:%i min:%04x max:%04x compact:%i\n", min_i, min_count, state.min_obj_id, state.max_obj_id, state.compaction);
if (min_count == 0) { if (min_count == 0) {
// no id in this range, skip compacting and use directly // no id in this range, skip compacting and use directly
@ -1843,9 +1848,9 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, u8_t *co
// in a work memory of log_page_size bytes, we may fit in log_page_size ids // in a work memory of log_page_size bytes, we may fit in log_page_size ids
// todo what if compaction is > 255 - then we cannot fit it in a byte // todo what if compaction is > 255 - then we cannot fit it in a byte
state.compaction = (state.max_obj_id-state.min_obj_id) / ((SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(u8_t))); state.compaction = (state.max_obj_id-state.min_obj_id) / ((SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(u8_t)));
SPIFFS_DBG("free_obj_id: COMP min:%04x max:%04x compact:%d\n", state.min_obj_id, state.max_obj_id, state.compaction); SPIFFS_DBG("free_obj_id: COMP min:%04x max:%04x compact:%i\n", state.min_obj_id, state.max_obj_id, state.compaction);
c_memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs)); memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_obj_lu_find_free_obj_id_compact_v, 0, &state, 0, 0); res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_obj_lu_find_free_obj_id_compact_v, 0, &state, 0, 0);
if (res == SPIFFS_VIS_END) res = SPIFFS_OK; if (res == SPIFFS_VIS_END) res = SPIFFS_OK;
SPIFFS_CHECK_RES(res); SPIFFS_CHECK_RES(res);

View File

@ -124,7 +124,7 @@
#define SPIFFS_EV_IX_NEW 1 #define SPIFFS_EV_IX_NEW 1
#define SPIFFS_EV_IX_DEL 2 #define SPIFFS_EV_IX_DEL 2
#define SPIFFS_OBJ_ID_IX_FLAG (1<<(8*sizeof(spiffs_obj_id)-1)) #define SPIFFS_OBJ_ID_IX_FLAG ((spiffs_obj_id)(1<<(8*sizeof(spiffs_obj_id)-1)))
#define SPIFFS_UNDEFINED_LEN (u32_t)(-1) #define SPIFFS_UNDEFINED_LEN (u32_t)(-1)
@ -311,6 +311,26 @@
// stop searching at end of all look up pages // stop searching at end of all look up pages
#define SPIFFS_VIS_NO_WRAP (1<<2) #define SPIFFS_VIS_NO_WRAP (1<<2)
#if SPIFFS_HAL_CALLBACK_EXTRA
#define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
(_fs)->cfg.hal_write_f((_fs), (_paddr), (_len), (_src))
#define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
(_fs)->cfg.hal_read_f((_fs), (_paddr), (_len), (_dst))
#define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
(_fs)->cfg.hal_erase_f((_fs), (_paddr), (_len))
#else // SPIFFS_HAL_CALLBACK_EXTRA
#define SPIFFS_HAL_WRITE(_fs, _paddr, _len, _src) \
(_fs)->cfg.hal_write_f((_paddr), (_len), (_src))
#define SPIFFS_HAL_READ(_fs, _paddr, _len, _dst) \
(_fs)->cfg.hal_read_f((_paddr), (_len), (_dst))
#define SPIFFS_HAL_ERASE(_fs, _paddr, _len) \
(_fs)->cfg.hal_erase_f((_paddr), (_len))
#endif // SPIFFS_HAL_CALLBACK_EXTRA
#if SPIFFS_CACHE #if SPIFFS_CACHE
#define SPIFFS_CACHE_FLAG_DIRTY (1<<0) #define SPIFFS_CACHE_FLAG_DIRTY (1<<0)
@ -423,7 +443,7 @@ typedef struct __attribute(( packed ))
// common page header // common page header
spiffs_page_header p_hdr; spiffs_page_header p_hdr;
// alignment // alignment
u8_t _align[4 - (sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3)]; u8_t _align[4 - ((sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3))];
// size of object // size of object
u32_t size; u32_t size;
// type of object // type of object
@ -435,7 +455,7 @@ typedef struct __attribute(( packed ))
// object index page header // object index page header
typedef struct __attribute(( packed )) { typedef struct __attribute(( packed )) {
spiffs_page_header p_hdr; spiffs_page_header p_hdr;
u8_t _align[4 - (sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3)]; u8_t _align[4 - ((sizeof(spiffs_page_header)&3)==0 ? 4 : (sizeof(spiffs_page_header)&3))];
} spiffs_page_object_ix; } spiffs_page_object_ix;
// callback func for object lookup visitor // callback func for object lookup visitor
@ -665,7 +685,7 @@ s32_t spiffs_gc_clean(
spiffs_block_ix bix); spiffs_block_ix bix);
s32_t spiffs_gc_quick( s32_t spiffs_gc_quick(
spiffs *fs); spiffs *fs, u16_t max_free_pages);
// --------------- // ---------------

View File

@ -239,7 +239,7 @@ public:
size_t position() const override { size_t position() const override {
CHECKFD(); CHECKFD();
auto result = SPIFFS_tell(_fs->getFs(), _fd); auto result = SPIFFS_lseek(_fs->getFs(), _fd, 0, SPIFFS_SEEK_CUR);
if (result < 0) { if (result < 0) {
DEBUGV("SPIFFS_tell rc=%d\r\n", result); DEBUGV("SPIFFS_tell rc=%d\r\n", result);
return 0; return 0;
@ -308,6 +308,13 @@ public:
return (const char*) _dirent.name; return (const char*) _dirent.name;
} }
size_t fileSize() override {
if (!_valid)
return 0;
return _dirent.size;
}
bool next() override { bool next() override {
spiffs_dirent* result = SPIFFS_readdir(&_dir, &_dirent); spiffs_dirent* result = SPIFFS_readdir(&_dir, &_dirent);
_valid = (result != nullptr); _valid = (result != nullptr);