Make magic dependent on fs length, if needed. (see #59 & #66)

This will also add possibility to probe the filesystems length
beforehand to fully mounting it.

Thanks @hreintke.

Added API funcs:
  SPIFFS_probe_nbr_of_blocks

Added config:
  SPIFFS_USE_MAGIC_LENGTH
This commit is contained in:
Peter Andersson
2016-01-24 22:12:07 +01:00
parent 5183bf423b
commit ac33a755a2
7 changed files with 162 additions and 5 deletions
+11 -1
View File
@@ -119,6 +119,17 @@
#define SPIFFS_USE_MAGIC (0)
#endif
#if SPIFFS_USE_MAGIC
// Only valid when SPIFFS_USE_MAGIC is enabled. If SPIFFS_USE_MAGIC_LENGTH is
// enabled, the magic will also be dependent on the length of the filesystem.
// For example, a filesystem configured and formatted for 4 megabytes will not
// be accepted for mounting with a configuration defining the filesystem as 2
// megabytes.
#ifndef SPIFFS_USE_MAGIC_LENGTH
#define SPIFFS_USE_MAGIC_LENGTH (0)
#endif
#endif
// SPIFFS_LOCK and SPIFFS_UNLOCK protects spiffs from reentrancy on api level
// These should be defined on a multithreaded system
@@ -131,7 +142,6 @@
#define SPIFFS_UNLOCK(fs)
#endif
// Enable if only one spiffs instance with constant configuration will exist
// on the target. This will reduce calculations, flash and memory accesses.
// Parts of configuration must be defined below instead of at time of mount.
+27
View File
@@ -282,6 +282,33 @@ typedef struct {
// functions
#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
/**
* Special function. This takes a spiffs config struct and returns
* the number of blocks this file system was formatted with.
* This function relies on following in the passed config struct:
* hal_read_f, phys_addr, and log_page_size.
*
* Do note, that caution should be taken with the value returned here.
*
* There is no check whatsoever that the flash actually contains a file
* system - meaning that just any number could be returned.
*
* There is neither any check that the configuration is set correctly.
* The block size may for instance differ.
*
* One must be sure of the page size and the physical address when
* calling this function.
*
* The resulting value can then be used to set the config structs
* phys_size by multiplying it with the known block size.
*
* @param config essential parts of the physical and logical
* configuration of the file system
*/
s32_t SPIFFS_probe_nbr_of_blocks(spiffs_config *config);
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
/**
* Initializes the file system dynamic parameters and mounts the filesystem.
* If SPIFFS_USE_MAGIC is enabled the mounting may fail with SPIFFS_ERR_NOT_A_FS
+11
View File
@@ -61,6 +61,17 @@ s32_t SPIFFS_format(spiffs *fs) {
return 0;
}
#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
s32_t SPIFFS_probe_nbr_of_blocks(spiffs_config *config) {
SPIFFS_LOCK(fs);
s32_t block_count = spiffs_probe(config);
SPIFFS_UNLOCK(fs);
return block_count;
}
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
u8_t *fd_space, u32_t fd_space_size,
void *cache, u32_t cache_size,
+26 -2
View File
@@ -243,7 +243,7 @@ s32_t spiffs_erase_block(
#if SPIFFS_USE_MAGIC
// finally, write magic
spiffs_obj_id magic = SPIFFS_MAGIC(fs);
spiffs_obj_id magic = SPIFFS_MAGIC(fs, bix);
res = _spiffs_wr(fs, SPIFFS_OP_C_WRTHRU | SPIFFS_OP_T_OBJ_LU2, 0,
SPIFFS_MAGIC_PADDR(fs, bix),
sizeof(spiffs_obj_id), (u8_t *)&magic);
@@ -259,6 +259,30 @@ s32_t spiffs_erase_block(
}
#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
s32_t spiffs_probe(
spiffs_config *cfg) {
s32_t res;
spiffs dummy_fs; // create a dummy fs struct just to be able to use macros
memcpy(&dummy_fs.cfg, cfg, sizeof(spiffs_config));
spiffs_obj_id magic;
u32_t paddr = SPIFFS_MAGIC_PADDR(&dummy_fs, (spiffs_block_ix)0);
#if SPIFFS_HAL_CALLBACK_EXTRA
// not any proper fs to report here, so callback with null
// (cross fingers that no-one gets angry)
res = cfg->hal_read_f((void *)0, paddr, sizeof(spiffs_obj_id), (u8_t *)&magic);
#else
res = cfg->hal_read_f(paddr, sizeof(spiffs_obj_id), (u8_t *)&magic);
#endif
SPIFFS_CHECK_RES(res);
// unwind the magic crap to get nbr of blocks
dummy_fs.block_count = 0;
return SPIFFS_MAGIC(&dummy_fs, 0) ^ magic;
}
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
static s32_t spiffs_obj_lu_scan_v(
spiffs *fs,
spiffs_obj_id obj_id,
@@ -311,7 +335,7 @@ s32_t spiffs_obj_lu_scan(
sizeof(spiffs_obj_id), (u8_t *)&magic);
SPIFFS_CHECK_RES(res);
if (magic != SPIFFS_MAGIC(fs)) {
if (magic != SPIFFS_MAGIC(fs, bix)) {
if (unerased_bix == (spiffs_block_ix)-1) {
// allow one unerased block as it might be powered down during an erase
unerased_bix = bix;
+14 -1
View File
@@ -131,7 +131,15 @@
#define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
#define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1)
#define SPIFFS_MAGIC(fs) ((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs)))
#if SPIFFS_USE_MAGIC
#if !SPIFFS_USE_MAGIC_LENGTH
#define SPIFFS_MAGIC(fs, bix) \
((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs)))
#else // SPIFFS_USE_MAGIC_LENGTH
#define SPIFFS_MAGIC(fs, bix) \
((spiffs_obj_id)(0x20140529 ^ SPIFFS_CFG_LOG_PAGE_SZ(fs) ^ ((fs)->block_count - (bix))))
#endif // SPIFFS_USE_MAGIC_LENGTH
#endif // SPIFFS_USE_MAGIC
#define SPIFFS_CONFIG_MAGIC (0x20090315)
@@ -530,6 +538,11 @@ s32_t spiffs_erase_block(
spiffs *fs,
spiffs_block_ix bix);
#if SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
s32_t spiffs_probe(
spiffs_config *cfg);
#endif // SPIFFS_USE_MAGIC && SPIFFS_USE_MAGIC_LENGTH
// ---------------
s32_t spiffs_obj_lu_scan(
+3 -1
View File
@@ -16,7 +16,9 @@
#define SPIFFS_PHYS_ADDR (4*1024*1024)
// test using filesystem magic
//#define SPIFFS_USE_MAGIC 1
#define SPIFFS_USE_MAGIC 1
// test using filesystem magic length
#define SPIFFS_USE_MAGIC_LENGTH 1
#define SECTOR_SIZE 65536
#define LOG_BLOCK (SECTOR_SIZE*2)
+70
View File
@@ -35,6 +35,76 @@ TEST(info)
}
TEST_END(info)
#if SPIFFS_USE_MAGIC
TEST(magic)
{
fs_reset_specific(0, 0, 65536*16, 65536, 65536, 256);
SPIFFS_unmount(FS);
TEST_CHECK_EQ(fs_mount_specific(0, 65536*16, 65536, 65536, 256), SPIFFS_OK);
SPIFFS_unmount(FS);
TEST_CHECK_NEQ(fs_mount_specific(0, 65536*16, 65536, 65536, 128), SPIFFS_OK);
TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS);
TEST_CHECK_NEQ(fs_mount_specific(4, 65536*16, 65536, 65536, 256), SPIFFS_OK);
TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS);
return TEST_RES_OK;
}
TEST_END(magic)
#if SPIFFS_USE_MAGIC_LENGTH
TEST(magic_length)
{
fs_reset_specific(0, 0, 65536*16, 65536, 65536, 256);
SPIFFS_unmount(FS);
TEST_CHECK_EQ(fs_mount_specific(0, 65536*16, 65536, 65536, 256), SPIFFS_OK);
SPIFFS_unmount(FS);
TEST_CHECK_NEQ(fs_mount_specific(0, 65536*8, 65536, 65536, 256), SPIFFS_OK);
TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS);
TEST_CHECK_NEQ(fs_mount_specific(0, 65536*15, 65536, 65536, 256), SPIFFS_OK);
TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS);
TEST_CHECK_NEQ(fs_mount_specific(0, 65536*17, 65536, 65536, 256), SPIFFS_OK);
TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS);
TEST_CHECK_NEQ(fs_mount_specific(0, 65536*256, 65536, 65536, 256), SPIFFS_OK);
TEST_CHECK_EQ(SPIFFS_errno(FS), SPIFFS_ERR_NOT_A_FS);
return TEST_RES_OK;
}
TEST_END(magic_length)
TEST(magic_length_probe)
{
fs_reset_specific(0, 0, 65536*16, 65536, 65536, 256);
TEST_CHECK_EQ(SPIFFS_probe_nbr_of_blocks(&__fs.cfg), 16);
fs_reset_specific(0, 0, 65536*24, 65536, 65536, 256);
TEST_CHECK_EQ(SPIFFS_probe_nbr_of_blocks(&__fs.cfg), 24);
fs_reset_specific(0, 0, 32768*16, 32768, 32768, 128);
TEST_CHECK_EQ(SPIFFS_probe_nbr_of_blocks(&__fs.cfg), 16);
fs_reset_specific(0, 0, 16384*37, 16384, 16384, 128);
TEST_CHECK_EQ(SPIFFS_probe_nbr_of_blocks(&__fs.cfg), 37);
fs_reset_specific(0, 0, 4096*11, 4096, 4096, 256);
TEST_CHECK_EQ(SPIFFS_probe_nbr_of_blocks(&__fs.cfg), 11);
return TEST_RES_OK;
}
TEST_END(magic_length_probe)
#endif // SPIFFS_USE_MAGIC_LENGTH
#endif // SPIFFS_USE_MAGIC
TEST(missing_file)
{