mirror of
https://github.com/pellepl/spiffs.git
synced 2025-05-20 00:36:06 +08:00
upped version: doc fixing, check fixing, commenting, config restructuring
This commit is contained in:
9
README
9
README
@ -1,5 +1,5 @@
|
|||||||
SPIFFS (SPI Flash File System)
|
SPIFFS (SPI Flash File System)
|
||||||
V0.1
|
V0.2
|
||||||
|
|
||||||
Copyright (c) 2013 Peter Andersson (pelleplutt1976<at>gmail.com)
|
Copyright (c) 2013 Peter Andersson (pelleplutt1976<at>gmail.com)
|
||||||
|
|
||||||
@ -15,7 +15,7 @@ Love to hear feedback though!
|
|||||||
Spiffs is a file system intended for SPI NOR flash devices on embedded targets.
|
Spiffs is a file system intended for SPI NOR flash devices on embedded targets.
|
||||||
|
|
||||||
Spiffs is designed with following characteristics in mind:
|
Spiffs is designed with following characteristics in mind:
|
||||||
- Small (embedded) targets, sparse RAM
|
- Small (embedded) targets, sparse RAM without heap
|
||||||
- Only big areas of data (blocks) can be erased
|
- Only big areas of data (blocks) can be erased
|
||||||
- An erase will reset all bits in block to ones
|
- An erase will reset all bits in block to ones
|
||||||
- Writing pulls one to zeroes
|
- Writing pulls one to zeroes
|
||||||
@ -26,6 +26,8 @@ Spiffs is designed with following characteristics in mind:
|
|||||||
* FEATURES
|
* FEATURES
|
||||||
|
|
||||||
What spiffs does:
|
What spiffs does:
|
||||||
|
- Specifically designed for low ram usage
|
||||||
|
- Uses statically sized ram buffers, independent of number of files
|
||||||
- Posix-like api: open, close, read, write, seek, stat, etc
|
- Posix-like api: open, close, read, write, seek, stat, etc
|
||||||
- It can be run on any NOR flash, not only SPI flash - theoretically also on
|
- It can be run on any NOR flash, not only SPI flash - theoretically also on
|
||||||
embedded flash of an microprocessor
|
embedded flash of an microprocessor
|
||||||
@ -33,8 +35,7 @@ What spiffs does:
|
|||||||
SPI flash device
|
SPI flash device
|
||||||
- Implements static wear leveling
|
- Implements static wear leveling
|
||||||
- Built in file system consistency checks
|
- Built in file system consistency checks
|
||||||
- Specifically designed for low ram usage
|
|
||||||
|
|
||||||
What spiffs does not:
|
What spiffs does not:
|
||||||
- Presently, spiffs does not support directories. It produces a flat
|
- Presently, spiffs does not support directories. It produces a flat
|
||||||
structure. Creating a file with path "tmp/myfile.txt" will create a file
|
structure. Creating a file with path "tmp/myfile.txt" will create a file
|
||||||
|
@ -90,7 +90,7 @@ define the SPI flash access functions:
|
|||||||
|
|
||||||
spiffs_config.hal_erase_f - pointing to the function erasing the SPI flash
|
spiffs_config.hal_erase_f - pointing to the function erasing the SPI flash
|
||||||
|
|
||||||
Depending on the build config - if SPIFFS_SINGLETON is undefined - following
|
Depending on the build config - if SPIFFS_SINGLETON is set to zero - following
|
||||||
parameters must be defined:
|
parameters must be defined:
|
||||||
|
|
||||||
spiffs_config.phys_size - the physical number of bytes accounted for
|
spiffs_config.phys_size - the physical number of bytes accounted for
|
||||||
@ -102,9 +102,13 @@ parameters must be defined:
|
|||||||
on the SPI flash found within the spiffs
|
on the SPI flash found within the spiffs
|
||||||
usage address space
|
usage address space
|
||||||
|
|
||||||
spiffs_config.log_block_size -
|
spiffs_config.log_block_size - the logical size of a spiffs block
|
||||||
|
|
||||||
|
spiffs_config.log_page_size - the logical size of a spiffs page
|
||||||
|
|
||||||
|
If SPIFFS_SINGLETON is set to one, above parameters must be set ny defines in
|
||||||
|
the config header file.
|
||||||
|
|
||||||
spiffs_config.log_page_size -
|
|
||||||
|
|
||||||
** Build config
|
** Build config
|
||||||
|
|
||||||
@ -117,6 +121,7 @@ be typedeffed.
|
|||||||
spiffs_config.h: you also need to define a spiffs_config.h header. Example of
|
spiffs_config.h: you also need to define a spiffs_config.h header. Example of
|
||||||
this is found in the default/ directory.
|
this is found in the default/ directory.
|
||||||
|
|
||||||
|
|
||||||
** RAM
|
** RAM
|
||||||
|
|
||||||
Spiffs needs ram. It needs a working buffer being double the size of the
|
Spiffs needs ram. It needs a working buffer being double the size of the
|
||||||
@ -144,7 +149,7 @@ you point out these files in your make script for compilation.
|
|||||||
|
|
||||||
Also copy the spiffs_config.h over from the default/ folder.
|
Also copy the spiffs_config.h over from the default/ folder.
|
||||||
|
|
||||||
Try buliding. This fails, nagging about inclusions and u32_t and whatnot. Open
|
Try building. This fails, nagging about inclusions and u32_t and whatnot. Open
|
||||||
the spiffs_config.h and delete the bad inclusions. Also, add following
|
the spiffs_config.h and delete the bad inclusions. Also, add following
|
||||||
typedefs:
|
typedefs:
|
||||||
|
|
||||||
|
@ -228,9 +228,9 @@ would look like this:
|
|||||||
|
|
||||||
PAGE 0 [ 12 12 545 12 *12 34 34 *4 0 0 0 0 ...]
|
PAGE 0 [ 12 12 545 12 *12 34 34 *4 0 0 0 0 ...]
|
||||||
|
|
||||||
where the asterisk means the msb is set.
|
where the asterisk means the msb of the object id is set.
|
||||||
|
|
||||||
This is another way to speed up the searches when looking for object indices.
|
This is another way to speed up the searches when looking for object indices.
|
||||||
By looking on the object id's msb in the object lookup, it is also possible
|
By looking on the object id's msb in the object lookup, it is also possible
|
||||||
whether the page is an object index page or a data page.
|
to find out whether the page is an object index page or a data page.
|
||||||
|
|
||||||
|
@ -20,33 +20,40 @@
|
|||||||
|
|
||||||
// compile time switches
|
// compile time switches
|
||||||
|
|
||||||
// set generic spiffs debug output
|
// Set generic spiffs debug output call.
|
||||||
#define SPIFFS_DBG(...)
|
#define SPIFFS_DBG(...)
|
||||||
// set spiffs debug output for garbage collecting
|
// Set spiffs debug output call for garbage collecting.
|
||||||
#define SPIFFS_GC_DBG(...)
|
#define SPIFFS_GC_DBG(...)
|
||||||
// set spiffs debug output for caching
|
// Set spiffs debug output call for caching.
|
||||||
#define SPIFFS_CACHE_DBG(...)
|
#define SPIFFS_CACHE_DBG(...)
|
||||||
// set spiffs debug output for system consistency checks
|
// Set spiffs debug output call for system consistency checks.
|
||||||
#define SPIFFS_CHECK_DBG(...)
|
#define SPIFFS_CHECK_DBG(...)
|
||||||
|
|
||||||
// define maximum number of gc runs to perform to reach desired free pages
|
// Enable/disable API functions to determine exact number of bytes
|
||||||
#define SPIFFS_GC_MAX_RUNS 3
|
// for filedescriptor and cache buffers. Once decided for a configuration,
|
||||||
// enable/disable statistics on gc
|
// this can be disabled to reduce flash.
|
||||||
#define SPIFFS_GC_STATS 1
|
#define SPIFFS_BUFFER_HELP 0
|
||||||
|
|
||||||
// enables/disable memory read caching of nucleus file system operations
|
// Enables/disable memory read caching of nucleus file system operations.
|
||||||
// if enabled, memory area must be provided for cache in SPIFFS_init
|
// If enabled, memory area must be provided for cache in SPIFFS_mount.
|
||||||
#define SPIFFS_CACHE 1
|
#define SPIFFS_CACHE 1
|
||||||
#if SPIFFS_CACHE
|
#if SPIFFS_CACHE
|
||||||
// enables memory write caching for file descriptors in hydrogen
|
// Enables memory write caching for file descriptors in hydrogen
|
||||||
#define SPIFFS_CACHE_WR 1
|
#define SPIFFS_CACHE_WR 1
|
||||||
// enable/disable statistics on caching
|
// Enable/disable statistics on caching. Debug/test purpose only.
|
||||||
#define SPIFFS_CACHE_STATS 1
|
#define SPIFFS_CACHE_STATS 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// checks header of each accessed page to validate state
|
// Always check header of each accessed page to ensure consistent state.
|
||||||
|
// If enabled it will increase number of reads, will increase flash.
|
||||||
#define SPIFFS_PAGE_CHECK 1
|
#define SPIFFS_PAGE_CHECK 1
|
||||||
|
|
||||||
|
// Define maximum number of gc runs to perform to reach desired free pages.
|
||||||
|
#define SPIFFS_GC_MAX_RUNS 3
|
||||||
|
|
||||||
|
// Enable/disable statistics on gc. Debug/test purpose only.
|
||||||
|
#define SPIFFS_GC_STATS 1
|
||||||
|
|
||||||
// Garbage collecting examines all pages in a block which and sums up
|
// Garbage collecting examines all pages in a block which and sums up
|
||||||
// to a block score. Deleted pages normally gives positive score and
|
// to a block score. Deleted pages normally gives positive score and
|
||||||
// used pages normally gives a negative score (as these must be moved).
|
// used pages normally gives a negative score (as these must be moved).
|
||||||
@ -55,22 +62,24 @@
|
|||||||
// The larger the score, the more likely it is that the block will
|
// The larger the score, the more likely it is that the block will
|
||||||
// picked for garbage collection.
|
// picked for garbage collection.
|
||||||
|
|
||||||
// garbage collecting heuristics - weight used for deleted pages
|
// Farbage collecting heuristics - weight used for deleted pages.
|
||||||
#define SPIFFS_GC_HEUR_W_DELET (10)
|
#define SPIFFS_GC_HEUR_W_DELET (10)
|
||||||
// garbage collecting heuristics - weight used for used pages
|
// Farbage collecting heuristics - weight used for used pages.
|
||||||
#define SPIFFS_GC_HEUR_W_USED (-1)
|
#define SPIFFS_GC_HEUR_W_USED (-1)
|
||||||
// garbage collecting heuristics - weight used for time between
|
// Farbage collecting heuristics - weight used for time between
|
||||||
// last erased and erase of this block
|
// last erased and erase of this block.
|
||||||
#define SPIFFS_GC_HEUR_W_ERASE_AGE (30)
|
#define SPIFFS_GC_HEUR_W_ERASE_AGE (30)
|
||||||
|
|
||||||
// object name length
|
// Object name maximum length.
|
||||||
#define SPIFFS_OBJ_NAME_LEN (32 - sizeof(spiffs_obj_type))
|
#define SPIFFS_OBJ_NAME_LEN (32)
|
||||||
|
|
||||||
// size of buffer on stack used when copying data
|
// Size of buffer allocated on stack used when copying data.
|
||||||
|
// Lower value generates more read/writes. No meaning having it bigger
|
||||||
|
// than logical page size.
|
||||||
#define SPIFFS_COPY_BUFFER_STACK (64)
|
#define SPIFFS_COPY_BUFFER_STACK (64)
|
||||||
|
|
||||||
// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level
|
// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level
|
||||||
// These must be defined on a multithreaded system
|
// These should be defined on a multithreaded system
|
||||||
|
|
||||||
// define this to entering a mutex if you're running on a multithreaded system
|
// define this to entering a mutex if you're running on a multithreaded system
|
||||||
#define SPIFFS_LOCK(fs)
|
#define SPIFFS_LOCK(fs)
|
||||||
@ -79,12 +88,13 @@
|
|||||||
|
|
||||||
|
|
||||||
// Enable if only one spiffs instance with constant configuration will exist
|
// Enable if only one spiffs instance with constant configuration will exist
|
||||||
// on the target, this will reduce calculations, flash and memory accesses.
|
// on the target. This will reduce calculations, flash and memory accesses.
|
||||||
|
// Parts of configuration must be defined below instead of at time of mount.
|
||||||
#define SPIFFS_SINGLETON 0
|
#define SPIFFS_SINGLETON 0
|
||||||
|
|
||||||
#if SPIFFS_SINGLETON
|
#if SPIFFS_SINGLETON
|
||||||
// instead of giving parameters in config struct, singleton build must
|
// Instead of giving parameters in config struct, singleton build must
|
||||||
// give parameters in defines below
|
// give parameters in defines below.
|
||||||
#define SPIFFS_CFG_PHYS_SZ(ignore) (1024*1024*2)
|
#define SPIFFS_CFG_PHYS_SZ(ignore) (1024*1024*2)
|
||||||
#define SPIFFS_CFG_PHYS_ERASE_SZ(ignore) (65536)
|
#define SPIFFS_CFG_PHYS_ERASE_SZ(ignore) (65536)
|
||||||
#define SPIFFS_CFG_PHYS_ADDR(ignore) (0)
|
#define SPIFFS_CFG_PHYS_ADDR(ignore) (0)
|
||||||
@ -108,24 +118,24 @@
|
|||||||
#define SPIFFS_TEST_VIS_DATA_STR(id) "d"
|
#define SPIFFS_TEST_VIS_DATA_STR(id) "d"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// types and constants
|
// Types depending on configuration such as the amount of flash bytes
|
||||||
|
// given to spiffs file system in total (spiffs_file_system_size),
|
||||||
|
// the logical block size (log_block_size), and the logical page size
|
||||||
|
// (log_page_size)
|
||||||
|
|
||||||
// spiffs file descriptor index type
|
// Block index type. Make sure the size of this type can hold
|
||||||
typedef s16_t spiffs_file;
|
// the highest number of all blocks - i.e. spiffs_file_system_size / log_block_size
|
||||||
// spiffs file descriptor flags
|
typedef u8_t spiffs_block_ix;
|
||||||
typedef u32_t spiffs_flags;
|
// Page index type. Make sure the size of this type can hold
|
||||||
// spiffs file mode
|
// the highest page number of all pages - i.e. spiffs_file_system_size / log_page_size
|
||||||
typedef u32_t spiffs_mode;
|
typedef u16_t spiffs_page_ix;
|
||||||
|
// Object id type - most significant bit is reserved for index flag. Make sure the
|
||||||
// block index type
|
// size of this type can hold the highest object id on a full system,
|
||||||
typedef u16_t spiffs_block_ix; // (address-phys_addr) / block_size
|
// i.e. 2 + (spiffs_file_system_size / (2*log_page_size))*2
|
||||||
// page index type
|
|
||||||
typedef u16_t spiffs_page_ix; // (address-phys_addr) / page_size
|
|
||||||
// object id type - most significant bit is reserved for index flag
|
|
||||||
typedef u16_t spiffs_obj_id;
|
typedef u16_t spiffs_obj_id;
|
||||||
// object span index type
|
// Object span index type. Make sure the size of this type can
|
||||||
|
// hold the largest possible span index on the system -
|
||||||
|
// i.e. (spiffs_file_system_size / log_page_size) - 1
|
||||||
typedef u16_t spiffs_span_ix;
|
typedef u16_t spiffs_span_ix;
|
||||||
// object type
|
|
||||||
typedef u8_t spiffs_obj_type;
|
|
||||||
|
|
||||||
#endif /* SPIFFS_CONFIG_H_ */
|
#endif /* SPIFFS_CONFIG_H_ */
|
||||||
|
29
src/spiffs.h
29
src/spiffs.h
@ -40,6 +40,15 @@
|
|||||||
#define SPIFFS_ERR_INTERNAL -10050
|
#define SPIFFS_ERR_INTERNAL -10050
|
||||||
|
|
||||||
|
|
||||||
|
// spiffs file descriptor index type. must be signed
|
||||||
|
typedef s16_t spiffs_file;
|
||||||
|
// spiffs file descriptor flags
|
||||||
|
typedef u16_t spiffs_flags;
|
||||||
|
// spiffs file mode
|
||||||
|
typedef u16_t spiffs_mode;
|
||||||
|
// object type
|
||||||
|
typedef u8_t spiffs_obj_type;
|
||||||
|
|
||||||
/* 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 */
|
||||||
@ -59,6 +68,7 @@ typedef enum {
|
|||||||
SPIFFS_CHECK_PROGRESS = 0,
|
SPIFFS_CHECK_PROGRESS = 0,
|
||||||
SPIFFS_CHECK_ERROR,
|
SPIFFS_CHECK_ERROR,
|
||||||
SPIFFS_CHECK_FIX_INDEX,
|
SPIFFS_CHECK_FIX_INDEX,
|
||||||
|
SPIFFS_CHECK_FIX_LOOKUP,
|
||||||
SPIFFS_CHECK_DELETE_ORPHANED_INDEX,
|
SPIFFS_CHECK_DELETE_ORPHANED_INDEX,
|
||||||
SPIFFS_CHECK_DELETE_PAGE,
|
SPIFFS_CHECK_DELETE_PAGE,
|
||||||
SPIFFS_CHECK_DELETE_BAD_FILE,
|
SPIFFS_CHECK_DELETE_BAD_FILE,
|
||||||
@ -386,4 +396,23 @@ s32_t SPIFFS_check(spiffs *fs);
|
|||||||
s32_t SPIFFS_vis(spiffs *fs);
|
s32_t SPIFFS_vis(spiffs *fs);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if SPIFFS_BUFFER_HELP
|
||||||
|
/**
|
||||||
|
* Returns number of bytes needed for the filedescriptor buffer given
|
||||||
|
* amount of file descriptors.
|
||||||
|
*/
|
||||||
|
u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs);
|
||||||
|
|
||||||
|
#if SPIFFS_CACHE
|
||||||
|
/**
|
||||||
|
* Returns number of bytes needed for the cache buffer given
|
||||||
|
* amount of cache pages.
|
||||||
|
*/
|
||||||
|
u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages);
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if SPIFFS_CHACHE
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif /* SPIFFS_H_ */
|
#endif /* SPIFFS_H_ */
|
||||||
|
@ -192,6 +192,9 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
|
|||||||
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);
|
||||||
|
} 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);
|
||||||
}
|
}
|
||||||
SPIFFS_CHECK_RES(res);
|
SPIFFS_CHECK_RES(res);
|
||||||
}
|
}
|
||||||
@ -211,6 +214,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);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
SPIFFS_CHECK_RES(res);
|
SPIFFS_CHECK_RES(res);
|
||||||
@ -248,6 +252,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
|
|||||||
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);
|
||||||
}
|
}
|
||||||
SPIFFS_CHECK_RES(res);
|
SPIFFS_CHECK_RES(res);
|
||||||
}
|
}
|
||||||
@ -299,6 +304,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);
|
||||||
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) ||
|
||||||
@ -307,6 +313,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);
|
||||||
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;
|
||||||
@ -344,6 +351,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 == 0) {
|
if (data_pix && objix_pix == 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);
|
||||||
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);
|
||||||
@ -359,6 +367,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) {
|
if (data_pix == 0 && objix_pix) {
|
||||||
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);
|
||||||
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);
|
||||||
@ -395,6 +404,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);
|
||||||
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),
|
||||||
@ -406,6 +416,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);
|
||||||
res = spiffs_page_delete(fs, cur_pix);
|
res = spiffs_page_delete(fs, cur_pix);
|
||||||
SPIFFS_CHECK_RES(res);
|
SPIFFS_CHECK_RES(res);
|
||||||
}
|
}
|
||||||
@ -582,8 +593,11 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
|||||||
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 %i, 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);
|
||||||
// delete file
|
// delete file
|
||||||
res = spiffs_page_delete(fs, cur_pix);
|
res = spiffs_page_delete(fs, cur_pix);
|
||||||
|
} 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);
|
||||||
}
|
}
|
||||||
SPIFFS_CHECK_RES(res);
|
SPIFFS_CHECK_RES(res);
|
||||||
restart = 1;
|
restart = 1;
|
||||||
@ -617,6 +631,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);
|
||||||
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;
|
||||||
@ -628,7 +643,10 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
|||||||
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 %i, 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);
|
||||||
res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
|
res = spiffs_delete_obj_lazy(fs, p_hdr.obj_id);
|
||||||
|
} 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);
|
||||||
}
|
}
|
||||||
SPIFFS_CHECK_RES(res);
|
SPIFFS_CHECK_RES(res);
|
||||||
restart = 1;
|
restart = 1;
|
||||||
@ -646,6 +664,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);
|
||||||
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
|
||||||
@ -740,15 +759,19 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
|
|||||||
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 %i, 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);
|
||||||
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 {
|
||||||
|
if (fs->check_cb_f) fs->check_cb_f(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);
|
||||||
res = spiffs_page_delete(fs, cur_pix);
|
res = spiffs_page_delete(fs, cur_pix);
|
||||||
}
|
}
|
||||||
SPIFFS_CHECK_RES(res);
|
SPIFFS_CHECK_RES(res);
|
||||||
|
@ -10,6 +10,16 @@
|
|||||||
|
|
||||||
static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh);
|
static s32_t spiffs_fflush_cache(spiffs *fs, spiffs_file fh);
|
||||||
|
|
||||||
|
#if SPIFFS_BUFFER_HELP
|
||||||
|
u32_t SPIFFS_buffer_bytes_for_filedescs(spiffs *fs, u32_t num_descs) {
|
||||||
|
return num_descs * sizeof(spiffs_fd);
|
||||||
|
}
|
||||||
|
#if SPIFFS_CACHE
|
||||||
|
u32_t SPIFFS_buffer_bytes_for_cache(spiffs *fs, u32_t num_pages) {
|
||||||
|
return sizeof(spiffs_cache) + num_pages * (sizeof(spiffs_cache_page) + SPIFFS_CFG_LOG_PAGE_SZ(fs));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
|
||||||
u8_t *fd_space, u32_t fd_space_size,
|
u8_t *fd_space, u32_t fd_space_size,
|
||||||
|
@ -18,8 +18,6 @@
|
|||||||
|
|
||||||
#define ASSERT(c, m) real_assert((c),(m), __FILE__, __LINE__);
|
#define ASSERT(c, m) real_assert((c),(m), __FILE__, __LINE__);
|
||||||
|
|
||||||
void real_assert(int c, const char *n, const char *file, int l);
|
|
||||||
|
|
||||||
typedef signed int s32_t;
|
typedef signed int s32_t;
|
||||||
typedef unsigned int u32_t;
|
typedef unsigned int u32_t;
|
||||||
typedef signed short s16_t;
|
typedef signed short s16_t;
|
||||||
@ -27,5 +25,6 @@ typedef unsigned short u16_t;
|
|||||||
typedef signed char s8_t;
|
typedef signed char s8_t;
|
||||||
typedef unsigned char u8_t;
|
typedef unsigned char u8_t;
|
||||||
|
|
||||||
|
void real_assert(int c, const char *n, const char *file, int l);
|
||||||
|
|
||||||
#endif /* PARAMS_TEST_H_ */
|
#endif /* PARAMS_TEST_H_ */
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
//#define REMOVE_LONG_TESTS
|
|
||||||
|
|
||||||
static void test_on_stop(test *t) {
|
static void test_on_stop(test *t) {
|
||||||
printf(" spiffs errno:%i\n", SPIFFS_errno(&__fs));
|
printf(" spiffs errno:%i\n", SPIFFS_errno(&__fs));
|
||||||
#if SPIFFS_TEST_VISUALISATION
|
#if SPIFFS_TEST_VISUALISATION
|
||||||
@ -1218,7 +1216,6 @@ TEST(lseek_read) {
|
|||||||
TEST_END(lseek_read)
|
TEST_END(lseek_read)
|
||||||
|
|
||||||
|
|
||||||
#ifndef REMOVE_LONG_TESTS
|
|
||||||
TEST(write_small_file_chunks_1)
|
TEST(write_small_file_chunks_1)
|
||||||
{
|
{
|
||||||
int res = test_create_and_write_file("smallfile", 256, 1);
|
int res = test_create_and_write_file("smallfile", 256, 1);
|
||||||
@ -1288,7 +1285,7 @@ TEST(write_big_files_chunks_1)
|
|||||||
return TEST_RES_OK;
|
return TEST_RES_OK;
|
||||||
}
|
}
|
||||||
TEST_END(write_big_files_chunks_1)
|
TEST_END(write_big_files_chunks_1)
|
||||||
#endif // REMOVE_LONG_TESTS
|
|
||||||
|
|
||||||
TEST(long_run_config_many_small_one_long)
|
TEST(long_run_config_many_small_one_long)
|
||||||
{
|
{
|
||||||
@ -1530,20 +1527,30 @@ TEST(long_run)
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
int macro_runs = 1000;
|
int macro_runs = 500;
|
||||||
printf(" ");
|
printf(" ");
|
||||||
|
u32_t clob_size = SPIFFS_CFG_PHYS_SZ(FS)/4;
|
||||||
|
int res = test_create_and_write_file("long_clobber", clob_size, clob_size);
|
||||||
|
TEST_CHECK(res >= 0);
|
||||||
|
|
||||||
|
res = read_and_verify("long_clobber");
|
||||||
|
TEST_CHECK(res >= 0);
|
||||||
|
|
||||||
while (macro_runs--) {
|
while (macro_runs--) {
|
||||||
//printf(" ---- run %i ----\n", macro_runs);
|
//printf(" ---- run %i ----\n", macro_runs);
|
||||||
if ((macro_runs % 20) == 0) {
|
if ((macro_runs % 20) == 0) {
|
||||||
printf(".");
|
printf(".");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
int res = run_file_config(sizeof(cfgs)/sizeof(cfgs[0]), &cfgs[0], 11, 2, 0);
|
res = run_file_config(sizeof(cfgs)/sizeof(cfgs[0]), &cfgs[0], 11, 2, 0);
|
||||||
TEST_CHECK(res >= 0);
|
TEST_CHECK(res >= 0);
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
int res = SPIFFS_check(FS);
|
res = read_and_verify("long_clobber");
|
||||||
|
TEST_CHECK(res >= 0);
|
||||||
|
|
||||||
|
res = SPIFFS_check(FS);
|
||||||
TEST_CHECK(res >= 0);
|
TEST_CHECK(res >= 0);
|
||||||
|
|
||||||
return TEST_RES_OK;
|
return TEST_RES_OK;
|
||||||
|
@ -296,7 +296,33 @@ static void spiffs_check_cb_f(spiffs_check_type type, spiffs_check_report report
|
|||||||
printf("%i%%\n", arg1 * 100 / 256);
|
printf("%i%%\n", arg1 * 100 / 256);
|
||||||
}*/
|
}*/
|
||||||
if (report != SPIFFS_CHECK_PROGRESS) {
|
if (report != SPIFFS_CHECK_PROGRESS) {
|
||||||
printf(" check cb f: %i %i %08x (%i) %08x\n", type, report, arg1, arg1, arg2);
|
printf(" check: ");
|
||||||
|
switch (type) {
|
||||||
|
case SPIFFS_CHECK_INDEX:
|
||||||
|
printf("INDEX "); break;
|
||||||
|
case SPIFFS_CHECK_LOOKUP:
|
||||||
|
printf("LOOKUP "); break;
|
||||||
|
case SPIFFS_CHECK_PAGE:
|
||||||
|
printf("PAGE "); break;
|
||||||
|
default:
|
||||||
|
printf("???? "); break;
|
||||||
|
}
|
||||||
|
if (report == SPIFFS_CHECK_ERROR) {
|
||||||
|
printf("ERROR %i", arg1);
|
||||||
|
} else if (report == SPIFFS_CHECK_DELETE_BAD_FILE) {
|
||||||
|
printf("DELETE BAD FILE %04x", arg1);
|
||||||
|
} else if (report == SPIFFS_CHECK_DELETE_ORPHANED_INDEX) {
|
||||||
|
printf("DELETE ORPHANED INDEX %04x", arg1);
|
||||||
|
} else if (report == SPIFFS_CHECK_DELETE_PAGE) {
|
||||||
|
printf("DELETE PAGE %04x", arg1);
|
||||||
|
} else if (report == SPIFFS_CHECK_FIX_INDEX) {
|
||||||
|
printf("FIX INDEX %04x:%04x", arg1, arg2);
|
||||||
|
} else if (report == SPIFFS_CHECK_FIX_LOOKUP) {
|
||||||
|
printf("FIX INDEX %04x:%04x", arg1, arg2);
|
||||||
|
} else {
|
||||||
|
printf("??");
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user